📄 generate_ddr_sim_model.pl
字号:
#print "Avalon burst length is $local_burst_length \n";
# Start building up a simulation-only display string.
@write_lines =
(
"",
"**********************************************************************",
"This testbench includes an SOPC Builder generated Altera memory model:",
"'$sim_file', to simulate accesses to the $mem_pretty_name memory.",
" ",
);
# if ($local_burst_length > 1)
# {
# push @write_lines,(
# "WARNING: The Altera $mem_pretty_name Controller supports Avalon bursts,",
# "but this simulation model does not. If any of the masters in your",
# "SOPC Builder system will issue Avalon bursts, then you ",
# "should use a memory model supplied by your memory vendor. ",
# " ",
# );
# }
push @write_lines,
(
"Initial contents are loaded from the file: ".
"'$sim_dat'."
);
push @write_lines,
("**********************************************************************");
# Convert all lines to e_sim_write objects.
map {$_ = e_sim_write->new({spec_string => $_ . '\\n'})} @write_lines;
# Wrap the simulation-only display string in an e_initial_block, so we
# only see the message once!
if (@write_lines)
{
my $init = e_initial_block->new({
contents => [ @write_lines ],
});
$module->add_contents($init);
} # if (@write_lines)
# sjh WRONG - should get the clock properly!
$WSA->{system_clock_rate} = $project->system_ptf()->{WIZARD_SCRIPT_ARGUMENTS}{clock_freq};
# New style contents generation (a'la OnchipMemoryII -- thanks AaronF)
my $Opt = {name => $project->_target_module_name()};
$project->do_makefile_target_ptf_assignments
(
's1',
['dat', 'sym', ],
$Opt,
);
# Reality checks:
#my $tempclockrate = $project->system_ptf()->{WIZARD_SCRIPT_ARGUMENTS}{clock_freq};
my $clockrate = $wizard_shortcut->{PRIVATE}{clock_speed}{value};
#print "clockrate = $clockrate\n";
my $clockperiod = 1/$clockrate*1000;
#print "clockperiod = $clockperiod\n";
#print "Data width = ".$wizard_shortcut->{PRIVATE}{width}{value}."\n";
#print "Data width2 = ".$WSA->{MEGACORE}{NETLIST_SECTION}{STATIC_SECTION}{PRIVATES}{NAMESPACE}{parameterization}{PRIVATE}{width}{value}."\n";
# SODIMM allows all the same data path widths as the sdram controller
&validate_parameter({
hash => $wizard_shortcut->{PRIVATE}{width},
name => "value",
type => "integer",
allowed => [8, 16, 32, 64],
});
#sjh Don't check these for now
# &validate_parameter({
# hash => $WSA,
# name => "sdram_bank_width",
# type => "integer",
# default => "2",
# allowed => [1, 2],
# });
#sjh Don't check these for now
# # Having a non-integer power of 2 for number of chip selects seems wrong.
# my $num_chipselects = $WSA->{sdram_num_chipselects};
my $num_chipselects = $wizard_shortcut->{PRIVATE}{chipselects}{value};
my $num_chipselect_address_bits = log2($num_chipselects);
# &validate_parameter({
# hash => $WSA,
# name => "sdram_num_chipselects",
# type => "integer",
# allowed => [1, 2, 4, 8],
# });
my $cas_latency = $wizard_shortcut->{PRIVATE}{cas_latency}{value};
#print "CAS latency = $cas_latency\n";
# In the real world, 3 bits of the mode register are used to encode
# cas latency, with code "3'b000" reserved.
&validate_parameter({
hash => $wizard_shortcut->{PRIVATE}{cas_latency},
name => "value",
type => "string",
allowed => ["2.0", "2.5", "3.0", "4.0", "5.0"],
});
my $resynch_phase = $wizard_shortcut->{PRIVATE}{resync_phase}{value};
my $resynch_cycle = $wizard_shortcut->{PRIVATE}{resynch_cycle}{value};
#print "resynch cycle = $resynch_cycle\n";
#print "resynch phase = $resynch_phase\n";
# approximate the roundtrip delay based on resynch cycle (taking CL into account) - 1/4 cycle + whatever the resynch phase is,.
# my $rtl_sim_delay = (($resynch_cycle + 2 - $cas_latency)*$clockperiod) + ($clockperiod * ($resynch_phase/360));
my $clock_board_delay = $wizard_shortcut->{PRIVATE}{board_tpd_clock_trace_nom}{value};
my $dqs_board_delay = $wizard_shortcut->{PRIVATE}{board_tpd_dqs_trace_total_nom}{value};
my $rtl_board_delay = ($clock_board_delay + $dqs_board_delay) / 1000;
# split total delay in 90 deg segements because we can't set modelsim to use transport delays instead of inertial!
# my $number_of_lump_delays = floor($rtl_sim_delay / ($clockperiod / 4) + 1);
#print "sim delay = $rtl_sim_delay spread over $number_of_lump_delays delays.\n";
#sjh Not needed for DDR
# This setting is hidden from the GUI, but takes affect as a result
# of using the 'preset's...
# FIXME: Our model doesn't care about refresh commands, but we might want
# to indicate via printf/write/$display that they are occuring...
# &validate_parameter({
# hash => $WSA,
# name => "init_refresh_commands",
# type => "integer",
# allowed => [1 .. 8],
# });
# Compute the width of the controller's address (as seen by the Avalon
# bus) from input parameters. SODIMM will address a raw memory array in
# the same way that Avalon accesses the Controller.
# my $addr_width =
# $num_chipselect_address_bits +
# $WSA->{sdram_bank_width} +
# $WSA->{sdram_col_width} +
# $WSA->{sdram_row_width};
my $addr_width = $wizard_shortcut->{PRIVATE}{local_address_width}{value};
my $ba_width = $wizard_shortcut->{PRIVATE}{bankbits}{value};
my $row_width = $wizard_shortcut->{PRIVATE}{rowbits}{value};
my $col_width = $wizard_shortcut->{PRIVATE}{colbits}{value};
#print "Controller has address widths, a = $addr_width, ba = $ba_width, row = $row_width, col = $col_width\n";
# print "ctrler width = $addr_width\t ".
# "Num CSBits = $num_chipselect_address_bits\n";
# print "Num Banks = ".$WSA->{sdram_num_banks}.
# " \tNum BankBits = ".$WSA->{sdram_bank_width}."\n";
# print "Rows = ".$WSA->{sdram_row_width}.
# " \tCols = ".$WSA->{sdram_col_width}."\n";
# FIXME:? We check NOTHING about validity of SDRAM Controller Timing or
# Protocol -- we trust the user to set the parameters as if for a real
# SODIMM!
my $dq_width = $wizard_shortcut->{PRIVATE}{width}{value};
my $dqs_width = $wizard_shortcut->{PRIVATE}{width}{value} / 8;
my $dm_width = $wizard_shortcut->{PRIVATE}{width}{value} / 8;
my $mem_width = $dq_width * 2;
my $mem_mask_width = $dm_width * 2;
#my $dm_width = $WSA->{sdram_data_width} / 8;
# if (int($dm_width) != $dm_width)
# {
# ribbit
# (
# "Unexpected: SDRAM data width '", $dq_width}, "', ".
# "leads to non-integer DQM width ($dm_width)"
# );
# }
# else
# {
# printf ("make_sodimm: data_width = %d\tdqm_width = %d\n",
# $WSA->{sdram_data_width},$dm_width);
# }
# Let's set up the str2hex CODE variable to be "INH" or 'some active
# code', depening upon {cs_n[x], ras_n, cas_n, we_n}
# set up some precoded 3 character wide strings for wave display below:
my $STR_INH = &str2hex ("INH"); # Inhibit
my $STR_LMR = &str2hex ("LMR"); # To grab cas_latency during LoadMoadReg
my $STR_ACT = &str2hex ("ACT"); # To grab cs/row/bank addr during Activate
my $STR__RD = &str2hex (" RD"); # To grab col addr during Read
my $STR__WR = &str2hex (" WR"); # To grab col addr during Write
# Precharge, AutoRefresh and Burst are ignored by this model!
# NB: we may choose to later add a AutoRefresh timing check...
# SRA modified so always read in file
#my $ram_file = "";
#if ($WSA->{is_initialized}) {
my $ram_file = $sim_dat;
#}
$module->add_contents
(
e_ram->new
({
comment => "Synchronous write when (CODE == $STR__WR (write))",
name => $project->get_top_module_name() . "_ram",
Read_Latency => "0",
dat_file => $ram_file,
port_map =>
{
#wren => "write_valid_r2",
wren => "write_to_ram_r",
data => "rmw_temp",
q => "read_data",
wrclock => "clk",
#wraddress=>"wr_addr_delayed",
wraddress=>"wr_addr_delayed_r",
#rdaddress=>"(write_valid) ? wr_addr_pipe_1 : read_addr_delayed",
rdaddress=>"rmw_address",
}
}),
);
# Tho the Altera SDR SDRAM Controller's always wire their clk_en 'ON',
# some users may wire their testbench to flick the bit...
# Port Naming matches common SODIMM conventions, with some exceptions:
# Since the controller only drives one clock, and one clock_enable, we
# never create a bus of inputs for those signals (many sodimms have 2 or
# more ck and cke's); we do not support any sort of Serial Presence
# Detect, nor the associated SCL (serial-clock) and SDA (serial-data)
# signals.
# NOTE: WSA->{sdram_addr_width} is not necessarily WSA->{sdram_row_width}!
my $dq; # variable for dq signal name, for 3-state mode
my $dqs; # variable for dq signal name, for 3-state mode
$dq = $default_pin_prefix."dq"; # Dedicated pin-mode dq name
$dqs = $default_pin_prefix."dqs"; # Dedicated pin-mode dq name
# Dedicated pin-mode sodimm port names and assignments
$module->add_contents
(
e_port->news
(
{name => "clk"},
{name => $default_pin_prefix."cke", width => $num_chipselects},
{name => $default_pin_prefix."cs_n", width => $num_chipselects},
{name => $default_pin_prefix."ras_n"},
{name => $default_pin_prefix."cas_n"},
{name => $default_pin_prefix."we_n"},
{name => $default_pin_prefix."dm", width => $dm_width },
{name => $default_pin_prefix."ba", width => $ba_width },
{name => $default_pin_prefix."a", width => $row_width },
{name => $default_pin_prefix."dq", width => $dq_width, direction => "inout"},
{name => $default_pin_prefix."dqs", width => $dqs_width, direction => "inout"},
),
e_signal->news
(
{name => "cke", width => $num_chipselects},
{name => "cs_n", width => $num_chipselects},
{name => "ras_n"},
{name => "cas_n"},
{name => "we_n"},
{name => "dm", width => $dm_width,export => 0, never_export => 1},
{name => "ba", width => $ba_width},
{name => "a", width => $row_width},
{name => "read_dq", width => $dq_width},
{name => "dqs", width => $dqs_width},
{name => "first_half_dq", width => $dq_width,export => 0, never_export => 1},
{name => "second_half_dq",width => $dq_width,export => 0, never_export => 1},
{name => "dq_captured", width=> $dq_width*2,export => 0, never_export => 1},
{name => "dq_valid", width=> 1,export => 0, never_export => 1},
{name => "dqs_valid", width=> 1,export => 0, never_export => 1},
{name => "dqs_valid_temp", width=> 1,export => 0, never_export => 1},
{name => "dm_captured", width=> $dqs_width*2,export => 0, never_export => 1},
{name => "open_rows", width => $row_width, depth => (2 ** ($ba_width + $num_chipselects))},
{name => "current_row", width => ($ba_width + $num_chipselects),export => 0, never_export => 1},
{name => "dqs_temp", width => $dqs_width},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -