Part 1,功能定義:
用16*8 RAM實現一個同步先進先出(FIFO)隊列設計。由寫使能端控制該數據流的寫入FIFO,並由讀使能控制FIFO中數據的讀出。寫入和讀出的操作(高電平有效)由時鍾的上升沿觸發。當FIFO的數據滿和空的時候分別設置相應的高電平加以指示。FIFO是英文First In First Out 的縮寫,是一種先進先出的數據緩存器,它與普通存儲器的區別是沒有外部讀寫地址線,這樣使用起來非常簡單,但缺點就是只能順序寫入數據,順序的讀出數據,其數據地址由內部讀寫指針自動加1完成,不能像普通存儲器那樣可以由地址線決定讀取或寫入某個指定的地址。
所謂同步FIFO是指讀時鍾和寫時鍾采用同一個時鍾。同時,異步FIFO就是指讀寫時鍾不一致。
Part 2.頂層信號定義:
| 信號名稱 |
I/O |
功能描述 |
源/目標 |
備注 |
| Rst |
In |
全局復位(低有效) |
管腳 |
|
| Clk |
In |
全局時鍾 |
管腳 |
頻率10Mhz;占空比:50% |
| W_en |
In |
高有效寫使能 |
管腳 |
|
| R_en |
In |
高有效讀使能 |
管腳 |
|
| Data_in[7:0] |
In |
數據輸入端 |
管腳 |
|
| Data_out[7:0] |
Out |
數據輸出端 |
管腳 |
|
| Empty |
Out |
空指示信號 |
管腳 |
為高時表示fifo空 |
| Full |
Out |
滿指示信號 |
管腳 |
為高時表示fifo滿 |
Part 3.頂層模塊即划分:
該同步fifo可划分為如下四個模塊,如圖所示:
①存儲器模塊(RAM) ——用於存放及輸出數據;
②讀地址模塊(r_addr) ——用於讀地址的產生;
③寫地址模塊(w_addr)——用於寫地址的產生
④標志模塊(flag_gen) ---- 用於產生FIFO當前空滿狀態。

Part 4.RAM塊:
RAM塊的源碼
本設計中采用16*8的雙扣RAM,以循環讀寫的方式實現。
根據r_addr模塊產生的讀地址在,讀使能(ren==1)時,將r_addr[4:0]地址中的對應單元的數據在時鍾上升沿到來時,讀出到data_out[7:0]中;
根據w_addr模塊產生的寫地址,在寫實能(wen==1)時,在時鍾沿的上升沿到來時,將data_in[7:0]中的數據寫入到w_addr[4:0]地址對應的單元。
1 //16*8 RAM define (七個端口) 2 module RAM(clk,ren,wen,r_addr,w_addr,data_in,data_out); 3 input clk,ren,wen; 4 input [4:0]r_addr,w_addr; 5 input [7:0]data_in; 6 output [7:0]data_out; 7 reg [7:0]data_out; 8 reg [7:0]fifo[15:0]; 9 always @(posedge clk) 10 begin 11 if(ren==1) 12 begin data_out<=fifo[r_addr]; end 13 end 14 always @(posedge clk) 15 begin 16 if(wen==1) 17 begin fifo[w_addr]<=data_in; end 18 end 19 endmodule
Part 5.r_addr產生塊:
該模塊用於產生FIFO讀數據時所用的地址。由於16個RAM單元可以用4位地址線尋址。本模塊用5位計數器(rd_addr[4:0])實現讀地址的產生。
在復位時(rst=0),讀地址值為0。
如果FIFO未空(~empty)且有讀使能(r_en)有效,則r_addr[4:0]加1;否則不變。
1 //read address genaration 2 module r_addr_gen(clk,rst,ren,r_addr,empty); 3 input clk,rst,ren,empty; 4 output [4:0]r_addr; 5 reg [4:0]r_addr; 6 always @(posedge clk) //negedge rst can be here to make it asynchronous 7 begin 8 if (!rst) begin r_addr<=5'b00000; end 9 else if(ren==1&&empty==0) begin r_addr<=r_addr+1;end 10 else begin r_addr<=5'b00000; end 11 end 12 endmodule
Part 6.w_addr產生塊:
該模塊用於產生FIFO寫數據時所用的地址。由於16個RAM單元可以用4位地址線尋址。
在復位時(rst=0),寫地址值為0。
如果FIFO未滿(~full)且有寫使能(w_en)有效,則w_addr[4:0]加1;否則不變。
1 //write address genaration 2 module w_addr_gen(clk,rst,wen,w_addr,full); 3 input clk,rst,wen,full; 4 output [4:0]w_addr; 5 reg [4:0]w_addr; 6 always @(posedge clk) //negedge rst can be here to make it asynchronous 7 begin 8 if (!rst) begin w_addr<=5'b00000; end 9 else if(wen==1&&full==0) begin w_addr<=w_addr+1;end 10 else begin w_addr<=5'b00000; end 11 end 12 endmodule
Part 7.空滿標志產生塊:
flag_gen模塊產生FIFO空滿標志。本模塊設計並不用讀寫地址判定FIFO是否空滿。設計一個計數器,該計數器(pt_cnt)用於指示當前周期中FIFO中數據的個數。由於FIFO中最多只有16個數據,因此采用5位計數器來指示FIFO中數據個數。具體計算如下:
1)復位的時候,count=0;
2)如果w_en和r_en同時有效的時候,count不加也不減;表示同時對FIFO進行讀寫操作的時候,FIFO中的數據個數不變。
3)如果w_en有效且full=0,則count+1;表示寫操作且FIFO未滿時候,FIFO中的數據個數增加了1;
4)如果r_en有效且empty=0,則count-1; 表示讀操作且FIFO未滿時候,FIFO中的數據個數減少了1;
5)如果count=0的時候,表示FIFO空,需要設置empty=1;如果count=16的時候,表示FIFO現在已經滿,需要設置full=1。
1 //empty and full flag gennaration 2 module flag_gen(clk,rst,ren,wen,empty,full); 3 input clk,ren,wen,rst; 4 output empty,full; 5 reg empty,full; 6 reg [4:0]count; 7 parameter max=5'b01111; 8 9 always @(posedge clk) 10 begin 11 if(!rst) begin count<=0;end 12 else case({ren,wen}) 13 2'b00: count<=count; 14 2'b01: if(count!=max) count<=count+1; 15 2'b10: if(count!=5'b0)count<=count-1; 16 2'b11: count<=count; 17 default:count<=count; 18 endcase 19 end 20 21 always @(count) 22 begin 23 if (count==max) full<=1; 24 else full<=0; 25 end 26 27 always @(count) 28 begin 29 if (count==5'b0) empty<=1; 30 else empty<=0; 31 end 32 endmodule
