Verilog學習筆記簡單功能實現(八)...............同步FIFO


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

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM