FIFO緩存是介于兩個(gè)子系統(tǒng)之間的彈性存儲(chǔ)器,其概念圖如圖1所示。它有兩個(gè)控制信號(hào),wr和rd,用于讀操作和寫(xiě)操作。當(dāng)wr被插入時(shí),輸入的數(shù)據(jù)被寫(xiě)入緩存,此時(shí)讀操作被忽視。FIFO緩存的head一般情況下總是有效的,因此可在任意時(shí)間被讀取。rd信號(hào)實(shí)際上就像“remove”信號(hào);當(dāng)其被插入的時(shí)候,F(xiàn)IFO緩存的第一個(gè)項(xiàng)(即head)被移除,下一個(gè)項(xiàng)變?yōu)榭捎庙?xiàng)。
圖1 FIFO緩存的概念框圖
在許多應(yīng)用中,F(xiàn)IFO緩存是一種臨界組件,其實(shí)現(xiàn)的優(yōu)化相當(dāng)復(fù)雜。在本節(jié)中,我們介紹一種簡(jiǎn)單的、真實(shí)的基于循環(huán)序列設(shè)計(jì)的FIFO緩存。更有效的、基于指定器件實(shí)現(xiàn)的FIFO緩存可在Altera或Xilinx的相關(guān)手冊(cè)中找到。
基于循環(huán)隊(duì)列的實(shí)現(xiàn)
一種實(shí)現(xiàn)FIFO緩存的方法是給寄存器文件添加一個(gè)控制電路。寄存器文件通過(guò)兩個(gè)指針像循環(huán)隊(duì)列一樣來(lái)排列寄存器。寫(xiě)指針(write poniter)指向隊(duì)列的頭(head);讀指針(read poniter)指向隊(duì)列的尾(tail)。每次讀操作或?qū)懖僮鳎羔樁紩?huì)前進(jìn)一個(gè)位置。8-字循環(huán)隊(duì)列的操作如圖2所示。
圖2 基于循環(huán)隊(duì)列的FIFO緩存
FIFO緩存通常包括兩個(gè)標(biāo)志信號(hào),full和empty,相應(yīng)地來(lái)指示FIFO滿(即不可寫(xiě))或FIFO空(即不可讀)。這兩種情況發(fā)生在讀指針和寫(xiě)指針相等的時(shí)候,如圖2(a)、(f)和(i)所示的情況。控制器最難的設(shè)計(jì)任務(wù)是獲取一種分辨這兩種情形的機(jī)制。一種方案是使用觸發(fā)器來(lái)跟蹤empty和full標(biāo)志。當(dāng)系統(tǒng)被初始化時(shí),觸發(fā)器被設(shè)置為1和0;然后在每一個(gè)時(shí)鐘周期根據(jù)wr和rd的值來(lái)修改。
代碼 FIFO緩存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
modulefifo #( parameterB=8, // number of bits in a word W=3 // number of address bits ) ( // global clock and aysn reset inputclk, inputrst_n, // fifo interface // fifo control signnal inputrd, inputwr, // fifo status signal outputempty, outputfull, // fifo data bus input[B-1:0] w_data, output[B-1:0] r_data ); // signal declaration reg[B-1:0] array_reg [2**W-1:0]; // register array reg[W-1:0] w_ptr_reg, w_ptr_next, w_ptr_succ; reg[W-1:0] r_ptr_reg, r_ptr_next, r_ptr_succ; regfull_reg, empty_reg, full_next, empty_next; wirewr_en; // body // register file write operation always@(posedgeclk) if(wr_en) array_reg[w_ptr_reg] <= w_data; // register file read operation assignr_data = array_reg[r_ptr_reg]; // write enabled only when FIFO is not full assignwr_en = wr & ~full_reg; // fifo control logic // register for read and write pointers always@(posedgeclk, negedgerst_n) if(!rst_n) begin w_ptr_reg <= 0; r_ptr_reg <= 0; full_reg <= 1'b0; empty_reg <= 1'b1; end else begin w_ptr_reg <= w_ptr_next; r_ptr_reg <= r_ptr_next; full_reg <= full_next; empty_reg <= empty_next; end // next-state logic for read and write pointers always@* begin // successive pointer values w_ptr_succ = w_ptr_reg + 1; r_ptr_succ = r_ptr_reg + 1; // default: keep old values w_ptr_next = w_ptr_reg; r_ptr_next = r_ptr_reg; full_next = full_reg; empty_next = empty_reg; case({wr, rd}) // 2'b00: no op 2'b01: // read if(~empty_reg) // not empty begin r_ptr_next = r_ptr_succ; full_next = 1'b0; if(r_ptr_succ==w_ptr_reg) empty_next = 1'b1; end 2'b10: // write if(~full_reg) // not full begin w_ptr_next = w_ptr_succ; empty_next = 1'b0; if(w_ptr_succ==r_ptr_reg) full_next = 1'b1; end 2'b11: // write and read begin w_ptr_next = w_ptr_succ; r_ptr_next = r_ptr_succ; end endcase end // output assignfull = full_reg; assignempty = empty_reg; endmodule |
代碼被分為寄存器文件和FIFO控制器兩部分??刂破饔蓛蓚€(gè)指針和兩個(gè)標(biāo)志觸發(fā)器組成,它們的次態(tài)邏輯會(huì)檢測(cè)wr和rd信號(hào),以采取相應(yīng)的動(dòng)作。舉例說(shuō),在“10”條件下,即暗示只發(fā)生寫(xiě)操作。先檢查標(biāo)志觸發(fā)器,以確保緩存不為滿。如果滿足條件,我們將寫(xiě)指針前進(jìn)一位,并清除空標(biāo)志。再多存儲(chǔ)一個(gè)字(偏移地址為1所對(duì)應(yīng)的數(shù)據(jù))可能使得FIFO緩存滿,即新的寫(xiě)指針趕上了讀指針,我們使用w_ptr_succ==r_ptr_reg表達(dá)式來(lái)描述這一情況。
根據(jù)圖2,我寫(xiě)了下面的testbench,其RTL仿真結(jié)果與圖2一致。
代碼 FIFO緩存的testbench
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
`timescale1ns/1ns modulefifo_tb; localparam T=20; // clock period // global clock and asyn reset regclk, rst_n; // fifo interface regrd, wr; wireempty, full; reg[7:0] w_data; wire[7:0] r_data; // fifo instantiation fifo #(.B(8), .W(3)) fifo_inst ( .clk(clk), .rst_n(rst_n), .rd(rd), .wr(wr), .empty(empty), .full(full), .w_data(w_data), .r_data(r_data) ); // clcok always begin clk = 1'b0; #(T/2); clk = 1'b1; #(T/2); end // reset initial begin rst_n = 1'b0; #(T/2) rst_n = 1'b1; end // stimulus body initial begin // initial input; empty rd=0; wr=0; w_data=8'h00; @(posedgerst_n); // wait to deassert rst_n @(negedgeclk); // wait for a clock // 1 write wr=1; w_data=8'h11; @(negedgeclk); // wait to assert wr wr=0; @(negedgeclk); // wait to deassert wr // 3 writes wr=1; repeat(3) begin w_data=w_data+8'h11; @(negedgeclk); end wr=0; @(negedgeclk); // 1 read rd=1; @(negedgeclk); // wait to assert rd rd=0; @(negedgeclk) // wait to deassert rd // 4 writes wr=1; repeat(4) begin w_data=w_data+8'h11; @(negedgeclk); end wr=0; @(negedgeclk); // 1 write; full wr=1; w_data=8'hAA; @(negedgeclk); wr=0; @(negedgeclk); // 2 reads rd=1; repeat(2) @(negedgeclk); rd=0; @(negedgeclk); // 5 reads rd=1; repeat(5) @(negedgeclk); rd=0; @(negedgeclk); // 1 read; empty rd=1; @(negedgeclk); rd=0; @(negedgeclk); $stop; end endmodule |
圖3 RTL級(jí)仿真波形
審核編輯:湯梓紅
-
寄存器
+關(guān)注
關(guān)注
31文章
5343瀏覽量
120363 -
fifo
+關(guān)注
關(guān)注
3文章
388瀏覽量
43679 -
Verilog
+關(guān)注
關(guān)注
28文章
1351瀏覽量
110100 -
緩存
+關(guān)注
關(guān)注
1文章
240瀏覽量
26678 -
RTL
+關(guān)注
關(guān)注
1文章
385瀏覽量
59785
原文標(biāo)題:Verilog設(shè)計(jì)FIFO
文章出處:【微信號(hào):Hack電子,微信公眾號(hào):Hack電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論