Weitter

爽朗的秋风吹走夏日的疲惫

SDR SDRAM读写控制器————读数据模块设计

 =================================================

 目录

  1、SDR SDRAM读写控制器————整体概述

  2、SDR SDRAM读写控制器————上电模块设计

  3、SDR SDRAM读写控制器————刷新模块设计  

  4、SDR SDRAM读写控制器————定时器模块设计

  5、SDR SDRAM读写控制器————写数据模块设计

  6、SDR SDRAM读写控制器————读数据模块设计

  7、SDR SDRAM读写控制器————主控制机模块设计

 =================================================

 

读数据模块时序图:

读数据模块状态转移图:

读数据模块程序设计:

`include "../rtl/head.v"

//读状态机
module rd_fsm(
            clk         ,//100MHz的时钟线 
            capture_clk ,//捕获时钟 理论上是180度相位
            soft_rst_n  ,//软复位 
            rd_en       ,//读数据使能
            rd_done     ,//完成读出数据操作标志
            row         ,//行地址
            col         ,//列地址
            ba          ,//Bank地址 
            rdata       ,//读出的数据
            rd_bus      ,//读数据模块的总线
            sdr_dq       //从SDR输出的数据
);

input  clk, capture_clk, soft_rst_n ;
input  rd_en                        ;
output reg rd_done                  ;
input  [12:0] row                   ;
input  [9:0]  col                   ;
input  [1:0]  ba                    ;
output wire [31:0] rdata             ;
output [19:0] rd_bus                ;
input  [15:0] sdr_dq                ;

reg    [15:0] dq_cap                ;
reg    [15:0] dq_syn                ;
reg    load_l                       ;
reg    load_h                       ;
reg    [12:0] rd_a                  ;
reg    [1:0]  rd_ba                 ;
reg    [3:0]  rd_cmd                ;
reg    rd_cke                       ;
reg    [5:0]  cnt                   ;
reg    [2:0]  state                 ;

localparam s0 = 3'b000;
localparam s1 = 3'b001;
localparam s2 = 3'b011;
localparam s3 = 3'b111;
localparam s4 = 3'b110;

/*================================================*/


assign rd_bus = {rd_cmd, rd_a, rd_ba, rd_cke};//组装总线

always @ (posedge clk)
begin
    if (!soft_rst_n)//同步复位
        begin 
            rd_done <= 0    ;//管理输出端口
            rd_cmd  <= `NOP ;
            rd_a    <= 0    ;
            rd_ba   <= 0    ;
            rd_cke  <= 1    ;
            load_l  <= 0    ;
            load_h  <= 0    ;
            cnt     <= 0    ;
            state   <= s0   ;
        end
    else
        case (state)
            s0: if (!rd_en) 
                    state  <= s0   ; 
                 else begin //读数据模块打开
                    rd_cmd <= `ACT ;//发送激活命令给SDR
                    rd_a   <= row  ;//发送行地址给SDR
                    rd_ba  <= ba   ;//发送Bank地址给给SDR
                    rd_done<= 0    ;//
                    state  <= s1   ;
                 end
            s1: if (cnt < `tRCD - 1)//经过TRCD的周期
                    begin
                        rd_cmd <= `NOP    ;
                        cnt    <= cnt + 1 ;
                        state  <= s1      ;
                    end
                  else begin 
                        rd_cmd     <= `RD   ;//发送读数据命令
                        cnt        <= 0     ;
                        rd_ba      <= ba    ;//发送Bank地址
                        rd_a[9:0]  <= col   ;//发送列地址
                        rd_a[10]   <= 1     ;//自动管理purchage
                        state      <= s2    ;
                   end
           s2: if (cnt < `CL + `SL - 1)//经过CL(列选通潜伏期)+SL个周期后
                    begin
                        rd_cmd     <= `NOP    ;
                        cnt        <= cnt + 1 ;
                        state      <= s2      ;
                    end
                  else begin
                        load_l     <= 1       ;//装配低16bit数据
                        cnt        <= 0       ;
                        state      <= s3      ;
                  end
            s3: begin
                        load_l     <= 0       ;
                        load_h     <= 1       ;//装配高16bit数据
                        state      <= s4      ;
                 end
            s4: begin
                        rd_done    <= 1       ;//发出完成读出数据的反馈信号
                        load_h     <= 0       ;
                        state      <= s0      ;
                 end
        endcase
end

//sdr_dq是来自SDR_CLK时钟域,需要先用capture_clk捕获,理论上SDR_CLK和capture_clk都是180度相位
//此时的sdr_dq数据与capture_clk是中心对齐
always @ (posedge capture_clk)
    begin: CAP_REG 
        dq_cap <= sdr_dq;
    end
//此时的dq_cap数据与CLK是中心对齐
always @ (posedge clk)
    begin: SYN_REG
        dq_syn <= dq_cap;
    end

reg [15:0] rdata_lr;
reg [15:0] rdata_hr;
always @ (posedge clk)
    begin:FIT
        if (!soft_rst_n)begin
            rdata_lr <= 16'b0             ;
            rdata_hr <= 16'b0             ;
            end
        else if (load_l)//如果需要装配低16bit数据时候 
            rdata_lr <= dq_syn            ;
        else if (load_h)//如果需要装配高16bit数据的时候
            rdata_hr <= dq_syn            ;
    end

assign rdata   = {rdata_hr, rdata_lr};//rdata再给Avalon总线上的local_rdata,输出到总线上
endmodule 



  

 

 

参考视频链接: 至芯科技李凡老师FPGA课堂:SDRAM控制器设计(超级经典)-学习视频教程-腾讯课堂

参考文档: Micron的MT48LC16M16A2器件文档

posted @ 2021-03-30 11:08  weitter  阅读(272)  评论(0编辑  收藏  举报