文章目录
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