快時鍾域同步到慢時鍾域--握手協議--verilog實現


前文分析請看https://www.cnblogs.com/shadow-fish/p/13451214.html

快時鍾域同步到慢時鍾域--單bit同步代碼:

module test (
    input clka,
    input clkb,
    input rst,
    input d_in,
    output reg d_out
);
    reg req_a;
    reg req_a_1;
    reg req_a_2;
    reg req_a_3;
    reg ack_b;
    reg ack_b_1;
    reg ack_b_2;

    always @(posedge clkb or negedge rst) begin//將req_a同步到慢時鍾域,告訴慢時鍾域,數據已經准備好
        if(!rst) begin
            req_a_1 <= 'b0;
            req_a_2 <= 'b0;
            req_a_3 <= 'b0;
        end
        else begin
            req_a_1 <= req_a;
            req_a_2 <= req_a_1;
            req_a_3 <= req_a_2;
        end
    end
    always @(posedge clkb or negedge rst) begin
        if(!rst) begin
            d_out <= 'b0;
        end
        else if (req_a_2 == 1'b1) begin
            d_out <= req_a_2 & (~req_a_3);
        end
        else begin
            d_out <= d_out;
        end
    end
    always @(posedge clkb or negedge rst) begin//發送ack,告訴慢時鍾域,數據已經讀取結束
        if(!rst) begin
            ack_b <= 'b0;
        end
        else if(req_a_2 == 1'b1) begin
            ack_b <= 'b1;
        end
        else begin
            ack_b <= 'b0;
        end
    end
    always @(posedge clka or negedge rst) begin//將慢時鍾域發出的ack信號同步到快時鍾域,表示讀取結束
        if(!rst) begin
            ack_b_1 <= 'b0;
            ack_b_2 <= 'b0;
        end
        else begin
            ack_b_1 <= ack_b;
            ack_b_2 <= ack_b_1;
        end
    end
  //assign req_a = (d_in==1'b1)?1'b1:((ack_b_2==1'b1)?1'b0:req_a);有可能下面的兩個時序邏輯不能正確捕捉到d_in的信號導致出錯
always @(posedge clka or negedge rst) begin//快時鍾將數據放到總線上,然后發送req信號繼續提醒 if(!rst) begin req_a <= 'b0; end else if(d_in == 1'b1)begin req_a <= 1'b1; end else begin req_a <= 'b0; end end always @(posedge clka or negedge rst) begin if(!rst) begin req_a <= 'b0; end else if (ack_b_2 == 1'b1) begin req_a <= 'b0; end else begin req_a <= req_a; end end endmodule

測試用例:

`timescale 1ns/10ps
module test_tb;
    
    reg clka;
    reg clkb;
    reg rst;
    reg d_in;
    wire d_out;

    test u1(
    .clka(clka),
    .clkb(clkb),
    .rst(rst),
    .d_in(d_in),
    .d_out(d_out)
);

    initial begin
        clka = 'b1;
        clkb = 'b1;
        rst = 'b0;
        #8 rst = 'b1;
    end
    always #5 clka = ~clka;
    always #12 clkb = ~clkb;
    initial begin
    d_in = 'b0;
        #20;
        d_in = 'd1;
        #10 d_in = 'd0;
    end
endmodule

questasim仿真波形:

 

 

快時鍾域同步到慢時鍾域--多bit同步代碼:多bit的代碼透露着一絲古怪,如發現問題請留言,以便改進。

module test (
    input clka,
    input clkb,
    input rst,
    input [7:0]d_in,
    output reg [7:0]d_out
);
    reg req_a;
    reg req_a_1;
    reg req_a_2;
    reg ack_b;
    reg ack_b_1;
    reg ack_b_2;
    reg [7:0]d_in_line;

    always @(posedge clkb or negedge rst) begin//將req_a同步到慢時鍾域,告訴慢時鍾域,數據已經准備好
        if(!rst) begin
            req_a_1 <= 'b0;
            req_a_2 <= 'b0;
        end
        else begin
            req_a_1 <= req_a;
            req_a_2 <= req_a_1;
        end
    end
    always @(posedge clkb or negedge rst) begin//檢測到req_a,將讀取需要傳輸的數據
        if(!rst) begin
            d_out <= 'b0;
        end
        else if (req_a_2 == 1'b1) begin
            d_out <= d_in_line;
        end
        else begin
            d_out <= d_out;
        end
    end
    always @(posedge clkb or negedge rst) begin//發送ack,告訴慢時鍾域,數據已經讀取結束
        if(!rst) begin
            ack_b <= 'b0;
        end
        else if(req_a_2 == 1'b1) begin
            ack_b <= 'b1;
        end
        else begin
            ack_b <= 'b0;
        end
    end
    always @(posedge clka or negedge rst) begin//將慢時鍾域發出的ack信號同步到快時鍾域,表示讀取結束
        if(!rst) begin
            ack_b_1 <= 'b0;
            ack_b_2 <= 'b0;
        end
        else begin
            ack_b_1 <= ack_b;
            ack_b_2 <= ack_b_1;
        end
    end
    always @(posedge clka or negedge rst) begin//快時鍾將數據放到總線上,然后發送req信號繼續提醒
        if(!rst) begin
            req_a <= 'b0;
        end
        else if(d_in_line != 'b0)begin
            req_a <= 1'b1;
        end
        else begin
            req_a <= 'b0;
        end
    end
    always @(posedge clka or negedge rst) begin
        if(!rst) begin
            d_in_line <= 'b0;
        end
        else begin
            d_in_line <= d_in;
        end
    end
    always @(posedge clka or negedge rst) begin
        if(!rst) begin
            req_a <= 'b0;
        end
        else if (ack_b_2 == 1'b1) begin
            req_a <= 'b0;
        end
        else begin
            req_a <= req_a;
        end
    end
endmodule

測試用例:

`timescale 1ns/10ps
module test_tb;
    
    reg clka;
    reg clkb;
    reg rst;
    reg [7:0]d_in;
    wire [7:0]d_out;

    test u1(
    .clka(clka),
    .clkb(clkb),
    .rst(rst),
    .d_in(d_in),
    .d_out(d_out)
);

    initial begin
        clka = 'b1;
        clkb = 'b1;
        rst = 'b0;
        #6 rst = 'b1;
    end
    always #5 clka = ~clka;
    always #22 clkb = ~clkb;
    initial begin
    d_in = 'b0;
        #80;
        d_in = 'd1;
        #160 d_in = 'd2;
        #160 d_in = 'd3;
        #160 d_in = 'd4;
        #160 d_in = 'd5;
        #160 d_in = 'd6;
        #160;
    end
endmodule

 


免責聲明!

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



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