双边沿D触发器

本文讨论了如何在Verilog中实现双边沿D触发器的问题,提出了四种解决方案。解决1尝试用单个always语句捕捉信号d的上升沿和下降沿,但无法综合。解决2直接连接d和q,但无法控制相位。解决3使用两个always语句分别对上升沿和下降沿敏感,通过clk电平切换输出。解决4采用官方答案,利用异或运算实现,确保q跟随d并延迟半个周期。在RTL和仿真中验证了解法的有效性。
摘要由CSDN通过智能技术生成

问题

遇到一个特别有意思的问题,链接: hdlbits.,其中模块描述如下:

module top_module (
    input clk,
    input d,
    output q
);

在这里插入图片描述

要求根据d信号的输入,输出q,但是d信号是在clk信号的双边沿变化,而q需要偏移d的半个周期,并跟随d的值变化。

解决1?

难道always语句同时在上升沿和下降沿捕捉信号d?

verilog

module top_module (
    input clk,
    input d,
    output q
);
    reg q_reg;
    always@(posedge clk,negedge clk)begin
       q_reg<=d; 
    end
    assign q= q_reg;
endmodule

好家伙直接综合不了。

ERROR: [Synth 8-91] ambiguous clock in event control。//事件控制表达式不明确

意味着always语句是无法同时将上升沿和下降沿设置成敏感延,那要是设置电平敏感呢?,在d高电平时,就输出q高电平,d低电平就输出q低电平。

解决2?

verilog

module top_module (
    input clk,
    input d,
    output q
);
    reg q_reg;
    always@(clk)begin
       q_reg = d; 
    end
    assign q= q_reg;
endmodule

直接综合成q直接连接d,只是vivado插入了IBUF,OBUF,虽然q确实是随着d变化的,但是它们之间的相位根本无法控制。也就无法完成寄存器用来稳定数据的功能。

rtl

在这里插入图片描述

解决3?

verilog

换个思路,虽然always语句无法同时设置两种敏感事件,那要是用一个always对上升沿敏感,一个always对下降沿敏感,并利用clk的电平变化,clk高电平输出always对上升沿敏感捕获的值,clk低电平输出always对下降沿敏感捕获的值,这样交替就可以输出双边沿变化d的信号。

module top_module (
    input clk,
    input d,
    output q
);
    reg q1,q2,q_reg;
    assign q = q_reg;
    always@(posedge clk)begin
       q1<=d; 
    end
    always@(negedge clk)begin
       q2<=d; 
    end
    always@(clk)begin
        if(clk)
        q_reg = q1;
        else 
        q_reg = q2;
    end
endmodule

rtl

在这里插入图片描述

sim

module tb(

    );

reg clk;
reg switch;
reg d1,d2;
initial begin
   clk          =   0;
   switch       =   0;
   d1           =   0;
   d2           =   0;
   #1 switch    =   1;
end 
always #10 clk = ~clk;
    wire q;
    wire d,Q;
    always @(posedge clk)
    d1<=    $random;
    always @(negedge clk)
    d2<=    $random;

   ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
   ) orrt_test (
      .Q(Q),   // 1-bit DDR output
      .C(clk),   // 1-bit clock input
      .CE(1'b1), // 1-bit clock enable input
      .D1(d1), // 1-bit data input (positive edge)
      .D2(d2), // 1-bit data input (negative edge
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值