3.6 握手信號方法

1)X將數放在資料總線上兵發出xreq信號,表示有效資料已經發到接收器Y的資料總線上,
2)xreq信號同步到接收器時鐘域ylk上,
3)Y在識別xreq同步的信號yreq2后,鎖存資料總線上信號,
4)Y發出確認信號yack,表示其已經接收了資料,
5)yack同步到發送時鐘xclk上,
6)X識別到同步的xack2信號后,將下一個資料放到資料總線上,

如圖,安全地將一個資料從發送器傳輸到接收器需要5個時鐘周期,
3.6.1 握手信號的要求
資料應在發送時鐘域內穩定至少兩個時鐘上升沿,
xreq寬度應該超過兩個上升沿時鐘,否則從高速時鐘域到低速時鐘域傳遞可能無法捕捉到該信號,
3.6.2 握手信號缺點
傳輸單個資料延遲比FIFO傳輸同樣的資料大得多,
3.7 使用同步FIFO傳輸資料
3.7.1 同步FIFO架構

寫指標指向下一個要寫的地址,讀指標指向下一個要讀的地址,寫使能使寫指標遞增,讀使能使讀指標遞增,
根據讀寫指標可以產生空信號和滿信號,也可以對FIFO內資料進行計數,
DPRAM可以同步讀取或者異步讀取,同步讀時,應在FIFO輸出有效前給都信號,異步讀時,輸出不會寄存,資料只要一寫入就可用,
3.7.2 同步FIFO的作業方式
3.7.2.1 FIFO空滿的產生

圖中為FIFO滿的情況,當讀指標等于寫指標加一并進行寫操作,FIFO滿,
同樣,當讀操作使兩個指標在下個周期相等時,FIFO變空,
3.7.2.2 另一種方法
另一種方法使使用計數器來指示FIFO中慷訓滿位置的個數,寫入資料時計數器加一,讀取資料時計數器減一,
這種方法原理上簡單,但是要增加額外的硬體(比較器),FIFO深度增加,比較器寬度也會增加,這最侄訓降低FIFO操作的最高頻率,
`timescale 1ns / 1ps module FIFO#( parameter WIDTH=16, parameter DEPTH=8 ) ( input clk, input reset_n, input [WIDTH-1:0]wr_data, input wr_en, input rd_en, output reg[WIDTH-1:0]rd_data, output reg fifo_full, output reg fifo_empty ); localparam RAM_SIZE=(1<<DEPTH); reg [DEPTH-1:0]rd_ptr,wr_ptr; reg [WIDTH-1:0]DPRAM[RAM_SIZE-1:0]; always @(posedge clk or negedge reset_n) begin if(~reset_n) rd_data <= 'd0; else begin if(wr_en && ~fifo_full) DPRAM[wr_ptr] <= wr_data; if(rd_en && ~fifo_empty) rd_data <= DPRAM[rd_ptr]; end end always @(posedge clk or negedge reset_n) begin:fifo_full_gen if(~reset_n) fifo_full <= 1'b0; else if(wr_en && rd_en) ;//do nothing else if(rd_en) fifo_full <= 1'b0; else if(wr_en && (rd_ptr == wr_ptr +1'b1)) fifo_full <= 1'b1; end always @(posedge clk or negedge reset_n) begin:fifo_empty_gen if(~reset_n) fifo_empty <= 1'b1; else if(wr_en && rd_en) ;//do nothing else if(wr_en) fifo_empty <= 1'b0; else if(rd_en && (wr_ptr == rd_ptr +1'b1)) fifo_empty <= 1'b1; end always @(posedge clk or negedge reset_n) begin:rd_ptr_gen if(~reset_n) rd_ptr <= 'd0; else if(rd_en && ~fifo_empty) rd_ptr <= rd_ptr +1'b1; end always @(posedge clk or negedge reset_n) begin:wr_ptr_gen if(~reset_n) wr_ptr <= 'd0; else if(wr_en && ~fifo_full) wr_ptr <= wr_ptr +1'b1; end endmodule
testbench
`timescale 1ns / 1ps module tb_fifo(); reg clk,rst_n,wr_en,rd_en; wire full,empty; reg [15:0]wr_data; wire [15:0]rd_data; initial begin clk = 0; rst_n = 0; wr_en = 0; rd_en = 0; wr_data = 0; #100 rst_n = 1; while(~full) begin #20 wr_en <= 1'b1; wr_data <= wr_data + 1'b1; end repeat(100) begin @(posedge clk)begin wr_en = {$random} %2; rd_en = {$random} %2; end end $finish; end always #10 clk = ~clk; FIFO my_fifo( .clk(clk), .reset_n(rst_n), .wr_data(wr_data), .wr_en(wr_en), .rd_en(rd_en), .rd_data(rd_data), .fifo_full(full), .fifo_empty(empty) ); endmodule
仿真結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/538167.html
標籤:其他
