HDLBits(15)3.9
3 电路
3.2 时序逻辑
3.2.1 锁存器与触发器(Latches and Flip-Flops)
- Create circuit from truth table
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
- Edgedetect(Detect an Edge)(边缘检测)
对于每个8bit的变量,检测这些信号什么时候从0变为1(类似检测上升沿),输出应该在0到1 变化之后才有值。
下图给我们展示了输入in[1]和输出pedge[1]的时序关系图:
边缘检测具体可参照文章 https://blog.csdn.net/qq_31799983/article/details/81544707
具体的设计可以采用一个寄存器Q来存储上一个时钟沿的输入值D,当寄存器输出Q与输入D的值分别为1、0时,则检测到下降沿。
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg [7:0] temp;
always @(posedge clk)
begin
temp <= in;//非阻塞赋值,不是即可生效,故temp始终比in晚一个周期
pedge <= ~temp & in;
end
endmodule
//本题与示例时序图相反,Q相当于temp,D相当于in,检测下降沿对in取反即可
- Edgedetect2(Detect both edges)
在一个8bit的变量中,从一个周期到另一个周期期间,检测输入信号变化。即上升沿变化或下降沿变化。输出应在0变为1后产生。
如下图所示为输入与输出的时序关系
上题仅针对上升沿检测,故使用 & (或)来检测;本题可以采用 ^(xor 异或)检测
module top_module (
input clk,
input [7:0] in,
output reg [7:0] anyedge
);
reg [7:0] in_temp;
always @ (posedge clk)
begin
in_temp <= in;
anyedge <= in ^ in_temp;
end
endmodule
- Edgecapture(Edge capture register)边缘捕获寄存器
对于32bit中的每一个变量,我们需要捕获输入信号的上升沿。其中捕获的意思就是说在寄存器复位之前,输出一直保持为 ‘1’ 。
每一个输出bit类似SR触发器:输出信号从1变0发生时会保持一个周期。输出会在时钟上升沿和reset信号为高时复位。如果上述事件在同一时间发生,reset有更高的优先级。在下图所示的最后4个周期内,reset信号比set信号早一个周期,所以没有冲突发生。
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] temp;//reg型数据(寄存器数据类型)常用在always模块内
wire [31:0] capture;//wire型数据常用来表示以assign指定的组合逻辑信号
//先检测信号的上升沿
always @(posedge clk)
begin
temp <= in;
end
assign capture = ~in & temp;
//检测到上升沿后,确定输出
always @(posedge clk)
begin
if(reset)
out <= 32'b0;
else
begin
for (int i=0;i<32;i=i+1)
begin
if(capture[i] == 1'b1)
out[i] <= 1'b1;
end
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;
if(reset)
out <= 32'b0;
else
out <= temp_in & ~in | out;
//temp_in & ~in检测上升沿,|out起捕获的作用(out=1,则一直为1;out=0,检测到上升沿后out=1)
end
endmodule
- Dualedge(Dual-edge triggered flip-flop)双边触发器
FPGA 没有双边触发触发器,并且始终不接受 @(posedge clk 或 negedge clk)作为合法的敏感度列表。
构建一个功能类似于双边触发触发器的电路:
(注意:它不一定完全等效:触发器的输出没有毛刺,但模拟这种行为的更大组合电路可能会。但我们将在这里忽略这个细节。)
无法在 FPGA 上创建双边触发触发器。但是可以同时创建正沿触发和负沿触发触发器。
//运用MUX
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
//运用XOR
module top_module(
input clk,
input d,
output q);
reg p, n;
// clk的上升沿
always @(posedge clk)
p <= d ^ n;
// clk的下降沿
always @(negedge clk)
n <= d ^ p;
//在上升沿时候,p=d^n, 则q=d^n^n=d;
//在下降沿时候,n=d^p, 则q=p^d^p=d;
//加载一个新值时会取消旧值。
assign q = p ^ n;
endmodule
3.2.2 计数器
- Count15(Four-bit binary counter)4bit二进制计数器
设计一个4bit的计数器,从0~15,共16个周期。reset是同步复位且复位为0
module top_module (
input clk,
input reset,
output reg [3:0] q);
always @ (posedge clk)
begin
if(reset)
q <= 4'b0000;
else
q <= q + 1'b1;
end
endmodule
- Count10(Decade counter)
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:0] q);
always @ (posedge clk)
begin
if(reset)
q <= 4'b0000;
else if(q <= 4'b1000) //这是≤,不是赋值
q <= q + 1'b1;
else
q <= 4'b0000;
end
endmodule
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Blazor Hybrid适配到HarmonyOS系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
· 分享4款.NET开源、免费、实用的商城系统