FPGA跨时钟域握手信号的结构

   FPGA跨时钟数据传输,是我们经常遇到的问题的,下面给出一种跨时钟握手操作的电路结构。先上图

    先对与其他人的结构,这个结构最大的特点是使用 req 从低到高或者高到低的变化 来表示DIN数据有效并开始传输。并且同过判断 req与ack信号是否相等就可以判断传输是否完成。当req !=ack时表示正在传输,不可以发起新的传输操作。当req=ack时表示传输完成,可以开始新的传输过程。

  并且这样的结构在req传输发生亚稳态时也可以有效的传输信号,可以适应任意时钟域之间的数据传输。仿真图如下

 

代码:

module handshack2
#(
    parameter DATA_SIZE = 8,
    parameter SREG_LENG = 3
)
(
    input                      rsta,
    input                           clka,
    input                           reqa,//变化沿表示数据有效
    input [DATA_SIZE-1:0]      dina,
    output                           acka,
    
    input                      rstb,
    input                      clkb,
    output reg                 rdyb,
    output reg [DATA_SIZE-1:0] doutb
);

reg req_ra;
reg [DATA_SIZE-1:0] din_ra;
reg[SREG_LENG-1:0] ack_ra;

reg[SREG_LENG-1:0] req_rb;

//clka
always@(posedge clka)begin
    if(rsta)begin
        req_ra <= 0;
    end else begin
        req_ra <= reqa;
    end
    din_ra <= dina;
end

always@(posedge clka)
    if(rsta)begin
        ack_ra <= 0;
    end else begin
        ack_ra <= {ack_ra[SREG_LENG-2:0], req_rb[SREG_LENG-1]};
    end    

assign acka = ack_ra[SREG_LENG-1];
    
//clkb
always@(posedge clkb)
    if(rstb)begin
        req_rb <= 0;
    end else begin
        req_rb <= {req_rb[1:0], req_ra};
    end
    
always@(posedge clkb)begin
    if(req_rb[SREG_LENG-1]^req_rb[SREG_LENG-2])begin
        doutb <= din_ra;
    end
    rdyb <= req_rb[SREG_LENG-1]^req_rb[SREG_LENG-2];
end

endmodule

测试脚本:

module tst_handshack2;

    // Inputs
    reg rsta;
    reg clka;
    reg reqa;
    reg [7:0] dina;
    reg rstb;
    reg clkb;

    // Outputs
    wire acka;
    wire rdyb;
    wire [7:0] doutb;

    // Instantiate the Unit Under Test (UUT)
    handshack2 uut (
        .rsta(rsta), 
        .clka(clka), 
        .reqa(reqa), 
        .dina(dina), 
        .acka(acka),
        
        .rstb(rstb), 
        .clkb(clkb), 
        .rdyb(rdyb), 
        .doutb(doutb)
    );

    initial begin
        clka = 0;
        #5
        forever
        #5 clka = ~clka;
    end
    
    initial begin
        rsta <= 0;
        dina <= 0; 
        reqa <= 0;
        #100;
        
        dina <= 10;
        reqa <= !reqa;
        #10;
        wait( acka == reqa)
        #10;
        dina <= 100;
        reqa <= !reqa;
    end
     
    
    initial begin
        #2.7;
        clkb = 0;
        #3
        forever
        #3 clkb = ~clkb;
    end
    initial begin
        rstb <= 0;
        #90;
    end


      
endmodule

 

posted on 2017-07-13 16:44  gNewplayer  阅读(1850)  评论(0)    收藏  举报