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

📄 em_dma.pm

📁 altera_avalon_dma.rar大家快下啊
💻 PM
📖 第 1 页 / 共 5 页
字号:
  my @contents = ();  my @muxtable;  # Get transaction bit names, least-significant first.  my @trans_bit_names = get_transaction_size_bit_names();  # Optimization alert: it sure seems that I ought to be able to drop the all-1's  # case from the byteenable mux.  for (my $trans_size = 1; $trans_size <= $num_byteenables; $trans_size <<= 1)  {    # Each time through this loop, push a pair of values into muxtable.    # Value 1: selector (simply the name of the transaction size bit for    # this transaction size).    # Value 2: an expression for the byteenable signal, depending on    # the address and the current transaction size.    my $trans_bit_name = pop @trans_bit_names;    ribbit("unexpected error") if !$trans_bit_name;    next if !is_transaction_allowed($trans_bit_name);    ribbit("ran out of transaction bit names!") if !$trans_bit_name;    my $be_expression;    # Log(multiplier) tells you how many address bits the elements of the     # byteenable expression depend on.    my $num_important_address_bits = log2($num_byteenables / $trans_size);    if ($num_important_address_bits == 0)    {      $be_expression =        sprintf("%d'b%s", $num_byteenables, '1' x $num_byteenables);    }    else    {      my @terms;      my $address_msb = log2($num_byteenables) - 1;      my $address_lsb = $address_msb - $num_important_address_bits + 1;      my $addr_sel =        $address_msb == $address_lsb ? "$address_msb" : "$address_msb : $address_lsb";      my $addr_sel_for_signal;      ($addr_sel_for_signal = $addr_sel) =~ s/ : /_to_/;      my $sig_name_prefix = "wa_$addr_sel_for_signal\_is_";      my %sel_signals;  # Avoid redundant signal names.            for my $sel (reverse(0 .. $num_byteenables - 1))      {        my $sig_name = "$sig_name_prefix@{[$sel >> $address_lsb]}";        if (!defined($sel_signals{$sig_name}))        {          # Create the signal.          push @contents, e_assign->new({            lhs => [$sig_name, 1,],            rhs => sprintf("($port_prefix\_address\[$addr_sel] == %d'h%X)",              $num_important_address_bits, $sel >> $address_lsb),          });          # Remember that this signal has been created.          $sel_signals{$sig_name} = 1;        }        push @terms, $sig_name;      }      # Concatenate all terms.      $be_expression = "{@{[join(', ', @terms)]}}";    }    if (get_allowed_transactions() > 1)    {      push @muxtable, ($trans_bit_name, $be_expression);    }    else    {      # Instead of a mux, a simple assignment.      push @contents, (        e_assign->new({          lhs => "$port_prefix\_byteenable",          rhs => $be_expression,        }),      );    }  }  if (get_allowed_transactions() > 1)  {    push @contents, (      e_mux->new({        lhs => "$port_prefix\_byteenable",        table => \@muxtable,        type => "and_or",      }),    );  }  $byteenable_module->add_contents(@contents);  return e_instance->new({module => $byteenable_module});}sub get_write_master_ports{  my ($Options, $burst_enable, $max_burstcount_width) = @_;  my $port_prefix = 'write';  my @ports = get_master_ports($Options, $port_prefix);  # SPR 12225.    if (has_byteenables($Options))  {    my $num_byteenables = $Options->{writedatawidth} / 8;    push @ports, (      e_port->new({        name => $port_prefix . "_byteenable",        width => $num_byteenables,        direction => "output",        type => 'byteenable',      }),    );  }  push @ports, (    e_port->new({      name => $port_prefix . "_address",      direction => "output",      width => $Options->{writeaddresswidth},      type => 'address',    }),    e_port->new({      name => $port_prefix . "_writedata",      direction => "output",      width => $Options->{writedatawidth},      type => 'writedata',    }),    e_port->new({      name => $port_prefix . "_write_n",      direction => "output",      type => 'write_n',    }),  );  push @ports, (    e_port->new({      name => $port_prefix . "_burstcount",      type => "burstcount",      direction => "output",      width => "$max_burstcount_width"    })   ) if ($burst_enable);  return @ports;}sub get_read_master_ports{  my ($Options, $burst_enable, $max_burstcount_width) = @_;  my $port_prefix = 'read';  my @ports = get_master_ports($Options, $port_prefix);  push @ports, (    e_port->new({      name => $port_prefix . "_address",      direction => "output",      width => $Options->{readaddresswidth},      type => 'address',    }),    e_port->new({      name => $port_prefix . "_readdata",      direction => "input",      width => $Options->{readdatawidth},      type => 'readdata',    }),    e_port->new({      name => $port_prefix . "_read_n",      direction => "output",      type => 'read_n',    }),    e_port->new({      name => $port_prefix . "_readdatavalid",      direction => "input",      type => 'readdatavalid',    }),    e_port->new({      name => $port_prefix . "_flush",      direction => "output",      type => 'flush',    }),  );  push @ports, (    e_port->new({      name => $port_prefix . "_burstcount",      type => "burstcount",      direction => "output",      width => "$max_burstcount_width"    })  ) if ($burst_enable);  return @ports;}sub get_master_ports{  my ($Options, $port_prefix) = @_;  my @master_ports = (    e_port->new({      name => $port_prefix . "_chipselect",      direction => "output",      type => 'chipselect',    }),    e_port->new({      name => $port_prefix . "_waitrequest",      direction => "input",      type => 'waitrequest',    }),    e_port->new({      name => $port_prefix . "_endofpacket",      direction => "input",      type => 'endofpacket',    })  );  return @master_ports;}sub make_fifo{  my ($top_module, $Options) = @_;  $top_module->add_contents(    e_assign->new([      "flush_fifo",      "~d1_done_transaction & done_transaction"    ]),  );  my $fifo_module = e_fifo->new({    device_family => $top_module->project()->device_family(),    name_stub => $top_module->name(),    data_width => $Options->{fifodatawidth},    fifo_depth => $Options->{fifo_depth},    flush => "flush_fifo",    full_port => 0,    p1_full_port => 1,    empty_port => 1,    implement_as_esb => $Options->{fifo_in_logic_elements} ? 0 : 1,    Read_Latency => $Options->{fifo_read_latency},  });  return $fifo_module;}sub make_fsm{  my (    $name,    $go,    $p1_done,    $mem_wait,    $p1_fifo_stall,    $select,    $access_n,    $inc,    $fifo_access,    $extra_latency,    ) = @_;  my $fsm = e_fsm->new({    name => $name,    start_state => "idle",  });  # Registered outputs for memory control.  my $p1_select = "p1_" . $select;  $fsm->add_contents(    e_signal->new({      name => $p1_select, never_export => 1,    }),    e_assign->new({      lhs => e_signal->new({name => $access_n, export => 1,}),      rhs => "~$select",    }),    e_register->new({      delay => 1 + $extra_latency,      in => $p1_select,      out => e_signal->new({name => $select, never_export => 1,}),    }),  );  # Optional fifo-access output - same as $inc.  if ($fifo_access)  {    $fsm->add_contents(      e_signal->new({name => $inc, export => 1,}),      e_assign->new({        lhs => e_signal->new({name => $fifo_access,}),        rhs => "$name\_access & ~$mem_wait",      }),    );  }  $fsm->OUTPUT_DEFAULTS({    $p1_select => 0,  });  $fsm->OUTPUT_WIDTHS({    $p1_select => 1,  });  $fsm->add_state(    "idle",    [      {$go => 0,},      "idle",      {}    ],    [      {$p1_done => 1,},      "idle",      {}    ],    # Loop while the fifo forces a stall.    [      {$p1_fifo_stall => 1,},      "idle",      {}    ],    [      # Go off to do an access.      # Note extra latency here: p1_fifo_stall = 0 means that it would      # be safe to do an access to a latent peripheral now, because there      # will be room by the time the new data arrives.  But, since select      # is registered, it takes one more cycle to make the request.  Seems      # like this could be optimized, but it might cause trouble with      # reads of non-latent slaves.      {        $go => 1,        $p1_done => 0,        $p1_fifo_stall => 0,      },      "access",      {$p1_select => 1,},    ],  );  $fsm->add_state(    "access",    # FIFO stalls: wait in idle.    [      {$p1_fifo_stall => 1, $mem_wait => 0,},      "idle",      {},    ],    # When finished, go back to idle.    [      {$p1_done => 1, $mem_wait => 0,},      "idle",      {},    ],    # If the memory says "wait", wait!    [      {$mem_wait => 1, },      "access",      {$p1_select => 1,},    ],    # Streaming right along... do another access.    [      {        $mem_wait => 0,        $p1_fifo_stall => 0,        $p1_done => 0,      },      "access",      {$p1_select => 1,},    ],  );  # Special case: dumb e_fsm can't figure out how to make this expression  # without a combinational logic loop, but I can.  $fsm->add_contents(    e_assign->new({      # comment => " $inc is active in state $name\_access, unless $mem_wait is high.",      lhs => [$inc, 1,],      rhs => "$select & ~$mem_wait",    }),  );  return $fsm;}sub make_write_machine{  my ($Options, $name) = @_;  # Given  #  #   write_waitrequest  #   fifo_datavalid  #  # generate   #  #   fifo_read  #   inc_write  #   mem_write_n  #   write_select  #  my $write_fsm_module = e_module->new({    name => $name,  });  $write_fsm_module->add_contents(    e_assign->new({      lhs => e_signal->new({name => "write_select", export => 1,}),      rhs => 'fifo_datavalid & ~d1_enabled_write_endofpacket',    }),    e_assign->new({      lhs => e_signal->new({name => "mem_write_n", export => 1,}),      rhs => "~write_select",    }),    e_assign->new({      lhs => e_signal->new({name => "fifo_read", export => 1,}),      rhs => "write_select & ~write_waitrequest",    }),    e_assign->new({      lhs => "inc_write",      rhs => "fifo_read",    }),  );  return $write_fsm_module;}sub make_fsms{  my ($top_module, $Options) = @_;  # Create three state machines:  # 1) reads memory  # 2) writes to FIFO when data arrives  # 3) reads from FIFO, writes to memory.  # READ FSM (read memory, write to FIFO):  # Inputs:  #  go  #  p1_done_read  #  read_waitrequest  #  p1_fifo_full

⌨️ 快捷键说明

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