HDLBits(七)学习笔记——Latches and Flip-Flops (锁存器和触发器)

D触发器

对于边沿触发的D触发器,具有两个稳定状态,即"0"和"1",D触发器在时钟脉冲CP的前沿(正跳变0→1)发生翻转。
在这里插入图片描述

练习1 DFF

创建一个D触发器:

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

练习2 DFF8

创建 8位 D 触发器

module top_module (
    input clk,
    input [7:0] d,
    output [7:0] q
);
    
    always @(posedge clk) begin
        q <= d;
    end

endmodule

练习3 DFF8r

创建一个带有高电平有效 同步复位 的 8 位 D触发器

module top_module (
    input clk,
    input reset,            // Synchronous reset
    input [7:0] d,
    output [7:0] q
);
    
    always @ (posedge clk)begin //同步
        if(reset) //高电平复位
            q <= 8'b0;
        else
            q <= d;
    end

endmodule

练习4 DFF8P

创建具有高电平有效 同步复位功能的 8 D 触发器。触发器必须重置为0x34而不是零。所有DFF都应由clk的负边触发

module top_module (
    input clk,
    input reset,
    input [7:0] d,
    output [7:0] q
);
    always @ (negedge clk)begin
        if(reset)
            q <= 8'h0x34;
        else
            q <= d;
    end

endmodule

练习5 Dff8ar

创建一个16D触发器,当我们仅需要修改部分触发器中的值的时候,即可采用字节信号控制的方式,其中字节使能信号byteena控制当前时钟周期中16个寄存器中哪个字节需被修改。byteena[1]控制高字节d[15:8],而byteena[0]控制低字节d[7:0]。

resetn是一个同步,低复位信号。

所有的D触发器由clk的上升沿触发

module top_module (
    input clk,
    input resetn,
    input [1:0] byteena,
    input [15:0] d,
    output [15:0] q
);
    
    always @ (posedge clk )begin
        if(!resetn)begin
            q <= 16'b0;
        end
        else begin

            if(byteena[1])
                q[15:8] <= d[15:8];
            else
                q[15:8] <= q[15:8];
            if (byteena[0])
                q[7:0] <= d[7:0];
            else
                q[7:0] <= q[7:0];
        end 
    end

endmodule

练习6 D Latch

在这里插入图片描述
D 锁存器

module top_module (
    input d, 
    input ena,
    output q
);    
    always @ (*)begin
        if(ena)
           q = d; 
    end      
endmodule

练习7 DFFAR

AR相当于清零信号
在这里插入图片描述

module top_module (
    input clk,
    input d, 
    input ar,   // asynchronous reset
    output q
);

    always @ (posedge clk or posedge ar)begin
        if(ar)begin
            q <= 1'b0;
        end
        else begin
            q <= d;
        end
    end

endmodule

练习8 DFFR

在这里插入图片描述

module top_module (
    input clk,
    input d, 
    input r,   // synchronous reset
    output q);

    always @(posedge clk) begin
        if(r) begin
            q<=1'b0;
        end
        else begin
            q<=d;
        end
    end
    
endmodule

练习9 DFF + 异或门

在这里插入图片描述

module top_module (
    input clk,
    input in, 
    output out);

    always @(posedge clk) begin
        out <= (in ^ out);
    end
    
endmodule

练习10 muxdff(多路器+D触发器)

本题在top顶层模块中给出了两个信号,r_in 和 q_in,其中r_in代表r0,r1,r2,q_in 表示最后一个D触发器的输入D,相当于我们无需一级一级的进行分析计算,默认前面结果计算完成。
在这里插入图片描述

module top_module (
	input clk,
	input L,
	input r_in,
	input q_in,
	output reg Q
);
    always @(posedge clk) begin
        Q <= L ? r_in : q_in ;
    end
    
endmodule

练习11 n位移位寄存器

在这里插入图片描述

module top_module (
    input clk,
    input w, R, E, L,
    output Q
);
    always @ (posedge clk) begin
        case({E,L})  //EL为sel
            2'b00:Q<=Q;
            2'b01:Q<=R;
            2'b10:Q<=w;
            2'b11:Q<=R;
        endcase
    end
  
endmodule

练习12 有限状态机电路

给定有限状态机电路,如图所示,假设在机器启动之前,D触发器最初为零
在这里插入图片描述
注意点:给出的top模块中,将输出Z定义定义为了默认的wire,因此我们需要定义内部连线,并且采用assign语句进行赋值。

module top_module (
    input clk,
    input x,
    output z
); 
    reg Q1;
    reg Q2;
    reg Q3;
    always @ (posedge clk)begin
        Q1 <= (x ^ Q1);
        Q2 <= (x & ~Q2);
        Q3 <= (x | ~Q3);
    end
    
    assign z = ~(Q1|Q2|Q3);
    
endmodule

练习13 JK触发器

JK触发器真值表如下,只使用D触发器和逻辑门实现JK触发器。
Qold是时钟上升沿前的D触发器的输出

在这里插入图片描述

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 <= 1'b0;
            2'b10: Q <= 1'b1;
            2'b11: Q <= ~Q;
        endcase
    end
    
endmodule

练习14 检测脉冲边沿

边沿:由 0 —— 1,或者1——0,将前后进来的信号做异或运算即可检测脉冲边沿,即两个电平不相同则是发生边沿。 上升沿pedge 由 0
—— 1 ,因此 pedge <= ~temp_in & in; 下降沿nedge由 1—— 0,因此 nedge <= temp_in
& ~ in;

对于8位向量中的每一位,检测输入信号何时从一个时钟周期的0变化到下一个时钟周期的1(上升沿检测)。输出位应该在发生0到1转换后的周期,如下示意图所示:
在这里插入图片描述

//上升沿检测
module top_module (
    input clk,
    input [7:0] in,
    output [7:0] pedge
);
    reg [7:0] temp_in;
    
    always @(posedge clk) begin
        temp_in <= in;
        pedge <= ~temp_in & in;  //与运算,in=1,temp_in=0,也就是由0变成1,为上升沿
    end

endmodule
//边沿检测
module top_module (
    input clk,
    input [7:0] in,
    output [7:0] anyedge
);
        reg [7:0] temp_in;
    always @(posedge clk) begin
        temp_in <= in;
        anyedge <= temp_in ^ in;
    end

endmodule

练习15 边沿捕获寄存器

对于32位向量中的每一位,当输入信号从一个时钟周期的1变化到下一个时钟周期的0时捕获(捕捉下降沿),“捕获”意味着输出将保持1直到被reset(同步重置)。

每个输出位的行为就像一个SR触发器:输出位应在发生1到0转换后的周期被设置(为1)。当复位为高时,输出位应该在正时钟边缘复位(为0)。如果上述两个事件同时发生,则reset具有优先级
在这里插入图片描述

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
    reg [31:0] temp_in;
    reg [31:0] state;
    integer i;
    
    always @(posedge clk) begin
        temp_in <= in;
        for(i=0;i<32;i++) begin
            case({temp_in[i] & ~in[i],reset})  //下降沿和复位的拼接
                2'b10:out[i]<=1'b1;  //下降沿且未复位时,输出保持1
                2'b11:out[i]<=1'b0;  //下降沿且复位时,输出保持0
                2'b01:out[i]<=1'b0;  //上降沿且复位时,两者同时发生则复位优先,复位说明输出0
                default:out[i]<=out[i];
            endcase
        end
    end

endmodule
//方法二
module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);

    reg [31:0] temp_in;
    
    always @(posedge clk) begin
        temp_in <= in;
    end
    
    always @(posedge clk) begin
        if(reset)begin
            out<=32'b0;
        end
        else begin
            out<=temp_in & ~in | out;
        end
    end
     
endmodule

练习16 双边沿触发器

在这里插入图片描述
注意 always @ (posedge clk or negedge clk) 不能用,其不可综合

这里可使用我们前面提到的边沿检测的方法,(异或运算)

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

    reg q1,q2;
    
    always @(posedge clk) begin
        q1<= d ^ q2;
    end
    
    always @(negedge clk) begin
        q2<= d ^ q1;
    end
    
    assign q = q1 ^ q2; 
        
endmodule
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Fighting_FPGA

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

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

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

打赏作者

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

抵扣说明:

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

余额充值