【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现_第1张图片

目录

Ⅰ. 实践说明

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

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现_第2张图片

上/下计数器接受单个 "上 "或 "下 "输入,并根据该输入将计数器的当前值递增或递减 1。

  • UP=1 时顺时针计数,DOWN=1 时逆时针计数。
  • U=D=0 时停止计数,不接受 U=D=1 的输入。

0x01 异步计数器(Asynchronous Counter)

异步计数器 (Asynchronous Counter) 又称纹波计数器,由多个串联的触发器组成。

第一个 flip-flop 接收时钟值作为输入,随后的 flip-flop 接收前一个 flip-flop 的输出作为输入。

Asynchronous Counter

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现_第3张图片

0x02 同步计数器(Synchronous Counter)

在异步计数器中,由于触发器是串联连接的,上一个触发器的输出被传递到下一个触发器的输入端,而不是所有触发器的输出同时发生。

由于这种结构,运算过程存在延迟,因此在需要精确时间尺度运算的电路中很难使用异步计数器。

同步计数器是对异步计数器上述问题的一种补充。为防止出现延迟,通过将时钟连接到每个触发器,触发器被并行连接起来。

由于触发器是并联的,因此可以同时工作,适合高速运行,但缺点是电路结构复杂。

Synchronous Counter

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现_第4张图片

Ⅱ. 实践:2位二进制计数器

0x00 实践说明

Verilog 实现带复位操作的 2 位二进制计数器,根据 A 的状态图创建状态表 B。

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现_第5张图片

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

运行结果如下:

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现_第6张图片

解读: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

运行结果如下:

【FPGA】Verilog:计数器 | 异步计数器 | 同步计数器 | 2位二进制计数器的实现 | 4位十进制计数器的实现_第7张图片

解读: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/.

你可能感兴趣的:(fpga开发,计数器,2位二进制计数器,四位十进制计数器)