📄 generate_ddr_sim_model.pl
字号:
),
],
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'b011)",
then =>
[
e_assign->news (["index" => "3'b010" ],)
],
else =>
[
e_if->new({
comment => "CAS Latency = 4.0 ",
condition => "(a[6:4] == 3'b100)",
then =>
[
e_assign->news
(["index" => "3'b011" ],)
],
else =>
[
e_assign->news
(["index" => "3'b100" ],)
],
}),
],
}),
],
}),
e_assign->news
(
["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[5:1]" => "rd_valid_pipe[4:0]"],
["rd_valid_pipe[0]" => "(cmd_code == 3'b101)"],
["wr_addr_pipe_5" => "wr_addr_pipe_4"],
["wr_addr_pipe_4" => "wr_addr_pipe_3"],
["wr_addr_pipe_3" => "wr_addr_pipe_2"],
["wr_addr_pipe_2" => "wr_addr_pipe_1"],
["wr_addr_pipe_1" => "wr_addr_pipe_0"],
["wr_valid_pipe[5:1]" => "wr_valid_pipe[4:0]"],
["wr_valid_pipe[0]" => "(cmd_code == 3'b100)"],
# ["write_valid_r" => "write_valid"],
# ["write_valid_r2" => "write_valid_r"],
["wr_addr_delayed_r" => "wr_addr_delayed"],
),
],
}),
],
}),
);
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}"],
),
],
}),
],
}),
);
} # if local_burst_length > 1
# Assign Outputs:
# if ($mem_mask_width > 1) {
# for (0 .. ($mem_mask_width - 1)) {
# $module->add_contents
# (
# e_assign->new
# (
# ["read_temp[$lanes{$_}]" => "mask[$_] ? ".
# "8'bz : read_data[$lanes{$_}]"]
# ),
# );
# } # for mask-bits
# } else {
# $module->add_contents
# (
# e_assign->new
# (
# ["read_temp" => "mask ? 8'bz : read_data"]
# ),
# );
# }
# process (clk)
# begin
# if clk'event and clk = '1' then
# first_half_dq <= read_data(31 DOWNTO 16);
# second_half_dq <= read_data(15 DOWNTO 0);
# end if;
# end process;
$module->add_contents
(
e_process->new
({
comment => " read data transition from single to double clock rate",
contents =>
[
e_assign->news
(
["first_half_dq" => "read_data[".($dq_width*2-1).":".$dq_width."]"],
["second_half_dq" => "read_data[".($dq_width-1).":0]"],
),
],
}),
# dq <= A_WE_StdLogicVector((std_logic'(clk) = '0'), first_half_dq, second_half_dq);
e_assign->new([read_dq => "clk ? second_half_dq : first_half_dq"]),
# ddr_dqs <= A_WE_StdLogicVector((std_logic'(dqs_valid) = '1'), A_REP(clk, 2), A_REP(std_logic'('Z'), 2));
# ddr_dq <= A_WE_StdLogicVector((std_logic'(dq_valid) = '1'), read_dq, A_REP(std_logic'('Z'), 16));
# e_assign->new([$dqs => "dqs_valid ? {".$dqs_width."{clk}} : {".$dqs_width."{1'bz}}"]),
#e_assign->new([$dq => "dq_valid ? read_dq : {".$dq_width."{1'bz}}"]),
e_assign->new([dqs_temp => "dqs_valid ? {".$dqs_width."{clk}} : {".$dqs_width."{1'bz}}"]),
e_assign->new([dq_temp => "dq_valid ? read_dq : {".$dq_width."{1'bz}}"]),
# model the board trace delay
e_assign->new
({
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -