Trust me, SDRAM is really not difficult -- read operation (page burst mode)

1. Read operation

         SDRAM provides a variety of data reading methods, such as single reading, page burst reading (burst length 1, 2, 4, 8, full page), etc. At present, this paper only explains and simulates the full page burst mode, and provides explanations and simulations of other writing methods as appropriate.

2. Full page burst read operation

         It should be noted that most SDRAM does not support automatic precharge in case of full page burst, so our read operation sequence includes manual precharge. The sequence diagram is as follows:

Each signal is described as follows:

        CK: working clock. The specific clock frequency varies according to different chips  

        CKE: clock enable, which needs to be pulled up during the whole burst reading process (in fact, all other operations need to be pulled up except pulling down in sleep mode)

        COMMAND: SDRAM commands are spliced by four lines, namely CS # (chip selection signal), RAS # (row gating signal), CAS # (column gating signal) and WE # (write enable signal). Through these four COMMAND lines, combined with SDRAM address, input and output data, various COMMAND operations can be carried out on SDRAM

        DQM/DQML,DQMU: data mask, which can "bury" a bit of input or output data, that is, invalidate a bit

        A[9:0],A[12:11]: data address line, which can also be used to set the mode register

        A10: data address line, which can also be used to enable some specific operations, such as controlling the number of automatic precharge enabling and enabling precharge bank s

        BA[1:0]: bank address

        DQ data: data bus. In the process of burst reading, it is necessary to obtain the data output by SDRAM on the data bus according to the timing

Through the analysis of the sequence diagram, the initialization process can be summarized as follows:

        1. Send the activation instruction, output the bank address of the data to be written on the bank bus, and output the row address of the data to be written on the address bus, so this operation is also called "row activation"

        2. After sending the activation command, you need to wait for a certain time, that is, tRCD. During this period, you also need to send the NOP null command (the null command is sent to prevent misoperation of SDRAM)

        3. After waiting, send the read instruction, output the column head address of the data to be read on the address bus, and then wait for the latency (CL, CAS latency) clock cycle

        4. After the incubation period, the data bus starts to output data, and then data is output in each cycle until the burst termination instruction is sent to SDRAM to end the burst reading, so as to realize the control of burst length (it can not exceed the maximum number of one line of data, i.e. 2 * 9 = 512 data)

        6. Send a precharge command to precharge all banks. Pulling A10 high means that all banks are selected

        7. After the precharge operation, you need to wait for a certain time, that is, tRP. During this period, you also need to send NOP null command (the null command is sent to prevent misoperation of SDRAM)

        8. After the Trp time, a burst write operation is completed

3. State machine

         According to the sequence diagram of burst reading, it is not difficult to draw the following state machine:

Describe each state, state jump condition and output:

  • RD_IDLE:   In the initial state, when the initialization completion signal is pulled high (initialization is completed) and the arbitration module sends a burst read enable signal, it jumps to the next state RD_ACT, send NOP command in this state
  • RD_ACT:   The row is ACTIVE, only one clock cycle is maintained, and then jump to the next state RD_TRCD, send line activation instruction (ACTIVE) + bank address + line address
  • RD_TRCD: line activation waiting state. After the waiting time in this state meets tRCD, it will jump to the next state RD_WR, send NOP command in this state  
  • RD_WR:     Column READ / write state, only maintain one clock cycle, and then jump to the next state RD_CL, send READ instruction (READ) + bank address + column head address
  • RD_CL:       Latency waiting state. After the waiting time in this state meets Cl, it jumps to the next state RD_DATA, send NOP instruction in this state  
  • RD_DATA: data reading status. In this status, send NOP instruction first and register the data on the data bus at the same time; When all the data to be read is output (CL clock cycles in advance, because the data reading will lag CL clock cycles), send a burst termination instruction (BURST TERM), terminate the read operation and jump to RD_PRE status
  • RD_PRE:   Send the PRECHARGE command state, maintain only one clock cycle, and then jump to the next state RD_TRP, send line PRECHARGE command (PRECHARGE) + A10 pull up
  • RD_TRP:   Precharge command waiting state. After the waiting time in this state meets Trp, jump to the next state RD_END, send NOP command in this state  
  • RD_END: this status raises the burst write flag completion signal wr_end one cycle, tell the arbitration module that the write operation is completed, so that the arbitration module can arbitrate the refresh, write, read and other requests (to prevent timing conflicts)

4. Interface definition and overall design

         The overall block diagram, input and output signals of the burst read module written by Verilog are as follows:

The signal description is as follows:

Signal nameBit widthattributedescribe
rd_clk1inputClock signal, 100M
rd_rst_n1inputReset signal, active at low level
init_end1inputInitialization completion signal. Read operation can be performed only after initialization is completed
rd_en1inputRead enable signal, which can be read only after the signal is pulled high
rd_addr24inputSome addresses of read operation are composed of bank address (2 bits), row address (13 bits) and column address (9 bits)
rd_data16inputData read from SDRAM
rd_burst_len10inputLength of a burst read
rd_ack1outputRead operation response signal, indicating that the module has read SDRAM
rd_end1outputThe read operation end signal only maintains one clock cycle after the end of the read operation
rd_sdram_cmd4output13 bit SDRAM address
rd_sdram_bank2output4-bit SDRAM command, consisting of {CS#,RAS#,CAS#,WE #}
rd_sdram_addr13output2-digit BANK address, 4 banks in total
rd_sdram_data16outputData read from SDRAM output to arbitration module

  5. Verilog code

         According to the above state machine description and overall design, it is not difficult to write Verilog code for module implementation (the comments are very detailed):

`timescale  1ns/1ns

module  sdram_read
(
    input   wire            rd_clk			,   //System clock, frequency 100MHz
    input   wire            rd_rst_n		,   //Reset signal, active at low level
    input   wire            init_end        ,   //Initialization end signal
    input   wire            rd_en           ,   //Read enable
    input   wire    [23:0]  rd_addr         ,   //Read SDRAM address
    input   wire    [15:0]  rd_data         ,   //Data read from SDRAM
    input   wire    [9:0]   rd_burst_len    ,   //Burst length

    output  wire            rd_ack          ,   //Read SDRAM response signal
    output  wire            rd_end          ,   //End of a burst read
    output  reg     [3:0]   rd_sdram_cmd	,   //Instructions written to sdram in the read data stage, {cs_n,ras_n,cas_n,we_n}
    output  reg     [1:0]   rd_sdram_bank	,   //Read data stage Bank address
    output  reg     [12:0]  rd_sdram_addr	,   //Address data, auxiliary precharge operation, row and column address, A12-A0,13 bit address
    output  wire    [15:0]  rd_sdram_data       //Data read out by SDRAM
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//parameter     define
parameter   TRCD =	10'd2   ,   		//Activation waiting period
            TCL  =	10'd3   ,   		//incubation period
            TRP  =	10'd4   ;   		//Precharge waiting period
			
parameter   RD_IDLE     =   4'b0000 ,   //free
            RD_ACT	    =   4'b0001 ,   //Row activation
            RD_TRCD     =   4'b0011 ,   //Activation wait
            RD_READ     =   4'b0010 ,   //Read operation
            RD_CL       =   4'b0100 ,   //incubation period
            RD_DATA     =   4'b0101 ,   //Read data
            RD_PRE      =   4'b0111 ,   //Precharge
            RD_TRP      =   4'b0110 ,   //Precharge wait
            RD_END      =   4'b1100 ;   //End of a burst read
parameter   NOP         =   4'b0111 ,   //Empty operation instruction
            ACTIVE      =   4'b0011 ,   //Activate command
            READ        =   4'b0101 ,   //Data read instruction
            BURST_STOP  =   4'b0110 ,   //Burst stop command
            PRECHARGE   =   4'b0010 ;   //Precharge command

//wire  define
wire		trcd_end_flag    ;   		//End of activation waiting cycle
wire		trp_end_flag     ;   		//End of precharge waiting period
wire		tcl_end_flag     ;   		//Latency end flag
wire		tread_end_flag   ;   		//Burst read end
wire		rdburst_end_flag ;   		//Read burst termination
		
//reg   define		
reg	[3:0]   state_cur  		;    		//SDRAM write status
reg	[3:0]   state_next  	;    		//SDRAM write status
reg	[9:0]   cnt_fsm     	;    		//Count the clock cycle, record the waiting time of each initialization state, and the bit width shall meet the requirements of the maximum burst length
reg			cnt_fsm_reset 	;    		//Clock cycle count reset flag
reg	[15:0]  rd_data_reg 	;

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//rd_data_reg, because there is a phase difference between the data read out from SDRAM and the clock of this module, it needs to be synchronized
always@(posedge rd_clk or negedge rd_rst_n)begin
    if(rd_rst_n == 1'b0)
        rd_data_reg <=  16'd0;
    else
        rd_data_reg <=  rd_data;
end

//rd_end: end of a burst read
assign  rd_end = (state_cur == RD_END) ? 1'b1 : 1'b0;

//rd_ sdram_ Data: data read out by SDRAM
assign  rd_sdram_data = (rd_ack == 1'b1) ? rd_data_reg : 16'b0;

//rd_ack: read SDRAM response signal
assign  rd_ack = (state_cur == RD_DATA)
                && (cnt_fsm >= 10'd1)
                && (cnt_fsm < (rd_burst_len + 2'd1));
				
//trcd_end,trp_end,tcl_end,tread_end,rdburst_end: wait end flag
assign  trcd_end_flag    =   ((state_cur == RD_TRCD) && (cnt_fsm == TRCD)) ? 1'b1 : 1'b0;				//End of line gating cycle
assign  trp_end_flag     =   ((state_cur == RD_TRP ) && (cnt_fsm == TRP)) ? 1'b1 : 1'b0;    			//End of precharge validity period
assign  tcl_end_flag     =   ((state_cur == RD_CL  ) && (cnt_fsm == TCL - 1)) ? 1'b1 : 1'b0;    		//End of incubation period
assign  tread_end_flag   =   ((state_cur == RD_DATA) && (cnt_fsm == rd_burst_len )) ? 1'b1 : 1'b0;		//Burst read end						
assign  rdburst_end_flag =   ((state_cur == RD_DATA) && (cnt_fsm == rd_burst_len - 4)) ? 1'b1 : 1'b0;	//Read burst termination				

//Reset signal of working state counter
always@(*)begin
	case(state_cur)
		RD_IDLE:	cnt_fsm_reset <= 1'b1;
		RD_TRCD:    cnt_fsm_reset <= (trcd_end_flag == 1'b1) ? 1'b1 : 1'b0;
		RD_READ:    cnt_fsm_reset <= 1'b1;
		RD_CL:      cnt_fsm_reset <= (tcl_end_flag == 1'b1) ? 1'b1 : 1'b0;
		RD_DATA:    cnt_fsm_reset <= (tread_end_flag == 1'b1) ? 1'b1 : 1'b0;
		RD_TRP:     cnt_fsm_reset <= (trp_end_flag == 1'b1) ? 1'b1 : 1'b0;
		RD_END:     cnt_fsm_reset <= 1'b1;
		default:    cnt_fsm_reset <= 1'b0;
	endcase
end

//It is used to count each state to realize state jump, and count the reset signal cnt_fsm_reset when reset is valid, and other times are accumulated
always@(posedge rd_clk or negedge rd_rst_n)begin
    if(rd_rst_n == 1'b0)
        cnt_fsm <=  10'd0;
    else    if(cnt_fsm_reset == 1'b1)
        cnt_fsm <=  10'd0;
    else
        cnt_fsm <=  cnt_fsm + 1'b1;
end

//------------< three stage state machine >----------------------------------------------------------------------------------

//--The first section of state machine: synchronous timing description state transition
always@(posedge rd_clk or negedge rd_rst_n)begin
	if(!rd_rst_n)
		state_cur <= RD_IDLE;	
	else
		state_cur <= state_next;
end

//--The second section of state machine: combinational logic judges the state transition conditions and describes the state transition law and output
always@(*)begin
	state_next = RD_IDLE;
	case(state_cur)
		RD_IDLE:
			if(rd_en && init_end)						//If the initialization is completed and the read enable is valid, it will jump to the next state, otherwise it will remain in this state
				state_next = RD_ACT;			
			else			
				state_next = RD_IDLE;					
		RD_ACT:			
			state_next = RD_TRCD;						//Jump to TRCD wait state
		RD_TRCD:			
			if(trcd_end_flag)							//If the TRCD waiting flag is pulled high, it will jump to the next state, otherwise it will remain in this state
				state_next = RD_READ;			
			else			
				state_next = RD_TRCD;			
		RD_READ:			
			state_next = RD_CL;							//Jump latency state	
		RD_CL:			
			if(tcl_end_flag)							//If the end of incubation period flag is raised, it will jump to the next state, otherwise it will remain in this state
				state_next = RD_DATA;			
			else			
				state_next = RD_CL;			
		RD_DATA:										//Burst read data status
			if(tread_end_flag)							//If the burst read data end flag is raised, it will jump to the next state, otherwise it will remain in this state
				state_next = RD_PRE;			
			else			
				state_next = RD_DATA;			
		RD_PRE:			
				state_next = RD_TRP;					//Precharge state
		RD_TRP:			
			if(trp_end_flag)							//If the TRP waiting flag is pulled high, it will jump to the next state, otherwise it will remain in this state
				state_next = RD_END;			
			else			
				state_next = RD_TRP;					
		RD_END:			
			state_next = RD_IDLE;						//Jump to initial state
		default:state_next = RD_IDLE;					//The default is in the initial state
	endcase
end

//--The third section of state machine: timing logic description output
always@(posedge rd_clk or negedge rd_rst_n)begin
    if(rd_rst_n == 1'b0)begin							//Reset the output NOP instruction. If you don't care about the address and BANK address, just pull it up	
            rd_sdram_cmd <= NOP;
            rd_sdram_bank <= 2'b11;
            rd_sdram_addr <= 13'h1fff;
    end
    else
        case(state_cur)
            RD_IDLE,RD_TRCD,RD_TRP,RD_END:begin			//Output NOP instruction. If you don't care about the address and BANK address, just raise them all	
				rd_sdram_cmd <= NOP;
				rd_sdram_bank <= 2'b11;
				rd_sdram_addr <= 13'h1fff;
            end
            RD_ACT:begin  						              
				rd_sdram_cmd <= ACTIVE;					//Activate command 	
				rd_sdram_bank <= rd_addr[23:22];		//The BANK address is the input address Rd_ The upper two digits of addr
				rd_sdram_addr <= rd_addr[21:9];			//The row address is 21-9 bits (13 bit address bus)
            end
            RD_READ:begin    	               
				rd_sdram_cmd <= READ;					//Column read operation instruction 
				rd_sdram_bank <= rd_addr[23:22];		//The BANK address is the input address Rd_ The upper two digits of addr
				rd_sdram_addr <= {4'b0000,rd_addr[8:0]};//The column address has only 9 bits, but shares a 13 bit address bus, so the upper 4 bits are supplemented with 0
            end
            RD_DATA:begin    	                		//I don't care about the address and BANK address. Just raise them all	
				rd_sdram_bank <= 2'b11;
				rd_sdram_addr <= 13'h1fff;
				if(rdburst_end_flag)
					rd_sdram_cmd <= BURST_STOP;			//Burst transmission termination instruction
				else
					rd_sdram_cmd <= NOP;				//Burst reading is not finished, send an empty instruction
            end
            RD_PRE:begin                   
				rd_sdram_cmd <= PRECHARGE;				//Precharge command 
				rd_sdram_bank <= rd_addr[23:22];		//The BANK address is the input address Rd_ The upper two digits of addr
				rd_sdram_addr <= 13'h0400;				//A10 pull up and select all banks to precharge all banks. Other bits don't care	
            end
            default:begin
				rd_sdram_cmd <=  NOP;					//Output NOP instruction. If you don't care about the address and BANK address, just raise them all
				rd_sdram_bank <=  2'b11;
				rd_sdram_addr <=  13'h1fff;
            end
        endcase
end

endmodule

The code is written in a three-stage state machine. In fact, it can also be written in a linear sequence machine, but the three-stage state machine will standardize points.

Relevant contents of three-stage state machine:

State machines (one-stage, two-stage, three-stage), Moore and Mealy

After brushing this set of questions, I found that Verilog was so simple - HDLBits answer series - final state machine( ❤️ Hematemesis, induction, suggestion collection ❤️)

6,Testbench

         In addition to the SDRAM burst read module written before, Testbench also instantiates a PLL module, which outputs 50M, 100M and 100M clock signals with a phase offset of - 30 ° respectively (the PLL module is not given, you can see the SDRAM, can't the PLL?), as well as the SDRAM initialization module designed before (all operations of SDRAM can only be carried out after initialization is completed) .

         In addition, a simulation model sdram_model_plus found on the Internet is exemplified. The authors are Li Sheng, Chen naikui and Luo Yao.
 

`timescale  1ns/1ns

module  tb_sdram_read();

//********************************************************************//
//****************** Internal Signal and Defparam ********************//
//********************************************************************//

//wire define
//clk_gen
wire            clk_50m         ;   //PLL output 50M clock
wire            clk_100m        ;   //PLL output 100M clock
wire            clk_100m_shift  ;   //PLL output 100M clock, phase offset - 30deg
wire            locked          ;   //PLL clock lock signal
wire            rst_n           ;   //Reset signal, low active
//sdram_init
wire    [3:0]   init_cmd        ;   //Initialization phase instruction
wire    [1:0]   init_bank       ;   //L-Bank address in initialization stage
wire    [12:0]  init_addr       ;   //Initialization phase address bus
wire            init_end        ;   //Initialization completion signal
//sdram_write
wire    [12:0]  wr_sdram_addr	;   //Data write phase address bus
wire    [1:0]   wr_sdram_bank	;   //L-Bank address in data writing stage
wire    [3:0]   wr_sdram_cmd	;   //Data write stage instruction
wire    [15:0]  wr_sdram_data   ;   //SDRAM data is written in the data write phase
wire            wr_sdram_en     ;   //Data write phase write data valid enable signal
wire            wr_end          ;   //The data write phase ends with a burst write
wire            sdram_wr_ack    ;   //Data write phase write response
//sdram_read
wire    [12:0]  rd_sdram_addr	;   //Data read phase address bus
wire    [1:0]   rd_sdram_bank	;   //L-Bank address in data reading stage
wire    [3:0]   rd_sdram_cmd	;   //Data read stage instruction
wire    [15:0]  rd_sdram_data	;   //SDRAM data is read in the data reading phase
wire            rd_end          ;   //The data reading phase ends with a burst write
//sdram_addr
wire    [12:0]  sdram_addr      ;   //SDRAM address bus
wire    [1:0]   sdram_bank		;   //Sdraml bank address
wire    [3:0]   sdram_cmd       ;   //SDRAM instruction
wire    [15:0]  sdram_dq        ;   //SDRAM data bus

wire    [12:0]  w_r_addr        ;   //Data read phase address bus
wire    [1:0]   w_r_bank		;   //L-Bank address in data reading stage
wire    [3:0]   w_r_cmd         ;   //Data read stage instruction

//reg define
reg             sys_clk         ;   //System clock
reg             sys_rst_n       ;   //Reset signal
reg             wr_en           ;   //Write enable
reg     [15:0]  wr_data_in      ;   //Write data
reg             rd_en           ;   //Read enable

//defparam
//Redefine the relevant parameters in the simulation model
defparam sdram_model_plus_inst.addr_bits = 13;          //Address bit width
defparam sdram_model_plus_inst.data_bits = 16;          //Data bit width
defparam sdram_model_plus_inst.col_bits  = 9;           //Column address bit width
defparam sdram_model_plus_inst.mem_sizes = 2*1024*1024; //L-Bank capacity

//********************************************************************//
//**************************** Clk And Rst ***************************//
//********************************************************************//

//Clock, reset signal
initial
  begin
    sys_clk     =   1'b1  ;
    sys_rst_n   <=  1'b0  ;
    #200
    sys_rst_n   <=  1'b1  ;
  end

always  #10 sys_clk = ~sys_clk;

//rst_n: reset signal
assign  rst_n = sys_rst_n & locked;

//wr_en: write data enable
always@(posedge clk_100m or negedge rst_n)
    if(rst_n == 1'b0)
        wr_en   <=  1'b1;
    else    if(wr_end == 1'b1)
        wr_en   <=  1'b0;
    else
        wr_en   <=  wr_en;

//wr_data_in: write data
always@(posedge clk_100m or negedge rst_n)
    if(rst_n == 1'b0)
        wr_data_in  <=  16'd0;
    else    if(wr_data_in == 16'd10)
        wr_data_in  <=  16'd0;
    else    if(sdram_wr_ack == 1'b1)
        wr_data_in  <=  wr_data_in + 1'b1;
    else
        wr_data_in  <=  wr_data_in;

//rd_en: read data enable
always@(posedge clk_100m or negedge rst_n)
    if(rst_n == 1'b0)
        rd_en   <=  1'b0;
    else    if(rd_end == 1'b1)
        rd_en   <=  1'b0;
    else    if(wr_en == 1'b0)
        rd_en   <=  1'b1;
    else
        rd_en   <=  rd_en;

//sdram_cmd,sdram_bank,sdram_addr
assign  sdram_cmd = (init_end == 1'b1) ? w_r_cmd : init_cmd;
assign  sdram_bank = (init_end == 1'b1) ? w_r_bank : init_bank;
assign  sdram_addr = (init_end == 1'b1) ? w_r_addr : init_addr;

//w_r_cmd,w_r_bank,w_r_addr
assign  w_r_cmd = (wr_en == 1'b1) ? wr_sdram_cmd : rd_sdram_cmd;
assign  w_r_bank = (wr_en == 1'b1) ? wr_sdram_bank : rd_sdram_bank;
assign  w_r_addr = (wr_en == 1'b1) ? wr_sdram_addr : rd_sdram_addr;

//wr_sdram_data
assign  sdram_dq = (wr_sdram_en == 1'b1) ? wr_sdram_data : 16'hz;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//

//------------- clk_gen_inst -------------
clk_gen clk_gen_inst (
    .inclk0     (sys_clk        ),
    .areset     (~sys_rst_n     ),
    .c0         (clk_50m        ),
    .c1         (clk_100m       ),
    .c2         (clk_100m_shift ),

    .locked     (locked         )
);

//------------- sdram_init_inst -------------
sdram_init  sdram_init_inst(

    .init_clk    (clk_100m   ),
    .init_rst_n  (rst_n      ),

    .init_cmd	 (init_cmd   ),
    .init_bank   (init_bank	),
    .init_addr   (init_addr  ),
    .init_end    (init_end   )

);

//------------- sdram_write_inst -------------
sdram_write sdram_write_inst(

    .wr_clk        	(clk_100m       ),
    .wr_rst_n      	(rst_n          ),
    .init_end       (init_end       ),
    .wr_en          (wr_en          ),

    .wr_addr        (24'h000_000    ),
    .wr_data        (wr_data_in     ),
    .wr_burst_len   (10'd10         ),

    .wr_ack         (sdram_wr_ack   ),
    .wr_end         (wr_end         ),
    .wr_sdram_cmd	(wr_sdram_cmd	),
    .wr_sdram_bank	(wr_sdram_bank	),
    .wr_sdram_addr	(wr_sdram_addr	),
    .wr_sdram_en    (wr_sdram_en    ),
    .wr_sdram_data  (wr_sdram_data  )

);

//------------- sdram_read_inst -------------
sdram_read  sdram_read_inst(

    .rd_clk        	(clk_100m       ),
    .rd_rst_n      	(rst_n          ),
    .init_end       (init_end       ),
    .rd_en          (rd_en          ),

    .rd_addr        (24'h000_000    ),
    .rd_data        (sdram_dq       ),
    .rd_burst_len   (10'd10         ),

    .rd_ack         (               ),
    .rd_end         (rd_end         ),
    .rd_sdram_cmd	(rd_sdram_cmd	),
    .rd_sdram_bank	(rd_sdram_bank	),
    .rd_sdram_addr	(rd_sdram_addr	),
    .rd_sdram_data  (rd_sdram_data	)

);

//-------------sdram_model_plus_inst-------------
sdram_model_plus    sdram_model_plus_inst(
    .Dq     (sdram_dq       ),
    .Addr   (sdram_addr     ),
    .Ba     (sdram_bank       ),
    .Clk    (clk_100m_shift ),
    .Cke    (1'b1           ),
    .Cs_n   (sdram_cmd[3]   ),
    .Ras_n  (sdram_cmd[2]   ),
    .Cas_n  (sdram_cmd[1]   ),
    .We_n   (sdram_cmd[0]   ),
    .Dqm    (2'b0           ),
    .Debug  (1'b1           )

);
//------------------------------------------------
//--State machine name viewer
//------------------------------------------------
reg [79:0]	name_state_cur;			//Each character is 8 bits wide. Here, take up to 10 characters and 80 bits wide

always @(*) begin
    case(sdram_read_inst.state_cur)
        4'b0000:	name_state_cur = "RD_IDLE  ";
        4'b0001:	name_state_cur = "RD_ACT   ";
        4'b0011:	name_state_cur = "RD_TRCD  ";
        4'b0010:	name_state_cur = "RD_READ  "; 
		4'b0100:	name_state_cur = "RD_CL    "; 
		4'b0101:	name_state_cur = "RD_DATA  "; 
		4'b0111:	name_state_cur = "RD_PRE   "; 
		4'b0110:	name_state_cur = "RD_TRP   "; 
		4'b1100:    name_state_cur = "RD_END   ";                      
        default:	name_state_cur = "RD_IDLE  ";
    endcase
end

//------------------------------------------------
endmodule

7. Simulation results

        The results are as follows:

Above:

  • After the read request rd_en is pulled high, init_end is high at this time, so it enters the sending line activation state in the next cycle, and the sending line activation command + line address + bank address
  • After waiting for TRCD clock cycles, enter the column read-write state and send the read instruction + column head address + bank address
  • After waiting for CL clock cycles, the first data is output on the data bus
  • Thereafter, the data bus outputs data until the burst is terminated
  • After sending the precharge command, wait to meet the TRP timing requirements of 2 clocks and enter the RD_END state
  • In the rd_end state, pull up the output signal rd_end for one cycle to notify the arbitration module that the reading operation has ended, so as to facilitate the arbitration module to schedule

The information printed in the modlesim command window is as follows:


 

You can see:

  • After the first initialization, the burst write operation is performed. The burst write length is 10, the write data are 1-10 respectively, and the write address is 0-10 of the first line of bank00
  • Since then, the above address has been read, and the read data is consistent with the written data

8. Summary

  • This full page burst read operation with burst termination is easier to control the read length and is much faster than a single read
  • For those who want engineering documents, please leave an email in the comments and I'll send it to you as soon as possible

 

 


 

Tags: Verilog FPGA sdram

Posted on Tue, 21 Sep 2021 01:25:59 -0400 by andre3