再战SDRAM与资料整理。

news2024/11/20 18:22:23

       总之只要阅读操作手册,按照时序来,完全不难!

        器件记录: 

小梅哥AC620上SDRAM:M12L2561616A-6TG2T

        其的存储空间为16M*16=256MB,第二行的数字则与其速度等级有关;其分为:

        4bank*16bit*4M 即:8192*512 = 2^13 * 2^9 = 2^22 = 4M

        bank数目*数据位宽*存储深度

HY57V281620F,所以其具备的是

        4bank*16bits*2M 即 2^12 * 2^9 = 2^21 = 2M

SDRAM原理:

        SDRAM 存储数据是利用了电容能够保持电荷以及其充放电特性。一位数据的存取电路 如图 所示,该存储单元主要由行列选通三极管,存储电容,刷新放大器组成。对于这 一位的数据,首先需要打开行地址,然后打开列地址,则电容的电平状态就能呈现在数据线 (data_bit)上,即实现了读取。 或者,数据线上的电平值被送到电容上,从而实现写入数据。

        但是,打开行地址(激活行)是需要一定时间的,即从打开行地址到可以打开列地址进 行数据读/写,这之间有一定的时间间隔,这个间隔叫做 tRCD(ACTIVE-to-READ or WRITE delay),对于不同型号或不同速度等级的器件,这个值是不一样的。

        需要自行查阅产品手册获得这个速度等级,而M12L2561616A-6则对应的是速度等级6,其tRCD等于18ns。

        当列地址被打开后,数据并不是立即出现在最终的数据总线引脚上,而是有若干个时钟 的延迟,这个延迟叫做列选通潜伏期(CL,CL = CAS (READ) latency)。如图 32.3 为不同速 度等级的器件的列选通潜伏期值,速度等级不一样,其值也是不一样的。

用户手册原文:

        Bank activate 命令用于在空闲 Bank 中选择随机行。通过将 RAS 和 CS 以及所需的行和存储体地址置为低电平,即可启动行访问。从存储体激活时间起,经过 tRCD(min) 的时间延迟后,可以进行读或写操作。 tRCD是SDRAM的内部时序参数,因此它取决于工作时钟频率。

SDRAM命令

        不同的SDRAM命令是一样的,如果不一样说明可能使用的命令不是低有效吧。(或者有额外的命令控制)

执行时间

        除了在指定的命令外,我们还需要关心执行命令所需的时间。

        例如:

M12L2561616A-6TG2T:

        初始化时序(小梅哥文档):

tRP :预充电需要时间;

tRFC:自刷新需要的周期

tRAS:激活行需要的时间

tRCD:激活到读或写命令的延迟(激活行到列操作的时间)

HY57V281620F:

Brust length

        对于SDRAM来说,区分于RAM和FIFO的读写方法,并不是连续地给出读写使能和地址,而是一次读写操作"Brust length"长度的数据。

        SDRAM的读指令都是默认突发的,但是写指令可以不突发,直接写一整行。

自动刷新:

        自动刷新(AUTO REFRESH)一般用于对 SDRAM 进行常规操作的 过程中。该命令是非持续性的,即每次需要时,都需要发送此命令。在执 行自动刷新命令之前,所有的 BANK 必须被预充电(关闭)。在自动刷新 和预充电命令之间,必须间隔最少 tRP 时间。自动刷新时,行地址由 SDRAM 芯片内部的刷新控制器自动更新,因此,在执行自动刷新命令时, 用户不需要关心地址总线上的值。不管器件的数据位宽是多少,对于 256Mbit 的 SDRAM,在商业和工业级的器件中,每 64ms 内需要执行 8192 次自动刷新操作,即每 7.813us 执行一次;在汽车级的器件中,每 16ms 内 执行 8192 次自动刷新操作,即每 1.953us 执行一次。另外,自动刷新操作 也可以采用突发的方式执行,即每 64ms(商业和工业级)/16ms(汽车级) 都连续不间断的执行 8192 次自动刷新命令,然后其他时间再执行读写或 者其他命令。如图 32.10 为刷新过程示意图。

        一些差别:

        M12L2561616A-6TG2T的自动刷新需要先发送预充电命令(ALL BANK),而且需要发送两次刷新指令,即需要一个tRP和两个tRFC的时间,而HY57V281620F却不需要,仅需要发送刷新指令然后等待刷新完成即可。

        后面的读写时序其实根据不同的器件来看还是有很多不一样的步骤的,请按照自己的芯片的操作手册来,应该不会有问题。

        比较重要的是仲裁器的写法,根据划定好的优先级来约束就好了。

        可参考:

参数配置:

//COMMAND  = {CS_N,RAS_N,CAS_N,WE_N};
parameter  COMMAND_MRS          = 4'b0000 ;
parameter  COMMAND_ARF          = 4'b0001 ;
parameter  COMMAND_PRE          = 4'b0010 ;
parameter  COMMAND_ACT          = 4'b0011 ;
parameter  COMMAND_WRITE        = 4'b0100 ;
parameter  COMMAND_READ         = 4'b0101 ;
parameter  COMMAND_interrupt    = 4'b0110 ;
parameter  COMMAND_NOP          = 4'b0111 ;

//time_wait
parameter  TIME_WAIT_ABOVE_100US = 10000 ;//wait_time > 100us set:200us Power up wait time
parameter  TIME_PRE_CHARGE       = 2     ;//tRP       > 18ns  set:40ns; Precharge cost time
parameter  TIME_Auto_refresh     = 5     ;//tRFC=TRRC > 60ns  set:100ns ARF cost time
parameter  TIME_MRS_done_wait    = 2     ;//During 2CLK following this command, the SDRAM cannot accept any other commands. 

//MRS_OPCODE
parameter  INIT_OPMODE_Brust_Mode   = 1'b0   ;//A9
parameter  INIT_OPMODE_STANDRD      = 2'b00  ;//A8 A7
parameter  INIT_CAS_Latency         = 3      ;//A6 A5 A4 ;CAS Latency ( 2 & 3 ) 
parameter  INIT_Burst_type          = 1'b0   ;//A3 0:Sequential 1:Interleave
parameter  INIT_Burst_length        = 4      ;//A2 A1 A0 ;Burst Length ( 1, 2, 4, 8 & full page )
parameter  INIT_OPMODE_Brust_Length = (INIT_Burst_length == 1)?(3'b000):
                                      (INIT_Burst_length == 2)?(3'b001):
                                      (INIT_Burst_length == 4)?(3'b010):
                                      (INIT_Burst_length == 8)?(3'b011):(3'b111);//( 1, 2, 4, 8 & full page )
parameter  INIT_OPMODE_CL           = (INIT_CAS_Latency  == 2)?(3'b010):(3'b011);//A6 A5 A4 ;

//auto refresh
parameter ARF_PERIOD = 750;// ARF_period = Row_nums/64ms 64ms = 64_000us = 64_000_000ns = 3_200_000 cycles (1 ARF/782 cycles)
//ACT
parameter TIME_RCD = 3;//tRCD > 20ns act RAS to CAS delay


主控制器和仲裁: 

        1.状态机的状态位宽要对齐。

module SDRAM_CTRL_TOP #(
    parameter SDRAM_DATA_WIDTH   = 16,
    parameter SDRAM_BANK_WIDTH   = 2 ,
    parameter SDRAM_ADDR_WIDTH   = 12
)(
    input   wire         Sys_clk,
    input   wire         Rst_n  ,
//SDRAM 
    //COMMAND
    output  wire            SDRAM_CS_N      ,
    output  wire            SDRAM_RAS_N     ,
    output  wire            SDRAM_CAS_N     ,
    output  wire            SDRAM_WE_N      ,
    output  wire            SDRAM_CKE       ,
    output  wire    [1:0]   SDRAM_DQM       ,
    output  wire            SDRAM_CLK       ,
    output  reg     [SDRAM_ADDR_WIDTH-1:0]  SDRAM_A_ADDR    ,
    output  reg     [SDRAM_BANK_WIDTH-1:0]  SDRAM_BANK_ADDR ,
    //DATA
    inout           [SDRAM_DATA_WIDTH-1:0]  SDRAM_DQ        
);
`include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    localparam  STATE_IDLE = 6'b00_0001;
    localparam  STATE_INIT = 6'b00_0010;
    localparam  STATE_ARB  = 6'b00_0100;
    localparam  STATE_ARF  = 6'b00_1000;
    localparam  STATE_RD   = 6'b01_0000;
    localparam  STATE_WE   = 6'b10_0000;
    //Main
            reg  [3:0]                    SDRAM_COMMAND_SEND;
            reg  [5:0]                    STATE             ;
           wire  [SDRAM_DATA_WIDTH-1:0]   WR_SDRAM_DQ       ;
           wire                           WR_avai           ;
    //init
           wire                           INIT_DONE         ;
           wire  [3:0]                    COMMAND_INIT      ;       
           wire  [SDRAM_ADDR_WIDTH-1:0]   INIT_A_ADDR       ;
           wire  [SDRAM_BANK_WIDTH-1:0]   INIT_BANK_ADDR    ;
    //ARF
           wire                           ARF_access        ;
           wire  [3:0]                    COMMAND_REF       ;
           wire  [SDRAM_ADDR_WIDTH-1:0]   ARF_A_ADDR        ;
           wire  [SDRAM_BANK_WIDTH-1:0]   ARF_BANK_ADDR     ;
           wire                           REF_DONE          ;
           wire                           ARF_req           ;
    //WR
           wire                           WR_req            ;
           wire                           WR_access         ;
           wire  [3:0]                    COMMAND_WR        ;
           wire  [SDRAM_ADDR_WIDTH-1:0]   WR_A_ADDR         ;
           wire  [SDRAM_BANK_WIDTH-1:0]   WR_BANK_ADDR      ;
           wire                           WR_data_done      ;
           wire                           FIFO_WR_EN        ;
           wire  [7:0]                    FIFO_WR_data      ;
    //RD
           wire                           RD_req            ;
           wire                           RD_access         ;
           wire                           RD_data_done      ;
    //break
           wire                           Break_WR_to_ARF   ;
           wire                           Break_RD_to_ARF   ;
           wire                           Break_RD_to_WR    ;
    assign  WR_avai   = (STATE == STATE_WE)?1'b1:1'b0;
    assign  SDRAM_DQ  = (WR_avai == 1'b1)?WR_SDRAM_DQ :16'dz;
    assign  SDRAM_DQM = 2'b00  ;
    assign  SDRAM_CKE = 1'b1   ;
    assign  SDRAM_CLK = Sys_clk;
    assign  {SDRAM_CS_N,
             SDRAM_RAS_N,
             SDRAM_CAS_N,
             SDRAM_WE_N } = SDRAM_COMMAND_SEND;
    always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            SDRAM_COMMAND_SEND <= COMMAND_NOP;
        end else if(STATE == STATE_INIT) begin
            SDRAM_COMMAND_SEND <= COMMAND_INIT  ;
            SDRAM_A_ADDR       <= INIT_A_ADDR   ;
            SDRAM_BANK_ADDR    <= INIT_BANK_ADDR;
        end else if(STATE == STATE_ARF) begin
            SDRAM_COMMAND_SEND <= COMMAND_REF   ;
            SDRAM_A_ADDR       <= ARF_A_ADDR    ;
            SDRAM_BANK_ADDR    <= ARF_BANK_ADDR ;
        end else if(STATE == STATE_WE) begin
            SDRAM_COMMAND_SEND <= COMMAND_WR    ;
            SDRAM_A_ADDR       <= WR_A_ADDR     ;
            SDRAM_BANK_ADDR    <= WR_BANK_ADDR  ;
        end
    end
    //access
    assign ARF_access = (STATE == STATE_ARB) && (ARF_req == 1'b1);
    assign WR_access  = (STATE == STATE_ARB) && (WR_req  == 1'b1) 
                     && (ARF_req == 1'b0);
    assign RD_access  = (STATE == STATE_ARB) && (RD_req  == 1'b1) 
                     && (WR_req  == 1'b0   ) && (ARF_req == 1'b0);
//-------------------STATE MAIN-----------------------//
    always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            STATE <= STATE_IDLE;
        end else begin
            case (STATE) //ARG > WR > RD
                STATE_IDLE: begin
                    STATE <= STATE_INIT;
                end
                STATE_INIT: begin
                    if(INIT_DONE == 'd1) begin
                        STATE <= STATE_ARB;
                    end else begin
                        STATE <= STATE_INIT;
                    end
                end
                STATE_ARB: begin
                    if(ARF_req == 1'b1) begin
                        STATE <= STATE_ARF;
                    end else if(WR_req == 1'b1 && ARF_req == 1'b0) begin
                        STATE <= STATE_WE;
                    end else if(RD_req == 1'b1 && WR_req == 1'b0 && ARF_req == 1'b0) begin
                        STATE <= STATE_RD;
                    end else begin
                        STATE <= STATE_ARB;
                    end
                end
                STATE_ARF: begin
                    if(REF_DONE == 1'b1) begin
                        STATE <= STATE_ARB;
                    end else begin
                        STATE <= STATE_ARF;
                    end
                end
                STATE_WE: begin
                    if(Break_WR_to_ARF == 1'b1) begin
                        STATE <= STATE_ARB;
                    end else if(WR_data_done == 1'b1) begin
                        STATE <= STATE_ARB;
                    end else begin
                        STATE <= STATE_WE;
                    end
                end
                STATE_RD: begin
                    if(RD_data_done == 1'b1) begin
                        STATE <= STATE_ARB;
                    end else if(Break_RD_to_WR == 1'b1) begin
                        STATE <= STATE_ARB;
                    end else if(Break_RD_to_ARF == 1'b1) begin
                        STATE <= STATE_ARB;
                    end else begin
                        STATE <= STATE_RD;
                    end
                end
                default: begin
                    STATE <= STATE_IDLE;
                end
            endcase
        end
    end
/*-------------------instance begin---------------------------*/
SDRAM_INIT  INST0_SDRAM_INIT(
//input
    .Sys_clk                 ( Sys_clk         ),
    .Rst_n                   ( Rst_n           ),
//output
    .COMMAND_INIT            ( COMMAND_INIT    ),
    .INIT_A_ADDR             ( INIT_A_ADDR     ),
    .INIT_BANK_ADDR          ( INIT_BANK_ADDR  ),
    .INIT_DONE               ( INIT_DONE       )
);
SDRAM_ARF  INST0_SDRAM_ARF (
    .Sys_clk                 ( Sys_clk               ),
    .Rst_n                   ( Rst_n                 ),
    .INIT_DONE               ( INIT_DONE             ),
    .ARF_access              ( ARF_access            ),

    .COMMAND_REF             ( COMMAND_REF           ),
    .ARF_A_ADDR              ( ARF_A_ADDR            ),
    .ARF_BANK_ADDR           ( ARF_BANK_ADDR         ),
    .REF_DONE                ( REF_DONE              ),
    .ARF_req                 ( ARF_req               )
);
SDRAM_WR INST0_SDRAM_WR(
    .Sys_clk                 ( Sys_clk               ),
    .Rst_n                   ( Rst_n                 ),
    .FIFO_WR_EN              ( FIFO_WR_EN            ),
    .FIFO_WR_data            ( FIFO_WR_data          ),
    .INIT_DONE               ( INIT_DONE             ),
    .ARF_req                 ( ARF_req               ),
    .WR_access               ( WR_access             ),

    .COMMAND_WR              ( COMMAND_WR            ),
    .WR_A_ADDR               ( WR_A_ADDR             ),
    .WR_BANK_ADDR            ( WR_BANK_ADDR          ),
    .WR_data_done            ( WR_data_done          ),
    .WR_req                  ( WR_req                ),
    .Break_WR_to_ARF         ( Break_WR_to_ARF       ),
    .WRITE_SDRAM_DQ          ( WR_SDRAM_DQ           )
);
/*-------------------instance end-----------------------------*/
endmodule

初始化:

        1.初始化只需要进行一次。

module SDRAM_INIT(
    input   wire            Sys_clk       ,
    input   wire            Rst_n         ,
    output  reg     [ 3:0]  COMMAND_INIT  ,//COMMAND  = {CS_N,RAS_N,CAS_N,WE_N}
    output  reg     [11:0]  INIT_A_ADDR   ,
    output  reg     [ 1:0]  INIT_BANK_ADDR,
    output  reg             INIT_DONE
);
    `include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    localparam TIME_TO_PRE   = TIME_WAIT_ABOVE_100US;
    localparam TIME_TO_ARF   = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE;
    localparam TIME_TO_ARF_2 = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE 
                             + TIME_Auto_refresh;
    localparam TIME_TO_MRS   = TIME_WAIT_ABOVE_100US + TIME_PRE_CHARGE 
                             + TIME_Auto_refresh + TIME_Auto_refresh;
    localparam INIT_END      = TIME_TO_MRS + TIME_MRS_done_wait     ;

            reg     [13:0]  INIT_CNT     ;
            reg             INIT_DONE_NOW;
            
    always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            INIT_DONE <= 'd0;
        end else if(INIT_CNT == INIT_END) begin
            INIT_DONE <= 'd1;
        end else begin
            INIT_DONE <= 'd0;
        end
    end
    always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            INIT_DONE_NOW <= 1'b0;
        end else if(INIT_CNT == INIT_END) begin
            INIT_DONE_NOW <= 1'b1;
        end else begin
            INIT_DONE_NOW <= INIT_DONE_NOW;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            INIT_CNT <= 'd0;
        end else if(INIT_DONE_NOW == 1'b0) begin
            if(INIT_CNT == INIT_END) begin
                INIT_CNT <= 'd0;
            end else begin
                INIT_CNT <= INIT_CNT + 1'b1;
            end
        end else begin
            INIT_CNT <= 'd0;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            COMMAND_INIT   <= COMMAND_NOP;
            INIT_A_ADDR    <= 12'd0      ;
            INIT_BANK_ADDR <= 2'b00      ;
        end else begin
            case (INIT_CNT)
                TIME_TO_PRE: begin
                    COMMAND_INIT      <= COMMAND_PRE;
                    INIT_A_ADDR[10]   <= 1'b1;
                end
                TIME_TO_ARF: begin
                    COMMAND_INIT <= COMMAND_ARF;
                end
                TIME_TO_ARF_2: begin
                    COMMAND_INIT <= COMMAND_ARF;
                end
                TIME_TO_MRS: begin
                    COMMAND_INIT <= COMMAND_MRS;
                    INIT_A_ADDR       <= {
                        2'b00                   ,//A11 A10
                        INIT_OPMODE_Brust_Mode  ,//A9
                        INIT_OPMODE_STANDRD     ,//A8 A7
                        INIT_OPMODE_CL          ,//A6 A5 A4 ;CAS Latency ( 2 & 3 ) 
                        INIT_Burst_type         ,//A3 0:Sequential 1:Interleave          
                        INIT_OPMODE_Brust_Length //A2 A1 A0 ;Burst Length ( 1, 2, 4, 8 & full page )
                    };
                end
                default:begin
                    COMMAND_INIT   <= COMMAND_NOP;
                    INIT_A_ADDR    <= 12'd0      ;
                    INIT_BANK_ADDR <= 2'b00		;
                end
            endcase
        end
	end
endmodule

刷新: 

module SDRAM_ARF #(

)(
    input   wire        Sys_clk,
    input   wire        Rst_n  ,
    //SDRAM
    input   wire            INIT_DONE     ,
    output  reg     [3:0]   COMMAND_REF   ,
    output  reg     [11:0]  ARF_A_ADDR    ,
    output  reg     [ 1:0]  ARF_BANK_ADDR ,
    output  reg             REF_DONE      ,
    output  reg             ARF_req       ,
    input   wire            ARF_access    
);
`include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
    localparam  TIME_ARF_BEGIN   = 1'b1                  ;
    // localparam  TIME_PRE_to_ARF  = 1'b1 + TIME_PRE_CHARGE;
    // localparam  TIME_ARF_to_done = 1'b1 + TIME_PRE_CHARGE + TIME_Auto_refresh;
    localparam  TIME_ARF_to_done = 'd9;
            reg  [9:0]  ARF_CNT    ;
            reg  [3:0]  COMMAND_CNT;
//ARF_CNT
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            ARF_req <= 'd0;
        end else if(ARF_access == 1'b1) begin
            ARF_req <= 1'b0;
        end else if(ARF_CNT == ARF_PERIOD) begin
            ARF_req <= 1'b1;
        end
    end
    always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            ARF_CNT <= 'd0;
        end else if(INIT_DONE == 1'b1) begin
            ARF_CNT <= 'd1;
        end else if(ARF_CNT == ARF_PERIOD) begin
            ARF_CNT <= 'd1;
        end else if(ARF_CNT > 'd0) begin
            ARF_CNT <= ARF_CNT + 1'd1;
        end else begin
            ARF_CNT <= ARF_CNT;
        end
    end
always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            REF_DONE <= 1'b0;
        end else if(COMMAND_CNT == TIME_ARF_to_done) begin
            REF_DONE <= 1'b1;
        end else begin
            REF_DONE <= 1'b0;
        end
    end
//COMMAND_CNT
    always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            COMMAND_CNT <= 'd0;
        end else if(ARF_access == 1'b1) begin
            COMMAND_CNT <= 'd1;
        end else if(COMMAND_CNT == TIME_ARF_to_done) begin
            COMMAND_CNT <= 'd0;
        end else if(COMMAND_CNT > 'd0) begin
            COMMAND_CNT <= COMMAND_CNT + 1'b1;
        end else begin
            COMMAND_CNT <= COMMAND_CNT;
        end
    end
//COMMAND
    always@(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            COMMAND_REF   <= COMMAND_NOP;
            ARF_A_ADDR    <= 12'd0      ;
            ARF_BANK_ADDR <= 2'b00      ;
        end else if(COMMAND_CNT == TIME_ARF_BEGIN) begin
            COMMAND_REF   <= COMMAND_ARF;
        end else begin
            COMMAND_REF   <= COMMAND_NOP;
            ARF_A_ADDR    <= 12'd0      ;
            ARF_BANK_ADDR <= 2'b00      ;
        end
    end
//COMMAND other SDRAM
    // always@(posedge Sys_clk or negedge Rst_n) begin
    //     if(Rst_n == 'd0) begin
    //         COMMAND_REF   <= COMMAND_NOP;
    //         ARF_A_ADDR    <= 12'd0      ;
    //         ARF_BANK_ADDR <= 2'b00      ;
    //     end else begin
    //         case (COMMAND_CNT)
    //             TIME_ARF_BEGIN:  begin
    //                 COMMAND_REF    <= COMMAND_PRE;
    //                 ARF_A_ADDR[10] <= 1'b1       ;
    //             end
    //             TIME_PRE_to_ARF: begin
    //                 COMMAND_REF   <= COMMAND_ARF;
    //             end
    //             default: begin
    //                 COMMAND_REF   <= COMMAND_NOP;
    //                 ARF_A_ADDR    <= 12'd0      ;
    //                 ARF_BANK_ADDR <= 2'b00      ;
    //             end
    //         endcase
    //     end
    // end
endmodule

写入:

        1.注意每一行结束以后要重新激活。

        2.写完了就不要继续req了。

//SDRAM SIZE = 8192X512X16
  //8192ROWS 512COLS 16BITS
module SDRAM_WR #(
    parameter SDRAM_COLS_MAX  = 128,
    parameter IMAGE_NEED_ROW  = 300, //300 = 640*480*8/16*512 
    parameter TIME_PRE_CHARGE_long = 8
)(
    input   wire        Sys_clk,
    input   wire        Rst_n  ,
    //FIFO
    input   wire            FIFO_WR_EN   ,//8bits
    input   wire    [ 7:0]  FIFO_WR_data ,
    //SDRAM
    input   wire            INIT_DONE    ,
    output  reg     [ 3:0]  COMMAND_WR   ,
    output  reg     [11:0]  WR_A_ADDR    ,
    output  reg     [ 1:0]  WR_BANK_ADDR ,
    output  wire            WR_data_done ,
    output  reg             WR_req       ,
    input   wire            ARF_req      ,
    output  reg             Break_WR_to_ARF,
    input   wire            WR_access    ,
    output  wire    [15:0]  WRITE_SDRAM_DQ    
);
`include "D:/three_verilog/SDRAM/SDRAM_init/rtl/sdram_param.h"
            localparam  STATE_IDLE      = 5'b0_0001;
            localparam  STATE_WR_wait   = 5'b0_0010;
            localparam  STATE_ACT       = 5'b0_0100;
            localparam  STATE_WR_NOW    = 5'b0_1000;
            localparam  STATE_Precharge = 5'b1_0000;
            reg     [ 4:0]       STATE         ;
            reg     [ 1:0]       CNT_ACT       ;
            reg     [ 9:0]       CNT_SDRAM_COLS;
            reg     [12:0]       CNT_SDRAM_ROWS;
            wire                 ROWS_END_Flag ;
            reg     [ 1:0]       CNT_Brust     ;
            reg     [ 3:0]       CNT_Precharge ;
            reg                  Done_image    ;
    //FIFO
            wire                 FIFO_FULL     ;
            wire                 FIFO_EMPTY    ;
            wire    [ 9:0]       FIFO_RD_cnt   ;
            reg                  FIFO_RD_EN    ;
            wire    [15:0]       FIFO_RD_DATA  ;
    assign WRITE_SDRAM_DQ = FIFO_RD_DATA;
//FIFO_RD_EN
always @(posedge Sys_clk or negedge Rst_n) begin
    if(Rst_n == 'd0) begin
        FIFO_RD_EN <= 'd0;
    end else if(STATE == STATE_WR_NOW) begin
        FIFO_RD_EN <= 1'b1;
    end else begin
        FIFO_RD_EN <= 'd0;
    end
end
//WR_req
    always @(posedge Sys_clk or negedge Rst_n) begin
    if(Rst_n == 'd0) begin
        WR_req <= 'd0;
    end else if(FIFO_RD_cnt >= 512 && STATE == STATE_WR_wait && Done_image == 'd0) begin
        WR_req <= 1'b1;
    end else if(WR_access == 1'b1  && STATE == STATE_WR_wait) begin 
        WR_req <= 'd0;
    // end else if(Break_WR_to_ARF == 1'b1 && Done_image == 'd0) begin //通过uart写入FIFO的数据速度太慢了,SDRAM的写入速度非常快,这行会导致读出大量的重复数据写入SDRAM
    //     WR_req <= 1'b1;
    end else if(Done_image == 1'b1) begin
        WR_req <= 'd0;
    end else begin
        WR_req <= WR_req;
    end
end
//Done_image
    // always @(posedge Sys_clk or negedge Rst_n) begin
    //     if(Rst_n == 'd0) begin
    //         Done_image <= 'd0;
    //     end else if(STATE == STATE_WR_NOW
    //     && (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1 )
    //     && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)    
    //     && (CNT_Brust == INIT_Burst_length -1'b1)) begin
    //         Done_image <= 1'b1;
    //     end else if(STATE == STATE_Precharge && CNT_Precharge == TIME_PRE_CHARGE_long) begin
    //         Done_image <= 'd0;
    //     end else begin
    //         Done_image <= Done_image;
    //     end
    // end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            Done_image <= 'd0;
        end else if(STATE == STATE_WR_NOW
        && (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1 )
        && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)    
        && (CNT_Brust == INIT_Burst_length -1'b1)) begin
            Done_image <= 1'b1;
        end else begin
            Done_image <= Done_image;
        end
    end
//WR_data_done
    assign WR_data_done = (STATE == STATE_Precharge 
        && CNT_Precharge == TIME_PRE_CHARGE_long 
        && Done_image == 1'b1);
    // always @(posedge Sys_clk or negedge Rst_n) begin
    //     if(Rst_n == 'd0) begin
    //         WR_data_done <= 'd0;
    //     end else if(STATE == STATE_Precharge 
    //     && CNT_Precharge == TIME_PRE_CHARGE_long 
    //     && Done_image == 1'b1) begin
    //         WR_data_done <= 1'b1;
    //     end else begin
    //         WR_data_done <= 'd0;
    //     end
    // end
//Break_WR_to_ARF
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            Break_WR_to_ARF <= 'd0;
        end else if(STATE == STATE_Precharge 
        && CNT_Precharge == TIME_PRE_CHARGE_long 
        && Done_image == 1'b0) begin
            Break_WR_to_ARF <= 'd1;
        end else begin
            Break_WR_to_ARF <= 'd0;
        end
    end
//CNT_ACT
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            CNT_ACT <= 'd0;
        end else if(STATE == STATE_ACT) begin
            if(CNT_ACT == TIME_RCD) begin
                CNT_ACT <= 'd0; 
            end else begin
                CNT_ACT <= CNT_ACT + 1'b1;
            end
        end else begin
            CNT_ACT <= 'd0;
        end
    end
//CNT_Brust
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            CNT_Brust <= 'd0;
        end else if(STATE == STATE_WR_NOW) begin
            if(CNT_Brust == INIT_Burst_length -1'b1) begin
                CNT_Brust <= 'd0;
            end else begin
                CNT_Brust <= CNT_Brust + 1'b1;
            end
        end else begin
            CNT_Brust <= 'd0;
        end
    end
//CNT_SDRAM_ROWS
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            CNT_SDRAM_ROWS <= 'd0;
        end else if(STATE == STATE_WR_NOW) begin
            if (CNT_SDRAM_ROWS == IMAGE_NEED_ROW - 1'b1 
            && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
            && (CNT_Brust == INIT_Burst_length -1'b1)) begin
                CNT_SDRAM_ROWS <= 'd0;
            end else if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1)
            && (CNT_Brust == INIT_Burst_length -1'b1)) begin
                CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS + 1'b1;
            end else begin
                CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
            end
        end else begin
            CNT_SDRAM_ROWS <= CNT_SDRAM_ROWS;
        end
    end
//CNT_SDRAM_COLS
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            CNT_SDRAM_COLS <= 'd0;
        end else if(STATE == STATE_WR_NOW) begin
            if((CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1) 
            && (CNT_Brust == INIT_Burst_length -1'b1)) begin
                CNT_SDRAM_COLS <= 'd0;
            end else if(CNT_Brust == INIT_Burst_length -1'b1) begin
                CNT_SDRAM_COLS <= CNT_SDRAM_COLS + 1'b1;
            end else begin
                CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
            end
        end else begin
            CNT_SDRAM_COLS <= CNT_SDRAM_COLS;
        end
    end
assign ROWS_END_Flag  = (STATE == STATE_WR_NOW) && (CNT_SDRAM_COLS == SDRAM_COLS_MAX - 1'b1) && (CNT_Brust == INIT_Burst_length -1'b1);
//CNT_Precharge
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            CNT_Precharge <= 'd0;
        end else if(STATE == STATE_Precharge && CNT_Precharge == TIME_PRE_CHARGE_long) begin
            CNT_Precharge <= 'd0;
        end else if(STATE == STATE_Precharge) begin
            CNT_Precharge <= CNT_Precharge + 1'b1;
        end else begin
            CNT_Precharge <= CNT_Precharge;
        end
    end
//COMMAND
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            COMMAND_WR   <= COMMAND_NOP;
            WR_A_ADDR    <= 12'd0      ;
            WR_BANK_ADDR <= 2'b00      ;
        end else if(STATE == STATE_WR_wait && WR_access == 1'b1) begin
            COMMAND_WR   <= COMMAND_ACT;
            WR_A_ADDR    <= CNT_SDRAM_ROWS;//row_addr
            WR_BANK_ADDR <= 2'b00      ;
        end else if(STATE == STATE_WR_NOW  && CNT_Brust  == 'd0) begin
            COMMAND_WR   <= COMMAND_WRITE;
            WR_A_ADDR    <= CNT_SDRAM_COLS<<2'd2;
            WR_BANK_ADDR <= 2'b00      ;
        end else if(STATE == STATE_Precharge && CNT_Precharge == 'd0) begin
            COMMAND_WR <= COMMAND_PRE;
            WR_A_ADDR[10]<= 1'b1       ;
            WR_BANK_ADDR <= 2'b00      ;
        end else begin
            COMMAND_WR   <= COMMAND_NOP;
            WR_A_ADDR    <= 12'd0      ;
            WR_BANK_ADDR <= 2'b00      ;
        end
    end
//STATE
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(Rst_n == 'd0) begin
            STATE <= STATE_IDLE;
        end else begin
            case (STATE)
                STATE_IDLE: begin
                    if(INIT_DONE == 1'b1) begin
                        STATE <= STATE_WR_wait;
                    end else begin
                        STATE <= STATE_IDLE;
                    end
                end
                STATE_WR_wait: begin
                    if(WR_access == 1'b1) begin
                        STATE <= STATE_ACT;
                    end else begin
                        STATE <= STATE_WR_wait;
                    end
                end
                STATE_ACT: begin
                    if(ARF_req == 1'b1 && CNT_ACT == TIME_RCD) begin
                        STATE <= STATE_Precharge;
                    end else if(CNT_ACT == TIME_RCD) begin
                        STATE <= STATE_WR_NOW;
                    end else begin
                        STATE <= STATE_ACT;
                    end
                end
                STATE_WR_NOW:begin
                    if(ARF_req == 1'b1 && CNT_Brust == INIT_Burst_length - 1'b1) begin
                        STATE <= STATE_Precharge;
                    end else if(ROWS_END_Flag == 1'b1) begin
                        STATE <= STATE_Precharge;
                    end else if(Done_image == 1'b1) begin
                        STATE <= STATE_Precharge;
                    end else begin
                        STATE <= STATE_WR_NOW;
                    end
                end
                STATE_Precharge: begin
                    if(CNT_Precharge == TIME_PRE_CHARGE_long) begin
                        STATE <= STATE_WR_wait;
                    end else begin
                        STATE <=  STATE_Precharge;
                    end
                end
                default: begin
                    STATE <= STATE_IDLE;
                end
            endcase
        end
    end
/*------------------------------------------------------------------------*/
AS_FIFO_w2048x8_r1024x16 INST0_AS_FIFO_w2048x8_r1024x16 (
  .wr_clk       ( Sys_clk       ), // input wr_clk
  .rd_clk       ( Sys_clk       ), // input rd_clk
  .din          ( FIFO_WR_data  ), // input [7 : 0] din
  .wr_en        ( FIFO_WR_EN    ), // input wr_en
  .rd_en        ( FIFO_RD_EN    ), // input rd_en
  .dout         ( FIFO_RD_DATA  ), // output [15 : 0] dout
  .full         ( FIFO_FULL     ), // output full
  .empty        ( FIFO_EMPTY    ), // output empty
  .rd_data_count( FIFO_RD_cnt   )  // output [9 : 0] rd_data_count
  /*------------------------------------------------------------------------*/
);
endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1017378.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NLP(6)--Diffusion Model

目录 一、Flow-Based General Model 1、概述 2、函数映射关系 3、Coupling Layer 4、Glow 二、Diffusion Model 1、概述 2、前向过程 3、反向过程 4、训练获得噪声估计模型 5、生成图片 三、马尔科夫链 一、Flow-Based General Model 1、概述 Flow-Based General…

C 通过宏定义重定义malloc - free,预防内存泄露

系列文章目录 C模版基础 文章目录 目录 代码地址 相关说明 使用案例 代码地址 GitHub - CHENLitterWhite/CPPWheel: CPP自封装的库 /* * 作者: 干饭小白 * 时间: 2023-09-25 16:00:00:00 * * 说明: * 只能检测 malloc 和 free,无法检测 new delete */ #pra…

[Linux入门]---Linux指令②

文章目录 Linux系统常用指令1.man指令2.echo3.cp指令&#xff08;重要&#xff09;4.mv指令&#xff08;重要&#xff09;&#xff1a;5.alias指令6.cat指令7.more指令8.less指令&#xff08;重要&#xff09;9.head指令10.tail指令11.时间相关的指令1.在显示方面2.在设定时间方…

Redis环境配置

【Redis解压即可】链接&#xff1a;https://pan.baidu.com/s/1y4xVLF8-8PI8qrczbxde9w?pwd0122 提取码&#xff1a;0122 【Redis桌面工具】 链接&#xff1a;https://pan.baidu.com/s/1IlsUy9sMfh95dQPeeM_1Qg?pwd0122 提取码&#xff1a;0122 Redis安装步骤 1.先打开Redis…

OpenAI开发系列(二):大语言模型发展史及Transformer架构详解

全文共1.8w余字&#xff0c;预计阅读时间约60分钟 | 满满干货&#xff0c;建议收藏&#xff01; 一、介绍 在2020年秋季&#xff0c;GPT-3因其在社交媒体上病毒式的传播而引发了广泛关注。这款拥有超过1.75亿参数和每秒运行成本达到100万美元的大型语言模型&#xff08;Large …

【力扣周赛】第 362 场周赛(⭐差分匹配状态压缩DP矩阵快速幂优化DPKMP)

文章目录 竞赛链接Q1&#xff1a;2848. 与车相交的点解法1——排序后枚举解法2——差分数组⭐差分数组相关题目列表&#x1f4d5;1094. 拼车1109. 航班预订统计2381. 字母移位 II2406. 将区间分为最少组数解法1——排序贪心优先队列解法2——差分数组 2772. 使数组中的所有元素…

加密算法发展简介

1&#xff1a;对称加密算法 客户端加密数据和服务端解密数据&#xff0c;使用的相同的秘钥&#xff1a; 固定秘钥&#xff1a;双方约定好一个固定秘钥&#xff1b; 随机秘钥&#xff1a;双方约定每次建立连接的时候&#xff0c;某固定BYTE为秘钥&#xff1b; 缺点&#xff1a…

【MySQL】 MySQL数据库基础

文章目录 &#x1f431;‍&#x1f453;数据库的操作&#x1f4cc;显示当前的数据库&#x1f4cc;创建数据库&#x1f388;语法&#xff1a;&#x1f388;语法说明&#x1f388;示例&#xff1a; &#x1f334;使用数据库&#x1f38b;删除数据库&#x1f431;‍&#x1f3cd;语…

sql注入Less-2

后台sql s q l " S E L E C T ∗ F R O M u s e r s W H E R E i d sql "SELECT * FROM users WHERE id sql"SELECT∗FROMusersWHEREidid LIMIT 0,1"; 注入语句 http://192.168.200.26/Less-3/?id-1? union select 1,2,database();– 使用id-1 便可…

JavaScript中的Hoisting机制

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ JavaScript 中的 Hoisting 机制⭐ 变量提升⭐ 函数提升⭐ 注意事项⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xf…

LVS+Keepalived 高可用集群

LVSKeepalived 高可用集群 1、Keepalived工具介绍2、vrrp协议&#xff08;虚拟路由冗余协议&#xff09;2.1vrrrp是什么&#xff1f;2.2vrrp工作过程2.3Keeplived、VRRP及其工作原理2.4Keepalived体系主要模块 3、搭建LVSKeepalived 高可用集群 1、Keepalived工具介绍 支持故障…

MFC-GetSystemFirmwareTable获取系统固件表

获取ACPI表格 void CgetSystemFirmwareTableDlg::OnBnClickedButton1() {//UINT bufferSize GetSystemFirmwareTable(ACPI, 0, NULL, 0);//获取系统固件表/*【参数3和参数4为NULL和0&#xff0c;只是为了返回真实大小】这个函数可以用来获得系统中的各种固件信息&#xff0c;如…

MySQL中SQL语句执行顺序分析

1、 MySQL手写执行顺序 2、 MySQL机读执行顺序 随着Mysql版本的更新换代&#xff0c;其优化器也在不断的升级&#xff0c;优化器会分析不同执行顺序产生的性能消耗不同而动态调整执行顺序。下面是经常出现的查询顺序&#xff1a;

SpringBoot使用Mybatis查询数据

1.创建工程 说明&#xff1a;创建springboot工程&#xff0c;数据库表book&#xff0c;实体类Book 1.1创建项目 1.2 勾选相应的配置 1.3数据表book 说明&#xff1a;创建了book表&#xff0c;添加了id,type,name,description字段。 1.4创建Book实体类 说明&#xff1a;生成…

微服务保护-流控效果

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

【AI】推理系统和推理引擎的整体架构

本文主要是对 B 站 Up 主 ZOMI酱 推理系统系列视频 的理解&#xff0c;可以认为是重点笔记。 一、深度学习模型的全生命周期 相信很多人和我一样&#xff0c;刚看到深度学习模型中的推理系统或推理引擎时是一头雾水&#xff0c;因为学习 DL 时通常关注于模型的设计和训练。下图…

MFC - 一文带你从小白到项目应用(全套1)

文章篇幅可能会比较长&#xff0c;从入门到基本能上项目的全部内容。建议观看的过程中&#xff0c;用电脑跟着学习案例。 持续输出优质文章是作者的追求&#xff0c;因为热爱&#xff0c;所以热爱。 最近看动漫被一句鸡汤感动到了&#xff0c;也送给各位朋友&#xff1a; 只要有…

微服务保护-热点参数限流

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

Dubbo3基础使用

1、Dubbo概述 现在SpringCloud Alibaba比较火&#xff0c;用的比较多是吧&#xff0c;那dubbo是不是过时的呢&#xff1f; 并不是的&#xff0c;以前有人把Dubbo和SpringCloud进行对比&#xff0c;其实两者是不同维度的&#xff0c;不能对比&#xff0c;dubbo就是一个rpc框架&…

Adobe Bridge 2024:解锁创意力的数字媒体利器

在当今数字化的时代&#xff0c;创意工作者们需要处理和管理大量的数字媒体资源&#xff0c;如照片、视频、音频等。为了提高工作效率和创作质量&#xff0c;他们需要一个功能强大、易于使用的工具来组织、浏览和共享这些媒体文件。幸运的是&#xff0c;Adobe Bridge 2024 正好…