HDLbits-时序逻辑Dff部分

DFF前面部分都比较简单,这里不赘述,直接从值得注意的开始做笔记。

Create circuit from turth table

在这里插入图片描述
这一题一开始我是用if-else做的,很符合常规思路,后面了解到原来还可以用case来描述,只要把两个要判断的条件括起来就行。

module top_module (
    input clk,
    input j,
    input k,
    output Q); 

    always@(posedge clk)
        begin
            case({j,k})
                2'b00 : Q <= Q;
                2'b01 : Q <= 0;
                2'b10 : Q <= 1;
                2'b11 : Q <= ~Q;
            endcase
        end
    
endmodule

边沿检测

时钟边沿检测是一个比较重要的内容,所以也花了不少的时间进行梳理。

Detect an edge

上升沿检测:

module top_module(
	input clk,
	input [7:0] in,
	output reg [7:0] pedge);
	
	reg [7:0] d_last;	
			
	always @(posedge clk) begin
		d_last <= in;			// Remember the state of the previous cycle
		pedge <= in & ~d_last;	// A positive edge occurred if input was 0 and is now 1.
	end
	
endmodule

粗略地汇总一下,方便记忆和理解,可能有误,请多指教。(下图不是很严谨,只是为了理解,如果把clk也画出来会更好)

  • 当检测到上升沿或者下降沿的时候,产生一个周期宽度的脉冲,就适合通过将信号打一拍后与原信号进行运算。
    • 上升沿:将原信号in打一拍并求反得到~in1,再和原信号in进行与运算,即可检测上升沿。(由于 in & ~in1是非阻塞赋值给pedge,所以会在下一个clk才会赋值,因此波形会慢一拍)
    • 下降沿:将原信号in打一拍得到in1,再将in求反后和in1进行与运算,即可检测下降沿。
    • 双边沿:这更简单,直接将in打一拍得到in1后跟in进行异或即可。
  • 从这个练习我才稍微懂了一点所谓的打一拍具体指什么。其实在非阻塞赋值<=时,综合器就会产生一个DFF,那么<=右边计算完的数(右值组合电路计算可以当做瞬间完成)会在下一拍才能给到左值。

在这里插入图片描述
进一步解释:
根据电路图很好理解,为了让原来的信号保持一下也可以说是延迟一个时钟,就能做出上升沿的判断,后面加入一个寄存器的目的就是为了让检测延迟一个时钟显示,也保证检测只持续一个时钟。(如果想让检测信号不止持续一个时钟,那参考下面的Edge capture register)

参考网址:https://blog.csdn.net/weixin_42664351/article/details/112131448

Detect both edges在这里插入图片描述

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] anyedge
);

    reg [7:0] last;
    always@(posedge clk)
        begin
       		last <= in;
            anyedge <= last ^ in;
        end
endmodule

Edge capture register

在这里插入图片描述
这道题和之前不一样的地方在于,一旦检测到下降沿,就让检测信号一直保持1,直到被重置。因此需要每个位矢量都进行下降沿检测,如果有下降沿就置1,否则就保持。
参考代码:

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);

    reg [31:0] last;
    always@(posedge clk)
        begin
            last <= in;
            if(reset)
            	out <= 0;
            else
                begin
                //last <= in;
                    for(int i=0; i < 32; i = i+1)
                        out[i] <= (~in[i] & last[i]) ? 1 : out[i];   
                        //单纯写out[i] <= ~in[i] & last[i],则只有一个脉冲而已
                end
        end
endmodule

注:一开始将last <= in 写在了重置信号后,感觉没什么问题,但是报错了。后来把电路图画出来才知道,打拍需要在组合逻辑之前进行的。不过这个图只是单指一位的情况。
在这里插入图片描述

Dual-edge triggered flip-flop

在这里插入图片描述
思路分析:

  • 双沿触发触发器在时钟的两个边沿触发。但是,FPGA没有双沿触发触发器,因此始终不接受@(posedge clk或negedge clk)作为合法敏感性列表。
  • 分别写出正沿触发和负沿触发的D触发器,赋值给q1,q2,再利用clk作为地址进行选择,上升沿就将q1给q,下降沿将q2给q.

参考代码:

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

    reg q1,q2;
    
    always@(posedge clk)
        begin
       		q1 <= d;
        end

    always@(negedge clk)
        begin
       		q2 <= d;
        end
	
    assign q = clk ? q1 : q2;
endmodule

附上综合图
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hardworking_IC_boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值