首页 > 编程知识 正文

双d触发器74ls74(双边沿D触发器)

时间:2023-05-03 11:52:00 阅读:121971 作者:3127

我对问题有了特别有趣的问题。 链接:硬盘位。 其中,模块说明如下。

moduletop_module(inputclk,input d,output q );

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

解决1? always语句在上升沿和下降沿都捕获信号d吗?

verilogmoduletop _ module (input clk,input d,output q ); reg q_reg; Always@(Posedgeclk,negedge clk ) begin q_reg=d; end assign q=q_reg; endmodule好家伙不能直接集成。

错误: [ synth8- 91 ] ambiguousclockineventcontrol。 //事件控制表达式不明确意味着always语句不能同时敏感地延长上升沿和下降沿,那么将级别设置为敏感怎么样?d为高电平时,q为高电平,d为低电平时,q输出低电平。

解决2? verilogmoduletop _ 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高电平建立

moduletop_module(inputclk,input d,output q ); reg q1、q2、q_reg; assign q=q_reg; Always@(Posedgeclk ) begin q1=d; endalways@(negedgeclk ) begin q2=d; endalways@(clk ) Beginif ) clk ) q_reg=q1; else q_reg=q2; 最终模块RTL

sim模块TB (; reg clk; reg交换机; reg d1、d2; 初始begin clk=0; 开关=0; d1=0; d2=0; # 1交换机=1end 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 )、//initialve //1-bitclockinput.ce(1) B1 )/1-bitclockenableinput.D1 ) D1 )、//1-bitdatainput (定位边缘).D2 )。 assign d=switch? 问题Q:1'b0; top_moduletest(.clk )、 d )、 q ); endmodule增加36行的理由是,在vivado模拟的情况下,ODDR基元输出的q信号是100ps的不定状态,如果不相加,则导致解法4的模拟top_module输出的q信号是x。

36: ass

ign d = switch?Q:1'b0;

其中仿真d信号利用 ODDR原语在clk上下沿输出,可以看到模块输出的q信号确实是寄存了d信号,但是延迟了1个半周期。并不完美切合题目。

解法4 verilog

官方的答案

module top_module(input clk,input d,output q);reg p, n;// A positive-edge triggered flip-flop always @(posedge clk) p <= d ^ n; // A negative-edge triggered flip-flop always @(negedge clk) n <= d ^ p; // Why does this work? // After posedge clk, p changes to d^n. Thus q = (p^n) = (d^n^n) = d. // After negedge clk, n changes to p^n. Thus q = (p^n) = (p^d^p) = d. // At each (positive or negative) clock edge, p and n FFs alternately // load a value that will cancel out the other and cause the new value of d to remain. assign q = p ^ n;endmodule

其中利用

异或运算可以随意调换异或项位置并且保持运算后结果不变。

p ⊕ d ⊕ p = d ⊕ p ⊕ p poplus doplus p = doplus poplus p p⊕d⊕p=d⊕p⊕p

0和任意项异或,依然保持任意项的原值。

0 ⊕ 1 = 1 0 ⊕ 0 = 0 begin{aligned} 0oplus1&=1\ 0oplus0&=0 end{aligned} 0⊕10⊕0​=1=0​

正如它所注释的,在clk上升沿
q = ( p ⊕ n ) = ( d ⊕ n ⊕ n ) = d q = (poplus n) = (doplus noplus n) = d q=(p⊕n)=(d⊕n⊕n)=d
在clk下降沿
q = ( p ⊕ n ) = ( p ⊕ d ⊕ p ) = ( d ⊕ p ⊕ p ) = d q = (poplus n) = (poplus doplus p) =(doplus poplus p)= d q=(p⊕n)=(p⊕d⊕p)=(d⊕p⊕p)=d

rtl

因此无论何时,q将始终跟随d信号的值,并延迟相对于d信号半个周期。

sim

由于p,n寄存器未赋初值,同样会导致在vivado里面仿真不了,这和上一个不一样,这里n是x,则p<=d^n也将是x,最终的输出也将是x。故增加一个赋初值的语句。

module top_module ( input rst_n, input clk, input d, output q); reg p ; reg n ;initial begin p = 0; n = 0;end always @(posedge clk) p <= d ^ n; always @(negedge clk) n <= d ^ p; assign q = p ^ n; endmodule

仿真代码和解法3的一致。

可以看到模块输出的q信号不但寄存了d信号,并且延迟了半个周期,满足题目要求。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。