脉冲信号跨时钟域verilog代码

目录

一、原理

二、设计代码

三、testbench

1、慢时钟域到快时钟域

 2、快时钟域到慢时钟域


一、原理

a 在第一个时钟域中检测需要跨时钟域的脉冲信号din的上升沿;

b 检测到上升沿时,将新设置的信号p_1置1;

c 将信号p_1通过打两拍同步到第二个时钟域,得到信号p_1_to_2_d2;

d  在第二个时钟域中,检测信号p_1_to_2_d2从0到1,得到同步后的脉冲信号dout;

e 将信号p_1_to_2_d2通过打两拍同步到第一个时钟域,得到信号p_2_to_1_d2;

f 在第一个时钟域中,检测信号p_2_to_1_d2从0到1,得到信号q;

g 在第一个时钟域中,当信号q为1时,将信号p_1置0;

二、设计代码

`timescale 1ns / 1ps

module cdc_pulse
(
    input clk1,
    input clk2,
    input rstn1,
    input rstn2,
    input din,
    output dout
);

reg din_d;
wire in_r;
reg p_1;

reg p_1_to_2_d1, p_1_to_2_d2;
reg p_1_to_2_d3; 

reg p_2_to_1_d1, p_2_to_1_d2;
reg p_2_to_1_d3; 

wire q;

always @ (posedge clk1 or negedge rstn1) begin
    if (~rstn1)
        din_d <= 'b0;
    else
        din_d <= din;
end

assign in_r = din & ~din_d;

always @ (posedge clk1 or negedge rstn1) begin
    if (~rstn1)
        p_1 <= 'b0;
    else if (in_r)
        p_1 <= 'b1;
    else if (q)
        p_1 <= 'b0;    
end

always @ (posedge clk2 or negedge rstn2) begin
    if (~rstn2) begin
        p_1_to_2_d1 <= 'b0;
        p_1_to_2_d2 <= 'b0;
    end
    else begin
        p_1_to_2_d1 <= p_1;
        p_1_to_2_d2 <= p_1_to_2_d1;
    end
end

always @ (posedge clk2 or negedge rstn2) begin
    if (~rstn2)
        p_1_to_2_d3 <= 'b0;
    else
        p_1_to_2_d3 <= p_1_to_2_d2;
end

assign dout = p_1_to_2_d2 & ~p_1_to_2_d3;

always @ (posedge clk1 or negedge rstn1) begin
    if (~rstn1) begin
        p_2_to_1_d1 <= 'b0;
        p_2_to_1_d2 <= 'b0;
    end
    else begin
        p_2_to_1_d1 <= p_1_to_2_d2;
        p_2_to_1_d2 <= p_2_to_1_d1;
    end
end

always @ (posedge clk1 or negedge rstn1) begin
    if (~rstn1)
        p_2_to_1_d3 <= 'b0;
    else
        p_2_to_1_d3 <= p_2_to_1_d2;
end

assign q = p_2_to_1_d2 & ~p_2_to_1_d3;


endmodule

三、testbench

1、慢时钟域到快时钟域

`timescale 1ns / 1ps

module cdc_tb();

reg clk1;
reg rst1_n;
reg clk2;
reg rst2_n;
reg cin;
wire cout;

cdc_pulse u(
    .clk1(clk1),
    .rstn1(rst1_n),
    .clk2(clk2),
    .rstn2(rst2_n),
    .din(cin),
    .dout(cout)
);

initial begin
    rst1_n = 0;
    rst2_n = 0;
    clk1 = 0;
    clk2 = 0;
    #50
    rst1_n = 1;
    rst2_n = 1;
end

always #30 clk1 = ~clk1;
always #10 clk2 = ~clk2;

initial begin
    cin <= 0;
    #90
    cin <= 1;
    #60
    cin <= 0;
end

endmodule

 2、快时钟域到慢时钟域

`timescale 1ns / 1ps

module cdc_tb();

reg clk1;
reg rst1_n;
reg clk2;
reg rst2_n;
reg cin;
wire cout;

cdc_pulse u(
    .clk1(clk1),
    .rstn1(rst1_n),
    .clk2(clk2),
    .rstn2(rst2_n),
    .din(cin),
    .dout(cout)
);

initial begin
    rst1_n = 0;
    rst2_n = 0;
    clk1 = 0;
    clk2 = 0;
    #50
    rst1_n = 1;
    rst2_n = 1;
end

always #10 clk1 = ~clk1;
always #30 clk2 = ~clk2;

initial begin
    cin <= 0;
    #70
    cin <= 1;
    #20
    cin <= 0;

end


endmodule

                                                       PS:觉得有用就点个赞收藏吧 

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值