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

📄 em_dma.pm

📁 altera_avalon_dma.rar大家快下啊
💻 PM
📖 第 1 页 / 共 5 页
字号:
      e_assign->new({        lhs => ["p1_writeincov_eq_0", 1, 0, 1],        rhs => $is0_p1_rhs,      }),      e_register->new({        out                => ["writeincov_eq_0", 1, 0, 1],        in                 => "p1_writeincov_eq_0",        enable             => $incov_clken,        async_value        => $async_val,      }),    );  }  my $transaction_size = get_transaction_size_expression();  my @top_priority =    $Options->{writeincovwidth} ? ("~writeincov_eq_0", "writeincov") : ();  $module->add_contents(    e_mux->new({      lhs => e_signal->new({        name => "writeaddress_inc",        # The increment width is at least the number of transaction-size bits        # in the control register, but can be as large as the override.        width => max(          scalar(get_transaction_size_bit_indices()),          $Options->{writeincovwidth}        ),      }),      type           => "priority",      table          => [        @top_priority,        "wcon", "0",        "$burst_enable", "0",      ],      default => "$transaction_size",    }),  );  @top_priority =    $Options->{readincovwidth} ? ("~readincov_eq_0", "readincov") : ();  $module->add_contents(    e_mux->new({      lhs => e_signal->new({        name => "readaddress_inc",        # The increment width is at least the number of transaction-size bits        # in the control register, but can be as large as the override.        width => max(          scalar(get_transaction_size_bit_indices()),          $Options->{readincovwidth}        ),      }),      type           => "priority",      table          => [        @top_priority,        "rcon", "0",        "$burst_enable", "0",      ],      default => "$transaction_size",    }),  );  # How about a nice read-data mux?  my @muxtable = ();  for (my $i = 0; $i < @reg_info; ++$i)  {    # Skip "reserved" registers.    next if $reg_info[$i]->[1] =~ /reserved/;    # Skip any register with width 0.    next if $reg_info[$i]->[2] == 0;    # Register select.    push @muxtable, "dma_ctl_address == $i";    # Selected register name.    my $reg_name = @{$reg_info[$i]}->[1];    # Special case: when "reserved3" is read, you get "control".    $reg_name = "control" if ($reg_name eq "reserved3");    # Special case: when "length" is read, you get    # writelength instead.  That's because the value in the    # (user-invisible) writelength register keeps track of     # transfers which are fully completed, while length    # can run ahead a bit.    $reg_name = "writelength" if ($reg_name eq "length");    push @muxtable, $reg_name;  }  my $data_width = get_slave_port_data_width($Options);  $module->add_contents(    e_mux->new({      lhs => ["p1_dma_ctl_readdata", $data_width, ],      type => "and_or",      table => \@muxtable,    }),    e_register->new({      in => "p1_dma_ctl_readdata",      out => "dma_ctl_readdata",    }),  );  $module->add_contents(    e_assign->new({      lhs => e_signal->new({name => "done_transaction", width => 1}),          rhs => "go & done_write",    })  );  $module->add_contents(    e_register->new({      out                => "done",      sync_set           => "done_transaction & ~d1_done_transaction",      sync_reset         => "status_register_write",      clock              => "clk",      async_value        => 0,    }),  );  $module->add_contents(    e_register->new({      out                => "d1_done_transaction",      in                 => "done_transaction",      clock              => "clk",      async_value        => 0,    }),  );  $module->add_contents(    e_assign->new({      lhs => e_signal->new({name => "busy", width => 1}),      rhs => "go & ~done_write",    })  );  # Pull the status and control bits out into their own lists,  # indexed by bit number.  my @status_bits;  map {    # $_ = ["reg_name", "bit_name", "bit_pos", "comment"];    $status_bits[$_->[2]] = $_->[1];  } get_status_bits();  my @control_bits;  map {    # $_ = ["reg_name", "bit_name", "bit_pos", "comment"];    $control_bits[$_->[2]] = $_->[1];  } get_control_bits();  $module->add_contents(    e_signal->new({      name => "status",      width => 0 + @status_bits,      never_export => 1,    }),  );  # Assign each status bit from its status reg.  for my $i (0 .. @status_bits - 1)  {    $module->add_contents(      e_assign->new({        rhs => "$status_bits[$i]",        lhs => "status[$i]",      })    );  }  # Assign random control bit signals from the control register.      for my $i (0 .. @control_bits - 1)  {    my $bit_name = $control_bits[$i];    my $rhs = "control[$i]";    if ($Options->{burst_enable} && ($bit_name =~ /^[rw]een$/))    {      # Bursting DMAs are not allowed to terminate early on      # write endofpacket events (doing so would violate the       # burst master rule that all requested burst transactions      # must be done - in all likelihood, the result would be system      # lockup).  To avoid this, prevent the ween bit from being set.      # Also prevent the reen bit from being set, because I can't see      # any use in setting reen on a read burst.      $rhs = "1'b0";    }    $module->add_contents(      e_assign->new({        lhs => e_signal->new({          name => $bit_name,          never_export => 1        }),        rhs => $rhs,      })    );  }  # How about an IRQ output?  $module->add_contents(    e_assign->new({      lhs => "dma_ctl_irq",      rhs => "i_en & done",    })  );}sub push_global_ports{  my $module = shift;  $module->add_contents(    e_port->new({name => "clk", type => "clk",}),    e_port->new({name => "system_reset_n", type => "reset_n",}),  );}sub get_control_interface_map{  my $Options = shift;  # Even master-less DMAs need these signals.  my @map = (    "dma_ctl_irq" => "irq",    "dma_ctl_readyfordata" => "readyfordata",  );  if (@{$Options->{masters_of_my_slave_port}})  {    # If the slave port has master(s), these ports are also needed.    push @map, (      "dma_ctl_chipselect" => "chipselect",      "dma_ctl_address" => "address",      "dma_ctl_write_n" => "write_n",      "dma_ctl_writedata" => "writedata",      "dma_ctl_readdata" => "readdata",      "clk" => "clk",      "system_reset_n" => "reset_n",    );  }  return @map;}sub modify_burst_system_ptf_asssignments {  my ($project, $module, $Options) = @_;  my $max_burst_size = $Options->{burst_enable} ? $Options->{max_burst_size} : 1;  my $module_name = $module->name();  my $sys_ptf = $project->system_ptf();  $sys_ptf->    {"MODULE $module_name"}->    {"MASTER $write_master_name"}->    {"SYSTEM_BUILDER_INFO"}->{Maximum_Burst_Size} = $max_burst_size;  $sys_ptf->    {"MODULE $module_name"}->    {"MASTER $read_master_name"}->    {"SYSTEM_BUILDER_INFO"}->{Maximum_Burst_Size} = $max_burst_size;}sub push_control_interface_ports{  my ($project, $module, $Options) = @_;  my $data_width = get_slave_port_data_width($Options);  my $addr_width = get_slave_port_addr_width($Options);  # While we're here, why not update the SBI section of the slave?  # It's got probably-reasonable values from the class.ptf, but it  # will be wrong if e.g. there's a large read- or write-address port.  my $module_name = $module->name();  my $sys_ptf = $project->system_ptf();  my $slave_sbi =    $sys_ptf->    {"MODULE $module_name"}->    {"SLAVE $control_port_name"}->    {"SYSTEM_BUILDER_INFO"};  ribbit("what th'?") if (!$slave_sbi);  $slave_sbi->{Data_Width} = $data_width;  $slave_sbi->{Address_Width} = $addr_width;  if (@{$Options->{masters_of_my_slave_port}})  {    $module->add_contents(      e_port->new({name => "dma_ctl_irq", type => "irq", direction => "output"}),    );    $module->add_contents(      e_port->new({        name => "dma_ctl_readyfordata",        type => "readyfordata",        direction => "output"      }),       e_assign->new(["dma_ctl_readyfordata", "~busy"]),    );    $module->add_contents(      e_port->new({name => "dma_ctl_chipselect", type => "chipselect",}),      e_port->new({        name => "dma_ctl_address", type => "address", width => $addr_width,      }),      e_port->new({name => "dma_ctl_write_n", type => "write_n",}),      e_port->new({        name => "dma_ctl_writedata",        width => $data_width,        type => "writedata",      }),      e_port->new({        name => "dma_ctl_readdata",        width => $data_width,        type => "readdata",        direction => "output",      },),    );      }  else  {    # No masters.  Generate a minimal port set; generate default-level signals    # for other control signals.    $module->add_contents(      e_port->new({        name => "dma_ctl_readyfordata",        direction => "output"      }),       e_assign->new(["dma_ctl_readyfordata", "~busy"]),      e_port->new({name => "dma_ctl_irq", direction => "output"}),      e_assign->new([        e_signal->new(["dma_ctl_chipselect", 1, 0, 1,]), 0      ]),      e_assign->new([        e_signal->new(["dma_ctl_address", $addr_width, 0, 1]), 0      ]),      e_assign->new([        e_signal->new(["dma_ctl_write_n", 1, 0, 1,]),    1      ]),      e_assign->new([        e_signal->new(["dma_ctl_writedata", $data_width, 0, 1]), 0      ]),      e_signal->new([        "dma_ctl_readdata",                 $data_width, 0, 1      ]),    );  }}sub get_read_master_type_list{  return qw(    readdata    readdatavalid    read_n    flush  );}sub get_write_master_type_list{  return qw(    write_n    writedata    byteenable  );}sub get_master_type_list{  my $Options = shift;  my $burst_enable = $Options->{burst_enable};  my @master_type_list = qw(    address    chipselect    waitrequest    endofpacket  );  push @master_type_list, "burstcount" if $burst_enable;  return @master_type_list;}sub get_write_master_type_map{  my $Options = shift;  ribbit("no Options hash\n") if (!$Options);  my $port_prefix = 'write';  my @types = get_master_type_list($Options);  # Add in all write-master-specific ports.  Omit  # byteenable if there ain't none.  push @types,    grep {has_byteenables($Options) or $_ ne 'byteenable'}      get_write_master_type_list();  # Make a hash of $port_prefix . "_" . $type[] => $type[].  return map {($port_prefix . "_$_" => $_)} @types;}sub get_read_master_type_map{  my $Options = shift;  ribbit("no Options hash\n") if (!$Options);  my $port_prefix = 'read';  my @types = get_master_type_list($Options);  push @types, get_read_master_type_list();  # Make a hash of $port_prefix . "_" . $type[] => $type[].  return map {($port_prefix . "_$_" => $_)} @types;}sub has_byteenables{  my $Options = shift;  # We need byteenables if more than one transaction size  # is allowed.  my $has_byteenables = scalar(get_allowed_transactions()) > 1;  return $has_byteenables;}# This is the point where the transaction size bits have an impact.# The write master sends out its byte address as always, but must modulate# the byte enables according to  1) the lower address bits and 2) the# transaction size.# The maximum number of bytes transferred in one write is equal to the # number represented by '1' in the most-significant transaction size bit,# and '0' in all other bits.# Loop over all possible transaction sizes.  Note that the number of# byteenables (related to the write port data width) determines the# maximum transaction size.  Example: if the write data port is 32 bits,# there are 4 byte enables and the max transaction size is 4 bytes aka# 'word'.sub make_write_byteenables{  my ($Options, $module, $project) = @_;  my $port_prefix = 'write';  my $num_byteenables = $Options->{writedatawidth} / 8;  # SPR 12225.  return () if not has_byteenables($Options);  my $byteenable_module = e_module->new({    name => $module->name() . "_byteenables",  });

⌨️ 快捷键说明

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