⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em_dma.pm

📁 altera_avalon_dma.rar大家快下啊
💻 PM
📖 第 1 页 / 共 5 页
字号:
use europa_all;use europa_utils;use e_avalon_master;use e_fsm;use strict;my $p4_revision = '$Revision: #1 $';my $p4_datetime = '$DateTime: 2005/08/05 18:28:42 $';$p4_revision =~ /#(\d+)/;my $revision = $1;my $read_master_name = "read_master";my $write_master_name = "write_master";my $control_port_name = "control_port_slave";my @all_transactions = qw(  quadword  doubleword  word  hw  byte);sub control_register{  my ($comment,      $name,      $width,      $condition,      $data,      $else_if,      $else_event,      $reset_value) = @_;  # If there's nothing to do, return an empty list.  return () if ($width == 0);  # Fix up the reset value with the proper width.  $reset_value =~ s/^[0-9]*\'h/$width\'h/;  # Make a table for my mux...  my @table = ($condition, $data);  if ($else_if)  {    push @table, ($else_if, $name . $else_event);  }  # ... a mux for my register input...    my $mux = e_mux->new({    lhs => e_signal->new(["p1_$name",]),    table          => \@table,    type           => "priority",    default => $name,  });  # ... and a register.    my $reg = e_register->new({    comment => $comment,    in => "p1_$name",    out => e_signal->new({name => $name, width => $width}),    async_value => $reset_value,  });  return ($reg, $mux);}sub get_slave_port_data_width{  # Find the max width value over all register descriptors.    return max(map {$_->[2]} get_slave_port_registers(@_));}sub get_slave_port_addr_width{  my @registers = get_slave_port_registers(@_);  my $addr_width = ceil(log2(0 + @registers));  return $addr_width;}sub get_max_transaction_size_in_bits{  my @trans = reverse get_transaction_size_bit_names();  my $size = 8;  @trans = map {    my $this_size = $size; $size *= 2; {trans => $_, size => $this_size}  } @trans;  my $max_size = -1;  map {$max_size = $_->{size} if is_transaction_allowed($_->{trans})} @trans;  ribbit("no possible transactions!") if $max_size == -1;  return $max_size;}# Transaction bit names, in a list with the least-significant bit# (the one encoding "byte" transaction") in the last position.sub get_transaction_size_bit_names{  return @all_transactions;}# We're interested in the indices of the control bits that encode the# transaction size in a few places, so here's a handy function.# # Bit indices are turned in a list with the least-significant bit# (the one encoding "byte" transaction") in the last position.sub get_transaction_size_bit_indices{  return get_slave_port_bits('control', get_transaction_size_bit_names());}# get_transaction_size_expression()# Get the list of control bit indices, least-significant ("byte") last;# form the expression of the associated control bit in the control register;# return the concatenation of all such control bits.# # The returned expression is appropriate for use as a number, namely a# read- or write-master address increment or length register decrement.# # Optimization: if the user promised to use any transaction sizes, exclude# their control bits.sub get_transaction_size_expression{  return concatenate(    map {is_transaction_allowed($_) ? $_ : "1'b0"}    get_transaction_size_bit_names()  );}sub get_slave_port_registers{  my $Options = shift;  # Historical note: registers "reserved1" and "reserved2" below  # used to be read and write increment override.  The list contents for  # those register positions was formerly:#   [" read master increment override",#     "readincov",#     $Options->{readincovwidth},#     "",#     "dma_ctl_writedata",#     "",#     "",#     0,#   ],#   [" write master increment override",#     "writeincov",#     $Options->{writeincovwidth},#     "",#     "dma_ctl_writedata",#     "",#     "",#     0,#   ],# Likewise, "reserved3" used to be "altcontrol".  Documenting that# register seems difficult, and it's likely of limited utility to# most people, so it's now renamed.#    [" control register alternate",#     "alt_control",#      $control_register_width,#      "",#      "dma_ctl_writedata",#      "",#      "",#      $control_default_reset_string,#    ],  # This function can be called at generate time in which case  # $Options is a hash of various useful things from the ptf file,  # or it can be called by generate_appurtenances, in which case  # $Options is undef.  # Here are the registers accessible from the slave port.  # Some of these widths depend on user choices/slave sizes, etc.  # But the status and control register widths are known.  Go inspect  # the bit defs to figure those widths out.  # [register_name, bit_name, bit_pos, comment]  # my @bits = get_slave_port_bit_definitions();  my @controlbits = get_control_bits();  my @statusbits =  get_status_bits();  my $control_register_width = 1 + max(map {$_->[2]} @controlbits);  my $status_register_width =  1 + max(map {$_->[2]} @statusbits);  my $transaction_size = get_transaction_size_expression();  # Go figure out a decent default reset value for the control register.  # I declare that the 'word' and 'leen' bits should be set.  my $control_default_reset_string = 0;  map {    $control_default_reset_string += (($_->[1] =~ /(^word$)|(leen)/) ? 1 << $_->[2] : 0)  } get_control_bits();  # Don't change the format of this table without first looking at all its  # dependencies!  my @reg_info = (    [" status register",      "status",      $status_register_width,      "",      "0",      "",      "",      0,    ],    [" read address",      "readaddress",      $Options->{readaddresswidth},      "",      "dma_ctl_writedata",      "inc_read",      " + readaddress_inc",      0,    ],    [" write address",      "writeaddress",      $Options->{writeaddresswidth},      "",      "dma_ctl_writedata",      "inc_write",      " + writeaddress_inc",      0,    ],    [" length in bytes",      "length",      # width should be no greater than the max address width, but at least      # as large as lengthwidth.      min(        $::g_max_address_width,        max(          $Options->{lengthwidth},          Bits_To_Encode($Options->{max_slave_address_span}),        ),      ),      "",      "dma_ctl_writedata",      "inc_read && (!length_eq_0)",      $Options->{burst_enable} ? " - length" : " - $transaction_size",      0,    ],    [" reserved",      "reserved1",      0,      "",      "dma_ctl_writedata",      "",      "",      0,    ],    [" reserved",      "reserved2",      0,      "",      "dma_ctl_writedata",      "",      "",      0,    ],    [" control register",      "control",      $control_register_width,      "",      "dma_ctl_writedata",      "",      "",      $control_default_reset_string,    ],    [" control register alternate",      "reserved3",      $control_register_width,      "",      "dma_ctl_writedata",      "",      "",      $control_default_reset_string,    ],  );  # If there are any over-ride reset values in Options, set them now.  # Meanwhile, fill in the write-condition expression, using the array  # position as register address.  my $index = 0;  my $control_reg_index = -1;  my $alt_control_reg_index = -1;  for my $reg_spec (@reg_info)  {    # Most registers have the following default write select.    $reg_spec->[3] =       "dma_ctl_chipselect & ~dma_ctl_write_n & (dma_ctl_address == $index)";    $control_reg_index = $index if ($reg_spec->[1] eq "control");    $alt_control_reg_index = $index if ($reg_spec->[1] eq "reserved3");    $index++;    my $name = $reg_spec->[1];    my $reset_value = $Options->{$name . "_reset_value"};    if (defined($reset_value))    {      # Reset values can be decimal or hex (0x...).  Perl's handy      # 'oct' function handles hex (starts with 0x) and octal (starts with 0).      $reset_value = eval($reset_value);      # $reset_value = oct($reset_value) if $reset_value =~ /^0/;      # The width is set to the max here; it'll be fixed up later.      $reg_spec->[7] = sprintf("%d'h%X", $::g_max_register_width, $reset_value);    }  }  ribbit ("can't find control register\n") if (-1 == $control_reg_index);  ribbit ("can't find alt_control register\n")    if (-1 == $alt_control_reg_index);  # Since I've decided to make an alternate control register, aliased  # to the control register, let writes to it go to the real control.  $reg_info[$control_reg_index]->[3] =     "dma_ctl_chipselect & ~dma_ctl_write_n & " .    "((dma_ctl_address == $control_reg_index) || " .    "(dma_ctl_address == $alt_control_reg_index))";  # Say, wouldn't it be handy to be able to specify reset values for  # control register bits by name?  If any such are found, they override  # the control register reset value.  my $cleared_bits = ~0;  # That is, all 1-bits.  my $set_bits = 0;  # Bleh.  Go grab the current reset value, and convert it back to a decimal  # number if necessary.  my $cur_reset = $reg_info[$control_reg_index]->[7];  $cur_reset =~ s/[0-9]*\'h/0x/g;  $cur_reset = eval($cur_reset);  my $i = 0;  for (get_control_bits())  {    my $bitname = $_->[1];      my $optionname = "control_" . $bitname . "_reset_value";    my $override_bit = $Options->{"control_" . $bitname . "_reset_value"};    if (defined($override_bit))    {      if ($override_bit)      {        $set_bits |= 1 << $i;      }      else      {        $cleared_bits &= ~(1 << $i);      }    }    $i++;  }  $cur_reset |= $set_bits;  $cur_reset &= $cleared_bits;  # A few sanity checks: I'm not going to enforce these at run-time, since  # that would cost logic, but I might as well prevent silly errors in the  # ptf-file reset values.  Why allow my gun to point directly at my foot?  # Only one of byte, hw, word  # should be true.  my @check_bits = get_transaction_size_bit_indices();  if (1 != grep {$cur_reset & (1 << $_)} @check_bits)  {    ribbit(      sprintf(        "Multiple bits set in bogus control register reset value 0x%X\n",        $cur_reset)    );  }  # The width is set to the max here; it'll be fixed up later.  $reg_info[$control_reg_index]->[7] =    sprintf("%d'h%X", $::g_max_register_width, $cur_reset);  return @reg_info;}sub get_control_bits{  my @control_bits = (    ["byte",                  "Byte transaction", ],    ["hw",                    "Half-word transaction", ],    ["word",                  "Word transaction", ],    ["go",                    "enable execution", ],    ["i_en",                  "enable interrupt", ],    ["reen",                  "Enable read end-of-packet", ],    ["ween",                  "Enable write end-of-packet", ],    ["leen",                  "Enable length=0 transaction end", ],    ["rcon",                  "Read from a fixed address", ],    ["wcon",                  "Write to a fixed address", ],    ["doubleword",            "Double-word transaction", ],    ["quadword",              "Quad-word transaction", ],    ["softwarereset",         "Software reset - write twice in succession to reset", ],  );  # Convert the above simple list into a list of listrefs of the form:  # [register name, bit name, bit position, comment].  my $i = 0;  return map {["control", $_->[0], $i++, $_->[1]]} @control_bits;}sub get_status_bits{  my @status_bits = (    [ "done",           "1 when done.  Status write clears.", ],    [ "busy",           "1 when busy.", ],    [ "reop",           "read-eop received",],    [ "weop",           "write-eop received",],    [ "len",            "requested length transacted",],  );  # Convert the above simple list into a list of listrefs of the form:  # [register name, bit name, bit position, comment].  my $i = 0;  return map {["status", $_->[0], $i++, $_->[1]]} @status_bits;}sub get_slave_port_bit_definitions{  # Bits within registers.  Each list element is a list ref  # of [register name, bit name, bit position, comment].  return (get_control_bits(), get_status_bits());  }# Look up a register and bit name(s) in the slave port# bit defs, and return their indices.sub get_slave_port_bits{  my ($reg_name, @bit_names) = @_;  my @bits = ();  my @reg_spec;  {    $reg_name eq "control" and do {@reg_spec = get_control_bits(); last;};    $reg_name eq "status"  and do {@reg_spec = get_status_bits();  last;};  }  ribbit("bad register-bit request '$reg_name'\n") if !@reg_spec;  # Where are map and grep when you need them?  for my $bit_name (@bit_names)  {    push @bits, (map {$_->[1] eq $bit_name ? $_->[2] : ()} @reg_spec);  }  return undef if (0 + @bits != @bit_names);    return @bits;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -