目录
前言
3.2 Sequential logic
3.2.1 Latches and Flip-Flops
3.2.1.1 D flip-flop(Dff)
3.2.1.2 D flip-flop(Dff8)
3.2.1.3 DFF with reset(Dff8r)
3.2.1.4 DFF with reset value(Dff8p)
3.2.1.5 DFF with asynchronous reset(Dff8ar)
3.2.1.6 DFF with byte enable(Dff16e)
3.2.1.7 D Latch(Exams/m2014 q4a)
3.2.1.8 DFF(Exams/m2014 q4b)
3.2.1.9 DFF (Exams/m2014 q4c)
3.2.1.10 DFF+gate(Exams/m2014 q4d)
3.2.1.11 Mux and DFF(Mt2015 muxdff)
3.2.1.12 Mux and DFF(Exams/2014 q4a)
3.2.1.13 DFFs and gates(Exams/ece241 2014 q4)
3.2.1.14 Creat circuit from truth table(Exams/ece241 2013 q7)
3.2.1.15 Detect an edge(Edgedetect)
3.2.1.16 Detect both edge(Edgedetect2)
3.2.1.17 Edge capture register(Edgecapture)
3.2.1.18 Dual-edge triggered flip-flop(Dualedge)
结语
HDLbits网站链接
今天进入到时序电路部分了,这部分有很多设计技巧比如双沿采样电路等等,也是数字IC或者FPGA设计的核心内容,下面我们就开始吧。
module top_module (
input clk, // Clocks are used in sequential circuits
input d,
output reg q );//
always@(posedge clk)begin
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
module top_module (
input clk,
input [7:0] d,
output [7:0] q
);
always@(posedge clk)begin
q <= d;
end
endmodule
这相当于一个由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)begin
q <= 8'd0;
end
else begin
q <= d;
end
end
endmodule
这是一个带同步复位的D触发器。
module top_module (
input clk,
input reset,
input [7:0] d,
output [7:0] q
);
always@(negedge clk)begin
if(reset)begin
q <= 8'h34;
end
else begin
q <= d;
end
end
endmodule
这是将DFF复位为指定值的DFF。
module top_module (
input clk,
input areset, // active high asynchronous reset
input [7:0] d,
output [7:0] q
);
always@(posedge clk or posedge areset)begin
if(areset)begin
q <= 8'd0;
end
else begin
q <= d;
end
end
endmodule
这是一个带有异步复位的D触发器。
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 == 1'b0)begin
q <= 16'd0;
end
else begin
case(byteena)
2'b00:begin
q <= q;
end
2'b01:begin
q <= {q[15:8], d[7:0]};
end
2'b10:begin
q <= {d[15:8], q[7:0]};
end
2'b11:begin
q <= d;
end
endcase
end
end
endmodule
这是一个同步低电平复位,byteena是一个四选一选择器。
module top_module (
input d,
input ena,
output q);
always@(*)begin
if(ena == 1'b1)begin
q = d;
end
end
endmodule
对于组合逻辑,if没有补全else,case条件不完全,可能会产生latch,但是如果中间的信号有初值,那就不会产生latch。所以我们建议组合逻辑尽可能不要产生latch,latch对于时序危害很大。
module top_module (
input clk,
input d,
input ar, // asynchronous reset
output q);
always@(posedge clk, posedge ar)begin
if(ar)begin
q <= 1'b0;
end
else begin
q <= d;
end
end
endmodule
这是个异步高电平复位,大家注意,异步信号在always中连接可以用or或者逗号(,),通常大家习惯使用or。
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
这道题是同步高电平复位。
module top_module (
input clk,
input in,
output reg out);
always@(posedge clk)begin
out <= in ^ out;
end
endmodule
大家注意,always中的output必须定义为reg型。
module top_module (
input clk,
input L,
input r_in,
input q_in,
output reg Q);
always@(posedge clk)begin
if(L)begin
Q <= r_in;
end
else begin
Q <= q_in;
end
end
endmodule
module top_module (
input clk,
input w, R, E, L,
output Q
);
always@(posedge clk)begin
if(L)begin
Q <= R;
end
else begin
if(E)begin
Q <= w;
end
else begin
Q <= Q;
end
end
end
endmodule
这是一个带保持功能的D触发器。
module top_module (
input clk,
input x,
output z
);
reg [2:0] Q;
always@(posedge clk)begin
Q[0] <= Q[0] ^ x;
Q[1] <= ~Q[1] & x;
Q[2] <= ~Q[2] | x;
end
assign z = ~(| Q);
endmodule
module top_module (
input clk,
input j,
input k,
output Q);
always@(posedge clk)begin
case({j, k})
2'b00:begin
Q <= Q;
end
2'b01:begin
Q <= 1'b0;
end
2'b10:begin
Q <= 1'b1;
end
2'b11:begin
Q <= ~Q;
end
endcase
end
endmodule
这是一个JK触发器。
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg [7:0] in_reg;
always@(posedge clk)begin
in_reg <= in;
end
always@(posedge clk)begin
pedge <= in & ~in_reg;
end
/*
//second way
integer i;
always@(posedge clk)begin
for(i = 0; i <= 7; i = i + 1)begin
if(in[i] & ~in_reg[i])begin
pedge[i] = 1'b1;
end
else begin
pedge[i] = 1'b0;
end
end
end
*/
endmodule
这是一个上升沿检测电路,大家要认真对待这个问题,招聘经常会问到。
module top_module (
input clk,
input [7:0] in,
output [7:0] anyedge
);
reg [7:0] in_reg;
always@(posedge clk)begin
in_reg <= in;
end
always@(posedge clk)begin
anyedge = in ^ in_reg;
end
endmodule
这是一个双沿检测电路。
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] in_reg;
always@(posedge clk)begin
in_reg <= in;
end
always@(posedge clk)begin
if(reset)begin
out <= 32'd0;
end
else begin
out <= ~in & in_reg | out;
end
end
endmodule
这个题博主完全是根据时序图来做的,具体含义博主也不太明白。
module top_module (
input clk,
input d,
output q
);
reg q_d1;
reg q_d2;
always@(posedge clk)begin
q_d1 <= d ^ q_d2;
end
always@(negedge clk)begin
q_d2 <= d ^ q_d1;
end
assign q = q_d1 ^ q_d2;
endmodule
/*
//second way
always@(posedge clk)begin
q_d1 <= d;
end
always@(negedge clk)begin
q_d2 <= d;
end
assign q = clk ? q_d1 : q_d2;
*/
//endmodule
这道题是重点,大家注意,对于双沿检测,一定不能使用always@(posedge clk or negedge clk)begin这种方式,这种方式是不可综合的,应该用图中的方法一。但是对于第二种方法,虽然这道题是正确的,但是博主亲测在modelsim和vivado中仿真会产生毛刺,不建议大家用,对于这部分逻辑大家应该清楚。
今天更新的这部分内容是我们设计时序电路的基础,有一些题目是实际工程中常用的,比如边沿检测电路,对于双沿触发电路,博主虽然很少用,但是作为面试笔试题,是有很大可能出现的,希望大家能够掌握。最后如果答案有什么问题,欢迎大家指出来,我一定尽快改正。
https://hdlbits.01xz.net/wiki/Main_Page