开始进入时序部分的练习:
[D-flip-flop](Dff - HDLBits (01xz.net))
module top_module (
input clk, // Clocks are used in sequential circuits
input d,
output reg q );//
always@(posedge clk)begin
if(clk)
q<=d;
end
// Use a clocked always block
// copy d to q at every positive edge of clk
// Clocked always blocks should use non-blocking assignments
endmodule
[D-flip-flops](Dff8 - HDLBits (01xz.net))
module top_module (
input clk,
input [7:0] d,
output [7:0] q
);
always@(posedge clk)begin
q<=d;
end
endmodule
[DFF with reset](Dff8r - HDLBits (01xz.net))
module top_module (
input clk,
input reset, // Synchronous reset
input [7:0] d,
output [7:0] q
);
always@(posedge clk)begin
if(reset)begin
q=8'b0000_0000;
end
else
begin
q<=d;
end
end
endmodule
[DFF with resset value](Dff8p - HDLBits (01xz.net))
module top_module (
input clk,
input reset,
input [7:0] d,
output [7:0] q
);
always@(negedge clk)begin
if(!reset)
q<=d;
else
q<=8'h0x34;
end
endmodule
[DFF with asynchronous reset](Dff8ar - HDLBits (01xz.net))
module top_module (
input clk,
input areset, // active high asynchronous reset //异步复位端
input [7:0] d,
output [7:0] q
);
always@(posedge clk,posedge areset)begin
if(areset)begin
q<=8'b0000_0000;
end
else begin
q<=d;
end
end
endmodule
[DFF with byte enable](Dff16e - HDLBits (01xz.net))
module top_module (
input clk,
input resetn,
input [1:0] byteena,
input [15:0] d,
output [15:0] q
);
always@(posedge clk)begin //clk的触发不需要写
if(resetn)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
else
q<=16'd0;
end
endmodule
[D latch](Exams/m2014 q4a - HDLBits (01xz.net))
module top_module ( //同步使能端ena
input d,
input ena,
output q);
always@(*)begin
if(ena)begin
q=d;
end
end
endmodule
[DFF](Exams/m2014 q4b - HDLBits (01xz.net))
module top_module (
input clk,
input d,
input ar, // asynchronous reset
output q);
always@(posedge clk,posedge ar)begin
if(ar)begin
q<=0;
end
else
q<=d;
end
endmodule
[DFF](Exams/m2014 q4c - HDLBits (01xz.net))
module top_module (
input clk,
input d,
input r, // synchronous reset
output q);
always@(posedge clk)begin
if(r)begin
q<=0;
end
else
q<=d;
end
endmodule
[DFF+gate](Exams/m2014 q4d - HDLBits (01xz.net))
module top_module (
input clk,
input in,
output out);
wire d1;
assign d1=out^in;
always@(posedge clk)begin
out<=d1;
end
endmodule
[Mux and DFF](Mt2015 muxdff - HDLBits (01xz.net))
module top_module (
input clk,
input L,
input r_in,
input q_in,
output reg Q);
always@(posedge clk)begin
Q<=(r_in*L)|(q_in*~L);
end
endmodule //这一题注意并不是要求设计全部代码,而是只要求设计子模块代码即可
[Mux and DFF](Exams/2014 q4a - HDLBits (01xz.net))
module top_module (
input clk,
input w, R, E, L,
output Q
);
wire a1,d1;
assign a1=(E*w)|(~E*Q);
assign d1=(L*R)|(~L*a1);
always@(posedge clk)begin
Q<=d1;
end
endmodule
附上网上的另一种写法:
module top_module (
input clk,
input w, R, E, L,
output Q
);
always @(posedge clk) begin
case({E,L})
2'b00:Q<=Q;
2'b01:Q<=R;
2'b10:Q<=w;
2'b11:Q<=R;
endcase
end
endmodule
[DFFs and gates](Exams/ece241 2014 q4 - HDLBits (01xz.net))
module top_module (
input clk,
input x,
output z
);
wire q1,q2,q3;
wire d1,d2,d3;
assign d1=x^q1;
assign d2=x&(~q2);
assign d3=x|(~q3);
assign z=~(q1|q2|q3);
always@(posedge clk)begin
q1<=d1;
q2<=d2;
q3<=d3;
end
endmodule //写的有点繁琐,其实可以不用拎出来定义wire的
优化一下:
module top_module (
input clk,
input x,
output z
);
reg Q1,Q2,Q3;
always @(posedge clk) begin
Q1 <= (x ^ Q1);
Q2 <= (x & ~Q2);
Q3 <= (x | ~Q3);
end
assign z = ~(Q1|Q2|Q3);
endmodule
[Create circuit from truth table](Exams/ece241 2013 q7 - HDLBits (01xz.net))
module top_module (
input clk,
input j,
input k,
output Q);
always@(posedge clk)begin
Q<=(j*(~Q))|((~k)*Q);
end
endmodule
网上的方法也很有启发,灵活运用 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<=1'b0;
2'b10:Q<=1'b1;
2'b11:Q<=~Q;
endcase
end
endmodule
[Detect an edge](Edgedetect - HDLBits (01xz.net))
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∈
end
endmodule
f323e3
[[#95f54c]]
[[#818888]]
HDLBits答案(10)_ D触发器、同步与异步复位、脉冲边沿检测d触发器异步复位日拱一卒_未来可期的博客-CSDN博客 如下:
设计寄存器用来接收被检测的信号;若 {先进reg,后进reg}=2'b10
,则是下降沿;
若 {先进reg,后进reg}=2'b01
,则为上升沿。
很好,值得思考。
[Detect both edges](Edgedetect2 - HDLBits (01xz.net))
module top_module (
input clk,
input [7:0] in,
output [7:0] anyedge
);
reg [7:0]a;
always@(posedge clk)begin
a<=in;
anyedge<=a^in;
end
endmodule
在写这一个逻辑关系时使用卡诺图,记住输出 anyedge 是延迟了一个周期的图像,所以需要前移一个周期来做卡诺图,即得异或关系。
![[991a4c87928015b2a33b8ab2077cf32.jpg]]
[[#7ebd73]]
[Edge capture register](Edgecapture - HDLBits (01xz.net))
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;
2'b11:out[i]<=1'b0;
2'b01:out[i]<=1'b0;
default:out[i]<=out[i];
endcase
end
end
endmodule
或者按照题目的意思来写,因为每一位的输出位 SR 触发器
![[1686035283814.png]]
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
[Dual-edge triggered flip-flop](Dualedge - HDLBits (01xz.net))
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
总结:
- 在触发器中对于 clk,在触发时的代码中,统统不需要写明 if (clk),这一点在异步触发和同步使能的诸多代码中均已体现。个人理解是因为触发器的核心在于“q 的值只在 clk 的上升沿到达变化时变化”
- 在锁存器中对于 clk 就要写 if (clk),个人理解是尾音锁存器的核心在于“当 clk 为高电平时,输出 q 随之改变”
- 异步和同步复位(使能、置位)的区别在于是否在敏感列表中声明,见两个 DFF 的对比
- 在实操中常用的方法见 [[#f323e3]],
temp_in<=in;
实现了在寄存器中延迟一个周期的功能,如果想继续再延迟一个周期,可以写 ```temp_in1<=in; temp_in2<=temp_in1;`` 95f54c
- 此代码实现的就是先将 in 暂存入 temp_in,再将其与现在的 in 进行操作
- 对于此题,0 是 0000_0000,2 是 0000_0010,e 是 0000_1110,c 是 0000_1100,因为延迟了一个周期(temp_in 的操作),从 0 到 2,变化 2,从 2 到 e,变化 c 818888
- In[1]只是选取了其中一个位来表示
- Always 中使用时序电路,所有的寄存器输出值都要在下一个周期才出现,即延迟一个周期 7ebd73