📄 generate_ddr_sim_model.pl
字号:
e_signal->news
(
{name => "rd_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 => "cas2",width=> 1,export => 0, never_export => 1},
{name => "cas25",width=> 1,export => 0, never_export => 1},
{name => "cas3",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}"],
),
],
else => ["write_cmd" => "1'b0"],
}),
e_if->new({
comment => " This is an activate - store the chip/row/bank address in the same order as the DDR controller",
condition => "(cmd_code == 3'b011)",
then => ["open_rows[current_row]" => "a"],
}),
e_if->new({
comment => "Load mode register - set CAS latency, burst mode and length",
condition => "(cmd_code == 3'b000 && ba == 2'b00)",
then =>
[
e_assign->news
(["burstmode" => "a[3]"],
["burstlength" => "a[2:0] << 1"],
#["wr_addr_pipe_0" => "0"], # otherwise if the first write is partial it breaks!
),
e_if->new({
comment => "Decode CAS Latency from bits a[6..4]",
condition => "(a[6:4] == 3'b010)",
then =>
[
e_assign->news
(["cas2" => "1'b1"],
["index" => "3'b001" ],)
],
else =>
[
e_if->new({
comment => "CAS Latency = 2.5 ",
condition => "(a[6:4] == 3'b110)",
then =>
[
e_assign->news
(["cas25" => "1'b1"],
["index" => "3'b001" ],)
],
else =>
[
e_assign->news
(["cas3" => "1'b1"],
["index" => "3'b010" ],)
],
}),
],
}),
],
}),
e_assign->news
(
["rd_valid_pipe[5:1]" => "rd_valid_pipe[4:0]"],
["rd_addr_pipe_5" => "rd_addr_pipe_4"],
["rd_addr_pipe_4" => "rd_addr_pipe_3"],
["rd_addr_pipe_3" => "rd_addr_pipe_2"],
["rd_addr_pipe_2" => "rd_addr_pipe_1"],
["rd_addr_pipe_1" => "rd_addr_pipe_0"],
["rd_valid_pipe[0]" => "(cmd_code == 3'b101)"],
["wr_addr_pipe_3" => "wr_addr_pipe_2"],
["wr_addr_pipe_2" => "wr_addr_pipe_1"],
["wr_addr_pipe_1" => "wr_addr_pipe_0"],
),
],
}),
],
}),
);
if ($local_burst_length > 1)
{
my $burstcounter_size = $local_burst_length / 2; # burst length count need to wrap within a burst length, so we need a suitable sized counter
# Burst support - make the wr_addr keep counting
$module->add_contents
(
e_process->new
({
comment => " Burst support - make the wr_addr & rd_addr keep counting",
contents =>
[
e_if->new({ # WRITES
comment => " Reset write address otherwise if the first write is partial it breaks!",
condition => "(cmd_code == 3'b000 && ba == 2'b00)",
then =>
[
e_assign->news ( ["wr_addr_pipe_0" => "0"],
["wr_burst_counter" => "0"], ),
],
else =>
[
e_if->new({
condition => "(cmd_code == 3'b100)",
then =>
[
e_assign-> news
(
["wr_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],
["wr_burst_counter[".($read_addr_width-1).":".($burstcounter_size)."]" => "{ba,open_rows[current_row],addr_col[".($col_width-2).":".($burstcounter_size)."]}"],
["wr_burst_counter[".($burstcounter_size-1).":0]" => "addr_col[".($burstcounter_size-1).":0] + 1"],
),
],
else =>
[
e_if->new({
# condition => "(write_cmd == 1'b1) || (write_to_ram == 1'b1)",
condition => "(write_cmd || write_to_ram)",
then =>
[
# e_assign-> news (["wr_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],),
e_assign-> news (["wr_addr_pipe_0" => "wr_burst_counter"],),
e_assign-> news (["wr_burst_counter[".($burstcounter_size-1).":0]" => "wr_burst_counter[".($burstcounter_size-1).":0] + 1"],),
],
else =>
[
e_assign-> news (["wr_addr_pipe_0" => "0"],),
],
}),
],
}),
],
}),
e_if->new({ # READS
comment => " Reset read address otherwise if the first write is partial it breaks!",
condition => "(cmd_code == 3'b000 && ba == 2'b00)",
then =>
[
e_assign->news ( ["rd_addr_pipe_0" => "0"], ),
],
else =>
[
e_if->new({
condition => "(cmd_code == 3'b101)",
then =>
[
e_assign-> news
(
["rd_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],
["rd_burst_counter[".($read_addr_width-1).":".($burstcounter_size)."]" => "{ba,open_rows[current_row],addr_col[".($col_width-2).":".($burstcounter_size)."]}"],
["rd_burst_counter[".($burstcounter_size-1).":0]" => "addr_col[".($burstcounter_size-1).":0] + 1"],
),
],
else =>
[
e_if->new({
condition => "(read_cmd || dq_valid || read_valid)",
then =>
[
e_assign-> news (["rd_addr_pipe_0" => "rd_burst_counter"],),
e_assign-> news (["rd_burst_counter[".($burstcounter_size-1).":0]" => "rd_burst_counter[".($burstcounter_size-1).":0] + 1"],),
],
else =>
[
e_assign-> news (["rd_addr_pipe_0" => "0"],),
],
}),
],
}),
],
}), # end of READS
], # end of contents
}),
);
}
else {
$module->add_contents # no Burst support
(
e_process->new
({
contents =>
[
e_if->new({
comment => " Reset write address otherwise if the first write is partial it breaks!",
condition => "(cmd_code == 3'b000 && ba == 2'b00)",
then =>
[
e_assign->news ( ["wr_addr_pipe_0" => "0"],),
],
else =>
[
e_if->new({
condition => "(cmd_code == 3'b100)",
then =>
[
e_assign-> news
(
["wr_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],
),
],
}),
],
}),
e_if->new({
comment => "Read request so store the read address",
condition => "(cmd_code == 3'b101)",
then =>
[
e_assign-> news
(
["rd_addr_pipe_0" => "{ba,open_rows[current_row],addr_col}"],
),
],
}),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -