目录
Ⅰ. 实践说明
0x00 计数器(Counter)
0x01 异步计数器(Asynchronous Counter)
0x02 同步计数器(Synchronous Counter)
Ⅱ. 实践:2位二进制计数器
0x00 实践说明
0x01 输出表
0x02 代码和仿真
Ⅲ. 实践:四位十进制计数器
0x00 实践说明
0x01 输出表
0x02 代码和仿真
Ⅰ. 实践说明
0x00 计数器(Counter)
计数器是一种状态周期性循环的顺序电路 (sequential circuit)。计数器接收一个时钟值 (high / low) 和一个要计数的输入值,输出结果是接收到输入的次数,并使用触发器对输入的累积次数进行计数。
计数器根据其工作方式分为 同步 (Synchronous) 和 异步 (Asynchronous) 两种,最简单的计数器形式是 上/下 计数器 (UP/DOWN)。
Up/Down Counter |
上/下计数器接受单个 "上 "或 "下 "输入,并根据该输入将计数器的当前值递增或递减 1。
- UP=1 时顺时针计数,DOWN=1 时逆时针计数。
- U=D=0 时停止计数,不接受 U=D=1 的输入。
0x01 异步计数器(Asynchronous Counter)
异步计数器 (Asynchronous Counter) 又称纹波计数器,由多个串联的触发器组成。
第一个 flip-flop 接收时钟值作为输入,随后的 flip-flop 接收前一个 flip-flop 的输出作为输入。
Asynchronous Counter |
0x02 同步计数器(Synchronous Counter)
在异步计数器中,由于触发器是串联连接的,上一个触发器的输出被传递到下一个触发器的输入端,而不是所有触发器的输出同时发生。
由于这种结构,运算过程存在延迟,因此在需要精确时间尺度运算的电路中很难使用异步计数器。
同步计数器是对异步计数器上述问题的一种补充。为防止出现延迟,通过将时钟连接到每个触发器,触发器被并行连接起来。
由于触发器是并联的,因此可以同时工作,适合高速运行,但缺点是电路结构复杂。
Synchronous Counter |
Ⅱ. 实践:2位二进制计数器
0x00 实践说明
Verilog 实现带复位操作的 2 位二进制计数器,根据 A 的状态图创建状态表 B。
0x01 输出表
Present State Q | Next State Q* | |
input x = 0 | input x = 1 | |
00 | 00 | 01 |
01 | 01 | 10 |
10 | 10 | 11 |
11 | 11 | 00 |
0x02 代码和仿真
💬 Source Code:
`timescale 1ns / 1ps
module BC(
input reset,
input clk,
input x,
output z,
output[1:0] out
);
reg [1:0]out;
reg z;
always @(posedge !clk) begin
if(reset) begin
out[0] <= 1'b0;
out[1] <= 1'b0;
z <= 1'b0;
end
else begin
if((x == 1'b1)) begin
if((out[0] && out[1])) z <= 1'b1;
if((out[0] == 1'b1)) begin
out[0] <= (~out[0]);
out[1] <= (~out[1]);
end
else out[0] <= (~out[0]);
end
end
end
endmodule
💬 Testbench:
`timescale 1ns / 1ps
module BC_tb;
reg clk,reset,x;
wire [1:0]out,z;
BC u_BC(
.clk(clk ),
.reset(reset ),
.x(x ),
.out(out ),
.z(z )
);
initial clk = 1'b0;
initial reset = 1'b1;
initial x = 1'b0;
always clk = #20 ~clk;
always@(reset) begin
reset = #50 ~reset;
end
always@(x) begin
x = #110 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
end
initial begin
#380
$finish;
end
endmodule
🚩 运行结果如下:
💡 解读:2 位二进制计数器是一个在数字 0,1,2,3 上迭代的计数器,这些数字可以用 2 位来表示。您可以编写这样的代码:当输入值 x 为 0 时,计数器保持当前状态;当输入值 x 为 1 时,计数器进入下一个数字。在数到 3(11)后,我们需要处理返回 0(00)。我们将其编写为下降沿触发器,模拟结果表明,每当时钟值从 1 下降到 0 时,输入值 x 就会反映到输出上,计数就会顺利进行。
Ⅲ. 实践:4位十进制计数器
0x00 实践说明
Verilog 实现带复位操作的 4 位十进制计数器,创建状态图和状态表,验证 Verilog 的仿真结果。
通过 FPGA 验证行为。
0x01 输出表
Present State Q | Next State Q* | |
input x=0 | input x=1 | |
0000 | 0000 | 0001 |
0001 | 0001 | 0010 |
0010 | 0010 | 0011 |
0011 | 0011 | 0100 |
0100 | 0100 | 0101 |
0101 | 0101 | 0110 |
0110 | 0110 | 0111 |
0111 | 0111 | 1000 |
1000 | 1000 | 1001 |
1001 | 1001 | 0000 |
0x02 代码和仿真
💬 Source Code:
`timescale 1ns / 1ps
module DC(
input reset,
input clk,
input x,
output z,
output [3:0]out
);
reg [3:0]out;
reg z;
always @(posedge !clk) begin
if(reset) begin
out[0] = 1'b0;
out[1] = 1'b0;
out[2] = 1'b0;
out[3] = 1'b0;
z = 1'b0;
end
else begin
if((x == 1'b1)) begin
if((out[0] == 1'b1)) begin
out[0] = (~out[0]);
out[1] = (~out[1]);
end
else out[0] = (~out[0]);
if((~out[0]) && (~out[1]) && (~out[2])) out[2] = 1'b1;
else if ((~out[0]) && (~out[1]) && out[2]) begin
out[2] = 1'b0;
out[3] = 1'b1;
end
if((out[3] && (~out[2]) && out[1] && (~out[0]))) begin
z = 1'b1;
out[0] = 1'b0;
out[1] = 1'b0;
out[2] = 1'b0;
out[3] = 1'b0;
end
end
end
end
endmodule
💬 Testbench:
`timescale 1ns / 1ps
module DC_tb;
reg clk,reset,x;
wire [3:0]out,z;
DC u_DC(
.clk(clk ),
.reset(reset ),
.x(x ),
.out(out ),
.z(z )
);
initial clk = 1'b0;
initial reset = 1'b1;
initial x = 1'b0;
always clk = #20 ~clk;
always@(reset) begin
reset = #50 ~reset;
end
always@(x) begin
x = #110 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
x = #60 ~x;
x = #20 ~x;
end
initial begin
#860
$finish;
end
endmodule
🚩 运行结果如下:
💡 解读:4 位十进制计数器是一种对 0 到 9 的数字进行迭代的计数器,可以用 4 位来表示。您可以编写这样的代码:当输入值 x 为 0 时,计数器保持当前状态;
当输入值 x 为 1 时,计数器进入下一个数字。一旦数到 9(1001),就应该进行处理,以便返回到 0(0000)。我们将其编写为下降沿触发器,模拟结果表明,每当时钟值从 1 下降到 0 时,x 的输入值就会反映在输出中,计数也就顺利进行了。
📌 [ 笔者 ] 王亦优
📃 [ 更新 ] 2023.11.11
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,
本人也很想知道这些错误,恳望读者批评指正!
📜 参考资料 Introduction to Logic and Computer Design, Alan Marcovitz, McGrawHill, 2008 Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. . 百度百科[EB/OL]. []. https://baike.baidu.com/. |