⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdram_dp.v

📁 sdram controller.verilog
💻 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 + -