📄 generate_ddr_sim_model.pl
字号:
{name => "dq_temp", width => $dq_width},
),
e_assign->news
(
["cke" => $default_pin_prefix."cke"],
["cs_n" => $default_pin_prefix."cs_n"],
["ras_n" => $default_pin_prefix."ras_n"],
["cas_n" => $default_pin_prefix."cas_n"],
["we_n" => $default_pin_prefix."we_n"],
["dm" => $default_pin_prefix."dm"],
["ba" => $default_pin_prefix."ba"],
["a" => $default_pin_prefix."a"],
),
);
# my $x;
# if ($number_of_lump_delays > 1) {
# for ($x=0; $x < ($number_of_lump_delays ); $x++) {
# #print "connecting lump delay $x out of $number_of_lump_delays\n";
# $module->add_contents
# (
# e_signal->news
# (
# {name => "dqs_out_".$x, width => $dqs_width},
# {name => "dq_out_".$x, width => $dq_width},
# )
# );
# }
# }
# Now the fun begins ;-)
$module->add_contents
(
# Define txt_code based on ras/cas/we
e_assign->new
({
lhs => e_signal->new({name => "cmd_code", width => 3}),
rhs => "{ras_n, cas_n, we_n}",
}),
e_sim_wave_text->new
({
out => "txt_code",
selecto => "cmd_code",
table =>
[
"3'h0" => "LMR",
"3'h1" => "ARF",
"3'h2" => "PRE",
"3'h3" => "ACT",
"3'h4" => " WR",
"3'h5" => " RD",
"3'h6" => "BST",
"3'h7" => "NOP",
],
default => "BAD",
}),
# "Inhibit" if no chip_selects,
e_signal->new({name => "CODE", width=> 8*3, never_export => 1}),
e_assign->new(["CODE" => "(\&cs_n) ? $STR_INH : txt_code"]),
);
## Row/Col Address Construction:
# We're constructing a monolithic address into a single large array.
# If there are multiple chip-selects, we assume they are one-hot
# encoded (that's what our controller drives).
# First, we'll build up row/bank. (arb == address_row_bank)
my $arb_rhs;
#my $arb_width = $WSA->{sdram_bank_width} + $WSA->{sdram_row_width};
my $arb_width = $ba_width + $row_width;
$arb_rhs = "{ba, a}";
# if ($ba_width == 1)
# {
# # We only have 2 banks, row/addr build as {row,bank}
# $arb_rhs = "{a, ba}";
# }
# elsif ($ba_width == 2)
# {
# # 4 banks construct address as {bank[1],row,bank[0]}
# $arb_rhs = "{ba[1], a, ba[0]}"
# }
# then we'll tack cs_encoded bits as the top bits, if applicable
# (acrb == addr_chip-select_row_bank)
my $acrb_rhs;
my $acrb_width = $arb_width;
if ($num_chipselects < 2)
{
# Single chipselect does not affect address:
$acrb_rhs = $arb_rhs;
}
else
{
# Multiple chipselects are encoded to create high order addr bits.
# Note that &one_hot_encoding outputs a properly ordered @list!
my %cs_encode_hash =
( default => ["cs_encode" => $num_chipselect_address_bits."'h0"] );
my @raw_cs = &one_hot_encoding($num_chipselects);
# print "\&make_sodimm: num_cs = $num_chipselects \t \@raw_cs = @raw_cs\n";
my $cs_count = 0;
foreach my $chip_select (@raw_cs) {
$cs_encode_hash{$chip_select} =
[
e_assign->new
(
["cs_encode" => $num_chipselect_address_bits."'h".$cs_count],
)
];
$cs_count++;
} # foreach (@raw_cs)
# Create the cs_encode signal, and use a case statement to define it.
$module->add_contents
(
e_signal->news
(
{name => "cs", width=> $num_chipselects},
{name => "cs_encode", width=> $num_chipselect_address_bits},
),
e_assign->new(["cs" => "~cs_n"]), # invert cs_n for encoding
e_process->new({
clock => "",
comment =>
"Encode 1-hot ChipSelects into high order address bit(s)",
contents=>
[
e_case->new({
switch => "cs",
parallel => 1,
contents => {%cs_encode_hash},
}),
],
}),
);
# prepend the encoded bits as upper order addr bits, and remember width
$acrb_rhs = "{cs_encode, $arb_rhs}";
$acrb_width += $num_chipselect_address_bits;
}
# define/assign final construction signals
# (ac_rhs == addr_col), constructed to avoid A[10] for large col_width
my $ac_rhs = "a[".($col_width-1).":1]";
# if ($col_width < 11) {
# $ac_rhs = "a[".($col_width-1).":0]";
# } elsif ($col_width == 11) {
# $ac_rhs = "{a[11],a[9:0]}";
# } else {
# $ac_rhs = "{a[".$col_width.":11],a[9:0]}";
# }
my $read_addr_width = $acrb_width + $col_width;
$module->add_contents
(
e_signal->news
(
#{name => "addr_crb", width=> $acrb_width},
{name => "addr_col", width=> $col_width - 1},
{name => "test_addr",width=> $read_addr_width},
# {name => "temp_addr",width=> $read_addr_width},
),
e_signal->news
(
{name => "rd_addr_pipe_0", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "rd_addr_pipe_1", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "rd_addr_pipe_2", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "rd_addr_pipe_3", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "rd_addr_pipe_4", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "rd_addr_pipe_5", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "read_addr_delayed", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "rmw_address", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_addr_pipe_0", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_addr_pipe_1", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_addr_pipe_2", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_addr_pipe_3", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_addr_pipe_4", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_addr_pipe_5", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_addr_delayed", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "wr_burst_counter", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
{name => "rd_burst_counter", width=> $read_addr_width, default_value => "0",export => 0, never_export => 1},
),
e_assign->news
(
["addr_col" => $ac_rhs],
# ["test_addr"=> "{addr_crb, addr_col}"],
),
);
## Define some random necessary variables:
# we only support up to a max cas_latency of 3, and just soak up that many
#resources, and pluck off an earlier version if the cas_latency is set
#lower during LMR...
$module->add_contents
(
e_signal->news
(
{name => "rd_valid_pipe", width=> 6}, # was 5?
{name => "wr_valid_pipe", width=> 6}, # was 5?
#{name => "latency", width=> 3},
{name => "index", width=> 3},
),
);
## Set up ram read/wr var's and initial block to readmem our dat file:
$module->add_contents
(
e_signal->news
(
{name => "rmw_temp", width=> $mem_width},
{name => "mem_bytes",width=> $mem_width},
{name => "read_data",width=> $mem_width},
{name => "read_temp",width=> $mem_width,export => 0, never_export => 1},
{name => "read_valid",width=> 1,export => 0, never_export => 1},
{name => "read_cmd",width=> 1,export => 0, never_export => 1},
{name => "write_valid_r" , width => 1, export => 0, never_export => 1},
{name => "read_valid_r" , width => 1, export => 0, never_export => 1},
{name => "write_valid_r2", width => 1, export => 0, never_export => 1},
{name => "write_valid_r3", width => 1, export => 0, never_export => 1},
{name => "write_to_ram_r", width => 1, export => 0, never_export => 1},
{name => "read_valid_r2" , width => 1, export => 0, never_export => 1},
{name => "read_valid_r3" , width => 1, export => 0, never_export => 1},
{name => "read_valid_r4" , width => 1, export => 0, never_export => 1},
{name => "burstmode",width=> 1,export => 0, never_export => 1},
{name => "burstlength",width=> 3,export => 0, never_export => 1},
),
e_assign->new(["current_row" => "{cs_n,ba}"]),
);
#sjh - No need for *read* masking with DDR
# # Try to make life easier by defining the necessary number of byte lane
# #field descriptors like 7:0, 15:8, etc...
my %lanes;
my $byte_lane;
# # assign rmw_temp[7:0]= dqm[0] ? mem_bytes[7:0] : $dq[7:0]
# if ($mem_mask_width > 1) {
# for (0 .. ($mem_mask_width-1))
# {
# $byte_lane = $_;
# $lanes{$byte_lane} = (($byte_lane*8)+7).":".($byte_lane*8);
# $module->add_contents
# (
# e_assign->new
# (
# ["rmw_temp[$lanes{$byte_lane}]" =>
# "dm[$byte_lane] ? ".
# "mem_bytes[$lanes{$byte_lane}] : ".$dq."[$lanes{$byte_lane}]"]
# )
# );
# } # for (0 to ($dm_width-1))
# } else {
# $module->add_contents
# (
# e_assign->new(["rmw_temp" => "dm ? mem_bytes : ".$dq])
# );
# }
# Build the Main Process:
$module->add_contents
(
e_process->new
({
comment => " Decode commands into their actions",
contents =>
[
e_if->new({
comment => " No Activity if the clock is",
condition => "cke",
then =>
[
e_if->new({
comment => " This is a read command",
condition => "(cmd_code == 3'b101)",
then => [e_assign->news
(["read_cmd" => "1'b1"],
# ["rd_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],
),
],
else => ["read_cmd" => "1'b0"],
}),
e_if->new({
comment => " This is a write command",
condition => "(cmd_code == 3'b100)",
then => [e_assign-> news
(["write_cmd" => "1'b1"],
#["wr_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -