//读指针与“满”逻辑 module rptr_empty( rempty, rptr, aempty_n, rreq, rclk, rrst_n ); parameter ADDR_WIDTH = 4; output rempty; output [ADDR_WIDTH-1:0]rptr; input aempty_n; input rreq, rclk, rrst_n; reg [ADDR_WIDTH-1:0]rptr,rbin; reg rempty, rempty2; wire [ADDR_WIDTH-1:0]rgnext, rbnext; //寄存器输出Gray码读地址指针 always @(posedge rclk or negedge rrst_n) if(!rrst_n) begin rbin <= 0; rptr <= 0; end else begin rbin <= rbnext; rptr <= rgnext; end //Gray码计数逻辑 assign rbnext = !rempty ? rbin + rreq : rbin;//二进制递增 assign rgnext = (rbnext>>1) ^ rbnext; //二进制到Gray码的转换 //rempty被aempty异步置位,并且当读指针递加后撤除 always @(posedge rclk or negedge aempty_n) begin if(!aempty_n) {rempty, rempty2} <= 2'b11; else {rempty, rempty2} <= {rempty2, ~aempty_n}; end endmodule //写指针与满逻辑模块 module wptr_full( wfull, wptr, afull_n, wreq, wclk, wrst_n ); parameter ADDR_WIDTH = 4; output wfull; output [ADDR_WIDTH-1:0]wptr; input afull_n; input wreq, wclk, wrst_n; reg [ADDR_WIDTH-1:0]wptr, wbin; reg wfull, wfull2; wire [ADDR_WIDTH-1:0]wgnext, wbnext; //寄存器输出Gray码读地址指针 always @(posedge wclk or negedge wrst_n) begin if(!wrst_n) begin wbin <= 0; wptr <= 0; end else begin wbin <= wbnext; wptr <= wgnext; end end //Gray码计数逻辑 assign wbnext = !wfull ? wbin + wreq : wbin; //二进制递增 assign wgnext = (wbnext>>1) ^ wbnext; //二进制到Gray码的转换 //当FIFO复位时,状态wfull也被复位,此外其也被afull_n异步置位,并且当读指针递加后撤除 always @(posedge wclk or negedge wrst_n or negedge afull_n) begin if(!wrst_n) {wfull, wfull2} <= 2'b00; else if(!afull_n) {wfull, wfull2} <= 2'b11; else {wfull, wfull2} <= {wfull2, ~afull_n}; end endmodule module async_fifo( rdata, wfull, rempty, wdata, wreq, wclk, wrst_n, rreq, rclk, rrst_n ); parameter DATA_WIDTH = 8; parameter ADDR_WIDTH = 4; output [DATA_WIDTH-1:0]rdata; //从fifo读出的数据 output wfull; //fifo数据满了,写不下了 output rempty; //fifo被读空了,别再读了 input [DATA_WIDTH-1:0]wdata; //写进fifo的数据 input wreq; //写允许 input wclk; //写时钟 input wrst_n; //写复位 input rreq; //读允许 input rclk; //读时钟 input rrst_n; //读复位 //一下wire类型只是起到两个模块之间的连线作用 wire [ADDR_WIDTH-1:0]wptr, rptr; wire [ADDR_WIDTH-1:0]waddr, raddr; wire aempty_n, afull_n; dp_ram dp_ram( .rdata(rdata), .wdata(wdata), .waddr(wptr), .raddr(rptr), .wclken(wreq), .wclk(wclk) ); defparam dp_ram.DATA_WIDTH = DATA_WIDTH; defparam dp_ram.ADDR_WIDTH = ADDR_WIDTH; async_cmp async_cmp( .aempty_n(aempty_n), .afull_n(afull_n), .wptr(wptr), .rptr(rptr), .wrst_n(wrst_n) ); defparam async_cmp.ADDR_WIDTH = ADDR_WIDTH; rptr_empty rptr_empty( .rempty(rempty), .rptr(rptr), .aempty_n(aempty_n), .rreq(rreq), .rclk(rclk), .rrst_n(rrst_n) ); defparam rptr_empty.ADDR_WIDTH = ADDR_WIDTH; wptr_full wptr_full( .wfull(wfull), .wptr(wptr), .afull_n(afull_n), .wreq(wreq), .wclk(wclk), .wrst_n(wrst_n) ); defparam wptr_full.ADDR_WIDTH = ADDR_WIDTH; endmodule 简单笔记:
1、defparam 重定义参数 语法:defparam path_name = value ;
低层模块的参数可以通过层次路径名重新定义
2、menory生成办法:
reg [DATA_WIDTH-1:0]MEN[0:DEPTH-1];
3、一个技巧:
//rempty被aempty异步置位,并且当读指针递加后撤除 always @(posedge rclk or negedge aempty_n) begin if(!aempty_n) {rempty, rempty2} <= 2'b11; else {rempty, rempty2} <= {rempty2, ~aempty_n}; end
4、用wire去连接两个模块
//以下wire类型只是起到两个模块之间的连线作用
wire [ADDR_WIDTH-1:0]wptr, rptr;
wire [ADDR_WIDTH-1:0]waddr, raddr; |