1、同步FIFO和异步FIFO的Verilog实现FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据, 其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端是AD数据采集, 另一端是计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bi
2、t,其最大传输速率为 1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而 DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。FIFO的分类根据FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。异步FIFO是指读写时钟不一致,读写时钟是互相独立的。FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIF
3、O在满的情况下,不能进行写操作。在空的状态下不能进行读操作。怎样判断FIFO的满/空就成了FIFO设计的核心问题。.同步FIFO的Verilog代码 之一在modlesim中验证过。/*A fifo controller verilog description.*/module fifo(datain, rd, wr, rst, clk, dataout, full, empty);input 7:0 datain;input rd, wr, rst, clk;output 7:0 dataout;output full, empty;wire 7:0 dataout;reg full_in,
4、 empty_in;reg 7:0 mem 15:0;reg 3:0 rp, wp;assign full = full_in;assign empty = empty_in;/ memory read outassign dataout = memrp;/ memory write inalways(posedge clk) begin if(wr & full_in) memwp=datain;end/ memory write pointer incrementalways(posedge clk or negedge rst) begin if(!rst) wp=0; else beg
5、in if(wr & full_in) wp= wp+1b1; endend/ memory read pointer incrementalways(posedge clk or negedge rst)begin if(!rst) rp = 0; else begin if(rd & empty_in) rp = rp + 1b1; endend/ Full signal generatealways(posedge clk or negedge rst) begin if(!rst) full_in = 1b0; else begin if( (rd & wr)&(wp=rp-1)|(r
6、p=4h0&wp=4hf) full_in = 1b1; else if(full_in & rd) full_in = 1b0; endend/ Empty signal generatealways(posedge clk or negedge rst) begin if(!rst) empty_in = 1b1; else begin if(rd&wr)&(rp=wp-1 | (rp=4hf&wp=4h0) empty_in=1b1; else if(empty_in & wr) empty_in=1b0; endendendmodule.同步FIFO的Verilog代码 之二这一种设计
7、的FIFO,是基于触发器的。宽度,深度的扩展更加方便,结构化跟强。以下代码在modelsim中验证过。module fifo_cell (sys_clk, sys_rst_n, read_fifo, write_fifo, fifo_input_data, next_cell_data, next_cell_full, last_cell_full, cell_data_out, cell_full); parameter WIDTH =8; parameter D = 2; input sys_clk; input sys_rst_n; input read_fifo, write_fifo
8、; input WIDTH-1:0 fifo_input_data; input WIDTH-1:0 next_cell_data; input next_cell_full, last_cell_full; output WIDTH-1:0 cell_data_out; output cell_full; reg WIDTH-1:0 cell_data_reg_array; reg WIDTH-1:0 cell_data_ld; reg cell_data_ld_en; reg cell_full; reg cell_full_next; assign cell_data_out=cell_
9、data_reg_array; always (posedge sys_clk or negedge sys_rst_n) if (!sys_rst_n) cell_full = #D 0; else if (read_fifo | write_fifo) cell_full = #D cell_full_next; always (write_fifo or read_fifo or next_cell_full or last_cell_full or cell_full) casex (read_fifo, write_fifo) 2b00: cell_full_next = cell_
10、full; 2b01: cell_full_next = next_cell_full; 2b10: cell_full_next = last_cell_full; 2b11: cell_full_next = cell_full; endcase always (posedge sys_clk or negedge sys_rst_n) if (!sys_rst_n) cell_data_reg_array WIDTH-1:0 = #D 0; else if (cell_data_ld_en) cell_data_reg_array WIDTH-1:0 = #D cell_data_ld
11、WIDTH-1:0; always (write_fifo or read_fifo or cell_full or last_cell_full) casex (write_fifo,read_fifo,cell_full,last_cell_full) 4bx1_xx: cell_data_ld_en = 1b1; 4b10_01: cell_data_ld_en = 1b1; default: cell_data_ld_en =1b0; endcase always (write_fifo or read_fifo or next_cell_full or cell_full or la
12、st_cell_full or fifo_input_data or next_cell_data) casex (write_fifo, read_fifo, next_cell_full, cell_full, last_cell_full) 5b10_x01: cell_data_ldWIDTH-1:0 = fifo_input_dataWIDTH-1:0; 5b11_01x: cell_data_ldWIDTH-1:0 = fifo_input_dataWIDTH-1:0; default: cell_data_ldWIDTH-1:0 = next_cell_dataWIDTH-1:0
13、; endcaseendmodulemodule fifo_4cell(sys_clk, sys_rst_n, fifo_input_data, write_fifo, fifo_out_data, read_fifo, full_cell0, full_cell1, full_cell2, full_cell3); parameter WIDTH = 8; parameter D = 2; input sys_clk; input sys_rst_n; input WIDTH-1:0 fifo_input_data; output WIDTH-1:0 fifo_out_data; input
14、 read_fifo, write_fifo; output full_cell0, full_cell1, full_cell2, full_cell3; wire WIDTH-1:0 dara_out_cell0, data_out_cell1, data_out_cell2, data_out_cell3, data_out_cell4; wire full_cell4; fifo_cell #(WIDTH,D) cell0 ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .fifo_input_data (fifo_input_dataWID
15、TH-1:0), .write_fifo (write_fifo), .next_cell_data (data_out_cell1WIDTH-1:0), .next_cell_full (full_cell1), .last_cell_full (1b1), .cell_data_out (fifo_out_data WIDTH-1:0), .read_fifo (read_fifo), .cell_full (full_cell0) ); fifo_cell #(WIDTH,D) cell1 ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .fi
16、fo_input_data (fifo_input_dataWIDTH-1:0), .write_fifo (write_fifo), .next_cell_data (data_out_cell2WIDTH-1:0), .next_cell_full (full_cell2), .last_cell_full (full_cell0), .cell_data_out (data_out_cell1WIDTH-1:0), .read_fifo (read_fifo), .cell_full (full_cell1) ); fifo_cell #(WIDTH,D) cell2 ( .sys_cl
17、k (sys_clk), .sys_rst_n (sys_rst_n), .fifo_input_data (fifo_input_dataWIDTH-1:0), .write_fifo (write_fifo), .next_cell_data (data_out_cell3WIDTH-1:0), .next_cell_full (full_cell3), .last_cell_full (full_cell1), .cell_data_out (data_out_cell2WIDTH-1:0), .read_fifo (read_fifo), .cell_full (full_cell2)
18、 ); fifo_cell #(WIDTH,D) cell3 ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .fifo_input_data (fifo_input_dataWIDTH-1:0), .write_fifo (write_fifo), .next_cell_data (data_out_cell4WIDTH-1:0), .next_cell_full (full_cell4), .last_cell_full (full_cell2), .cell_data_out (data_out_cell3WIDTH-1:0), .read_f
19、ifo (read_fifo), .cell_full (full_cell3) ); assign data_out_cell4WIDTH-1:0 = WIDTH1B0; assign full_cell4 = 1b0;endmodule.异步FIFO的Verilog代码 之一这个是基于RAM的异步FIFO代码,个人认为代码结构简单易懂,非常适合于考试中填写。记得10月份参加威盛的笔试的时候,就考过异步FIFO的实现。想当初要是早点复习,可能就可以通过威盛的笔试了。与之前的用RAM实现的同步FIFO的程序相比,异步更为复杂。增加了读写控制信号的跨时钟域的同步。此外,判空与判满的也稍有不同。m
20、odule fifo1(rdata, wfull, rempty, wdata, winc, wclk, wrst_n,rinc, rclk, rrst_n);parameter DSIZE = 8; parameter ASIZE = 4;output DSIZE-1:0 rdata;output wfull;output rempty;input DSIZE-1:0 wdata;input winc, wclk, wrst_n;input rinc, rclk, rrst_n;reg wfull,rempty;reg ASIZE:0 wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr;reg ASIZE:0 rbin, wbin;reg DSIZE-1:0 mem0:(1ASIZE)-1;wire ASIZE-1:0 waddr, raddr;wire ASIZE:0 rgraynext, rbinnext,wgraynext,wbinnext;wire rempty_val,wfull_val;/-双口RAM存储器-assign rdata=memraddr;always(posedge wclk)if (winc & !wfull) memwaddr = wdata;/-同步rptr 指针-always (posedge w
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1