SDRAM——FIFO控制模块

fifo_ctrl 模块的功能主要是:使用 FIFO 对传入的待写入 SDRAM 的数据和自 SDRAM读出的数据进行进行缓存,实现跨时钟域处理;为数据读写模块提供 SDRAM 读写地址,产生读写请求。
在这里插入图片描述
在这里插入图片描述

`timescale  1ns/1ns
module  fifo_ctrl
(
    input   wire            sys_clk         ,   //系统时钟
    input   wire            sys_rst_n       ,   //复位信号
//写fifo信号
    input   wire            wr_fifo_wr_clk  ,   //写FIFO写时钟
    input   wire            wr_fifo_wr_req  ,   //写FIFO写请求
    input   wire    [15:0]  wr_fifo_wr_data ,   //写FIFO写数据
    input   wire    [23:0]  sdram_wr_b_addr ,   //写SDRAM首地址		  顶层设定
    input   wire    [23:0]  sdram_wr_e_addr ,   //写SDRAM末地址		  顶层设定
    input   wire    [9:0]   wr_burst_len    ,   //写SDRAM数据突发长度 顶层设定
    input   wire            wr_rst          ,   //写复位信号		  
//读fifo信号
    input   wire            rd_fifo_rd_clk  ,   //读FIFO读时钟
    input   wire            rd_fifo_rd_req  ,   //读FIFO读请求
    input   wire    [23:0]  sdram_rd_b_addr ,   //读SDRAM首地址		  顶层设定
    input   wire    [23:0]  sdram_rd_e_addr ,   //读SDRAM末地址		  顶层设定
    input   wire    [9:0]   rd_burst_len    ,   //读SDRAM数据突发长度 顶层设定
    input   wire            rd_rst          ,   //读复位信号
    output  wire    [15:0]  rd_fifo_rd_data ,   //读FIFO读数据
    output  wire    [9:0]   rd_fifo_num     ,   //读fifo中的数据量

    input   wire            read_valid      ,   //SDRAM读使能
    input   wire            init_end        ,   //SDRAM初始化完成标志
//SDRAM写信号
    input   wire            sdram_wr_ack    ,   //SDRAM写响应 来自写模块
    output  reg             sdram_wr_req    ,   //SDRAM写请求 给到仲裁
    output  reg     [23:0]  sdram_wr_addr   ,   //SDRAM写地址
    output  wire    [15:0]  sdram_data_in   ,   //写入SDRAM的数据
//SDRAM读信号
    input   wire            sdram_rd_ack    ,   //SDRAM读相应 来自读模块
    input   wire    [15:0]  sdram_data_out  ,   //读出SDRAM数据
    output  reg             sdram_rd_req    ,   //SDRAM读请求 给到仲裁
    output  reg     [23:0]  sdram_rd_addr       //SDRAM读地址
);

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

//wire define
wire            wr_ack_fall ;   //写响应信号下降沿
wire            rd_ack_fall ;   //读相应信号下降沿
wire    [9:0]   wr_fifo_num ;   //写fifo中的数据量

//reg define
reg        wr_ack_dly       ;   //写响应打拍
reg        rd_ack_dly       ;   //读响应打拍

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

//wr_ack_dly:写响应信号打拍
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        wr_ack_dly  <=  1'b0;
    else
        wr_ack_dly  <=  sdram_wr_ack;

//rd_ack_dly:读响应信号打拍
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        rd_ack_dly  <=  1'b0;
    else
        rd_ack_dly <=  sdram_rd_ack;

//wr_ack_fall,rd_ack_fall:检测读写响应信号下降沿 下降沿代表对应操作完成
assign  wr_ack_fall = (wr_ack_dly & ~sdram_wr_ack);
assign  rd_ack_fall = (rd_ack_dly & ~sdram_rd_ack);

//sdram_wr_addr:sdram写地址
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sdram_wr_addr   <=  24'd0;
    else    if(wr_rst == 1'b1)
        sdram_wr_addr   <=  sdram_wr_b_addr;
    else    if(wr_ack_fall == 1'b1) //一次突发写结束,更改写地址
        begin
            if(sdram_wr_addr < (sdram_wr_e_addr - wr_burst_len))
                        //不使用乒乓操作,一次突发写结束,更改写地址,未达到末地址,写地址累加
                sdram_wr_addr   <=  sdram_wr_addr + wr_burst_len;
            else        //不使用乒乓操作,到达末地址,回到写起始地址
                sdram_wr_addr   <=  sdram_wr_b_addr;
        end

//sdram_rd_addr:sdram读地址
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sdram_rd_addr   <=  24'd0;
    else    if(rd_rst == 1'b1)
        sdram_rd_addr   <=  sdram_rd_b_addr;
    else    if(rd_ack_fall == 1'b1) //一次突发读结束,更改读地址
        begin
            if(sdram_rd_addr < (sdram_rd_e_addr - rd_burst_len))
                    //读地址未达到末地址,读地址累加
                sdram_rd_addr   <=  sdram_rd_addr + rd_burst_len;
            else    //到达末地址,回到首地址
                sdram_rd_addr   <=  sdram_rd_b_addr;
        end

//sdram_wr_req,sdram_rd_req:读写请求信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            sdram_wr_req    <=  1'b0;
            sdram_rd_req    <=  1'b0;
        end
    else    if(init_end == 1'b1)   //初始化完成后响应读写请求
        begin   //优先执行写操作,防止写入SDRAM中的数据丢失
            if(wr_fifo_num >= wr_burst_len)
                begin   //写FIFO中的数据量达到写突发长度
                    sdram_wr_req    <=  1'b1;   //写请求有效
                    sdram_rd_req    <=  1'b0;
                end
            else    if((rd_fifo_num < rd_burst_len) && (read_valid == 1'b1))
                begin //读FIFO中的数据量小于读突发长度,且读使能信号有效
                    sdram_wr_req    <=  1'b0;
                    sdram_rd_req    <=  1'b1;   //读请求有效
                end
            else
                begin
                    sdram_wr_req    <=  1'b0;
                    sdram_rd_req    <=  1'b0;
                end
        end
    else
        begin
            sdram_wr_req    <=  1'b0;
            sdram_rd_req    <=  1'b0;
        end

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

//------------- wr_fifo_data -------------
fifo_data   wr_fifo_data(
    //用户接口
    .wrclk      (wr_fifo_wr_clk ),  //写时钟
    .wrreq      (wr_fifo_wr_req ),  //写请求
    .data       (wr_fifo_wr_data),  //写数据
    //SDRAM接口
    .rdclk      (sys_clk        ),  //读时钟
    .rdreq      (sdram_wr_ack   ),  //读请求
    .q          (sdram_data_in  ),  //读数据

    .rdusedw    (wr_fifo_num    ),  //FIFO中的数据量
    .wrusedw    (               ),
    .aclr       (~sys_rst_n || wr_rst)  //清零信号
    );

//------------- rd_fifo_data -------------
fifo_data   rd_fifo_data(
    //sdram接口
    .wrclk      (sys_clk        ),  //写时钟
    .wrreq      (sdram_rd_ack   ),  //写请求
    .data       (sdram_data_out ),  //写数据
    //用户接口
    .rdclk      (rd_fifo_rd_clk ),  //读时钟
    .rdreq      (rd_fifo_rd_req ),  //读请求
    .q          (rd_fifo_rd_data),  //读数据

    .rdusedw    (               ),
    .wrusedw    (rd_fifo_num    ),  //FIFO中的数据量
    .aclr       (~sys_rst_n || rd_rst)  //清零信号
    );

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值