📄 sdram_dp.v
字号:
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
`include "sdram_defines.v"
module sdram_dp
(
wb_clk_i,
mem_clk_i,
rst_i,
// sdram state machine interface
do_mode_set,
do_read,
do_write,
sd_addx_mux,
sd_addx10_mux,
sd_rd_ena,
decoded_dqm,
do_write_ack,
do_read_ack,
do_modeset_ack,
pwrup,
// wishbone interface
wb_dat_i,
wb_dat_o,
wb_ack_o,
wb_sel_i,
wb_adr_i,
wb_we_i,
wb_cyc_i,
wb_stb_i,
// sdram io interface
sd_adr_o,
sd_ba_o,
sd_dat_o,
sd_dat_i,
// mode register settings
modereg_cas_latency,
modereg_burst_length
);
input wb_clk_i ;
input mem_clk_i ;
input rst_i ;
output do_mode_set ;
output do_read ;
reg do_read ;
output do_write ;
reg do_write ;
input [1:0] sd_addx_mux ;
input [1:0] sd_addx10_mux ;
input sd_rd_ena ;
output [3:0] decoded_dqm ;
reg [3:0] decoded_dqm ;
input do_write_ack ;
input do_read_ack ;
input do_modeset_ack ;
input pwrup ;
input [31:0] wb_dat_i ;
output [31:0] wb_dat_o ;
reg [31:0] wb_dat_o ;
output wb_ack_o ;
input [3:0] wb_sel_i ;
input [31:0] wb_adr_i ;
input wb_we_i ;
input wb_cyc_i ;
input wb_stb_i ;
output [12:0] sd_adr_o ;
reg [12:0] sd_adr_o ;
output [1:0] sd_ba_o ;
output [31:0] sd_dat_o ;
reg [31:0] sd_dat_o ;
input [31:0] sd_dat_i ;
output [2:0] modereg_cas_latency;
output [2:0] modereg_burst_length;
wire [12:0] modereg_value = {3'b000, 1'b1, 2'b00, `SDRAM_CAS_LATENCY_VALUE, 1'b0, 3'b010} ;
assign modereg_cas_latency = modereg_value[6:4] ;
assign modereg_burst_length = modereg_value[2:0] ;
reg [25:4] read_buffer_tag ;
reg [31:0] read_buffer0 ;
reg [31:0] read_buffer1 ;
reg [31:0] read_buffer2 ;
reg [31:0] read_buffer3 ;
reg read_buffer0_valid ;
reg read_buffer1_valid ;
reg read_buffer2_valid ;
reg read_buffer3_valid ;
reg current_read_data_valid ;
wire keep_outputs = do_read || do_write || pwrup ;
always@
(
wb_adr_i or
read_buffer0 or
read_buffer1 or
read_buffer2 or
read_buffer3
)
begin
case(wb_adr_i[3:2])
2'b00:wb_dat_o = read_buffer0 ;
2'b01:wb_dat_o = read_buffer1 ;
2'b10:wb_dat_o = read_buffer2 ;
2'b11:wb_dat_o = read_buffer3 ;
endcase
end
always@
(
wb_adr_i or
read_buffer0_valid or
read_buffer1_valid or
read_buffer2_valid or
read_buffer3_valid
)
begin
case(wb_adr_i[3:2])
2'b00:current_read_data_valid = read_buffer0_valid ;
2'b01:current_read_data_valid = read_buffer1_valid ;
2'b10:current_read_data_valid = read_buffer2_valid ;
2'b11:current_read_data_valid = read_buffer3_valid ;
endcase
end
wire read_buffer_hit = (read_buffer_tag == wb_adr_i[25:4]) ;
// previous write acknowledge
// here if two clock domains are used, so acknowledge isn't asserted for two wb clock cycles in case of block transfer
reg do_write_ack_previous ;
always@(posedge wb_clk_i or posedge rst_i)
begin
if ( rst_i )
do_write_ack_previous <= #1 1'b0 ;
else
do_write_ack_previous <= #1 do_write_ack ;
end
assign wb_ack_o = wb_cyc_i &&
wb_stb_i &&
(
( wb_we_i && do_write_ack && !do_write_ack_previous ) ||
( !wb_we_i && read_buffer_hit && current_read_data_valid )
) ;
wire refill_buffer = wb_cyc_i && wb_stb_i && !wb_we_i && ( !read_buffer_hit || !current_read_data_valid ) ;
wire invalidate_current_buffer = wb_cyc_i && wb_stb_i && wb_we_i && read_buffer_hit ||
wb_cyc_i && wb_stb_i && !wb_we_i && !read_buffer_hit ;
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
read_buffer_tag <= #1 0 ;
else
if ( refill_buffer && !sd_rd_ena)
read_buffer_tag <= #1 wb_adr_i[25:4] ;
end
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
sd_dat_o <= #1 0 ;
else
if ( wb_cyc_i && wb_stb_i && wb_we_i && !keep_outputs)
sd_dat_o <= #1 wb_dat_i ;
end
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
decoded_dqm <= #1 4'hF ;
else
if ( wb_cyc_i && wb_stb_i && !keep_outputs)
decoded_dqm <= #1 ~wb_sel_i ;
end
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
do_write <= #1 1'b0 ;
else if ( do_write_ack )
do_write <= #1 1'b0 ;
else
do_write <= #1 do_write || ( wb_cyc_i && wb_stb_i && wb_we_i && !keep_outputs );
end
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
do_read <= #1 1'b0 ;
else if ( do_read_ack )
do_read <= #1 1'b0 ;
else
do_read <= #1 do_read || ( refill_buffer && !keep_outputs );
end
reg [8:0] column_address ;
reg [12:0] row_address ;
reg [1:0] bank_address ;
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
begin
column_address <= #1 0 ;
row_address <= #1 0 ;
bank_address <= #1 0 ;
end
else
if ( wb_cyc_i && wb_stb_i && !keep_outputs)
begin
column_address <= #1 wb_adr_i[10:2] ;
row_address <= #1 wb_adr_i[23:11] ;
bank_address <= #1 wb_adr_i[25:24] ;
end
end
// 32 bit implementation
reg [1:0] read_buffer_address ;
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
begin
read_buffer0_valid <= #1 1'b0 ;
read_buffer1_valid <= #1 1'b0 ;
read_buffer2_valid <= #1 1'b0 ;
read_buffer3_valid <= #1 1'b0 ;
end
else if ( invalidate_current_buffer )
begin
read_buffer0_valid <= #1 1'b0 ;
read_buffer1_valid <= #1 1'b0 ;
read_buffer2_valid <= #1 1'b0 ;
read_buffer3_valid <= #1 1'b0 ;
end
else if (sd_rd_ena)
begin
if ( read_buffer_address == 2'h0 )
read_buffer0_valid <= #1 1'b1 ;
if ( read_buffer_address == 2'h1 )
read_buffer1_valid <= #1 1'b1 ;
if ( read_buffer_address == 2'h2 )
read_buffer2_valid <= #1 1'b1 ;
if ( read_buffer_address == 2'h3 )
read_buffer3_valid <= #1 1'b1 ;
end
end
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
read_buffer_address <= #1 0 ;
else
if ( !sd_rd_ena )
read_buffer_address <= #1 column_address ;
else
read_buffer_address <= #1 read_buffer_address + 1'b1 ;
end
always@(posedge mem_clk_i or posedge rst_i)
begin
if ( rst_i )
begin
read_buffer0 <= #1 0 ;
read_buffer1 <= #1 0 ;
read_buffer2 <= #1 0 ;
read_buffer3 <= #1 0 ;
end
else if ( sd_rd_ena )
begin
if ( read_buffer_address == 2'h0 )
read_buffer0 <= #1 sd_dat_i ;
if ( read_buffer_address == 2'h1 )
read_buffer1 <= #1 sd_dat_i ;
if ( read_buffer_address == 2'h2 )
read_buffer2 <= #1 sd_dat_i ;
if ( read_buffer_address == 2'h3 )
read_buffer3 <= #1 sd_dat_i ;
end
end
// SDRAM SIDE ADDX
always @(sd_addx10_mux or modereg_value or row_address)
begin
case (sd_addx10_mux)
2'b00:sd_adr_o[10] = row_address[10];
2'b01:sd_adr_o[10] = 1'b0;
2'b10:sd_adr_o[10] = modereg_value[10];
2'b11:sd_adr_o[10] = 1'b1;
endcase
end
always @(sd_addx_mux or row_address or modereg_value)
begin
case (sd_addx_mux)
2'b00:sd_adr_o[12:11] = row_address[12:11]; // ROW
2'b01:sd_adr_o[12:11] = 2'b00; // COLUMN
2'b10:sd_adr_o[12:11] = modereg_value[12:11] ;
2'b11:sd_adr_o[12:11] = 2'b00;
endcase
end
always @(sd_addx_mux or row_address or column_address or modereg_value)
begin
case (sd_addx_mux)
2'b00:sd_adr_o[9:0] = row_address[9:0]; // ROW
2'b01:sd_adr_o[9:0] = {1'b0, column_address}; // COLUMN
2'b10:sd_adr_o[9:0] = modereg_value[9:0] ;
2'b11:sd_adr_o[9:0] = 10'h0;
endcase
end
assign sd_ba_o = bank_address ;
assign do_mode_set = 1'b0 ;
endmodule //sdram_dp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -