扭环形计数器

一、原理

        约翰逊(Johnson)计数器又称扭环计数器,是一种用n位触发器(位宽)来表示2n个状态的计数器。它有一个非常明显地好处,相邻两组数只有一位不同,具体如下例子所示,因此在计数过程中不会存在竞争冒险问题。
        以4bit扭环形计数器为例,能表示8(2×4)种状态,相邻两组数之间,仅有1bit不同:
        0000 1000 1100 1110 1111 0111 0011 0001 0000 1000
        相邻的两个数据,高三位直接平移到第三位,最低位取反后平移到最高位。                                    例如 1100 → 1110 (110_0 → 1_110)key

二、代码

module johnson_counter#(parameter WIDTH = 4)(
    input clk,
    input rst_n,
    output reg [WIDTH-1:0] cnt
);
always@(posedge clk or negedge rst_n) 
    begin
    if(!rst_n)
      cnt <= { WIDTH { 1'b0 }};   //0000
    else
      cnt <= { ~cnt[0], cnt[WIDTH-1:1] }; //rst_n=1后,第一个上升沿 1_000
    end
endmodule

三、电路

从电路图可以看出,在时钟上升沿还没到前,把Q端的4bit数据分成两路处理,Q端数据的高三位(cnt[3:1])平移到低三位(cnt[2:0])。同时Q端数据的最低位(cnt[0])取反后平移到最高位(cnt[3]) 。最后操作完的数据  {cnt[3],cnt[2:0]} 就是D端的数据。

四、测试代码

`timescale 1ns / 1ps
module johnson_counter_tst #(parameter WIDTH = 4);
    reg clk;
    reg rst_n;
    wire [WIDTH-1:0] cnt;
 
johnson_counter U_johnson_counter(
    .clk(clk),
    .rst_n(rst_n),
    .cnt(cnt)
);
    initial
    begin
    clk=0;
    rst_n=0;
    #20;
    rst_n=1;
    end
always #10 clk=~clk;
endmodule

rst_n 拉高后且遇到上升沿才会变化,所以波形图的 20~30ns之间是不会变化的。cnt的位宽是4,cnt[3:0],使用扭环形计数器可以表示8种 cnt 状态,分别是0000 1000 1100 1110 1111 0111 0011 0001 0000 1000

### 环形计数器 Verilog 实现 环形计数器是一种特殊的移位寄存器型计数器,在每次时钟脉冲作用下,数据在各个触发器之间循环移动。与普通的环形计数器不同的是,环形计数器的数据流会在最后一个触发器处被反转再送回到第一个触发器。 #### 代码实现 下面是一个简单的8位环形计数器的Verilog模块: ```verilog module twist_ring_counter( input wire clk, input wire rst_n, output reg [7:0] q ); // 初始化状态向量 always @(posedge clk or negedge rst_n) begin : proc_q if (!rst_n) q <= 8'b0000_0001; else q <= {q[6:0], ~q[7]}; end endmodule ``` 此段代码定义了一个名为`twist_ring_counter`的模块,它接收两个输入信号——时钟(`clk`)和异步复位低电平有效(`rst_n`)以及一个输出信号表示当前的状态(`q`). 当接收到下降沿复位信号时,状态会被重置为初始值`8'b0000_0001`. 否则,在每一个上升沿到来的时候,新的状态由旧状态下除最高位外其他各位加上最高位取反后的结果构成[^2]. 为了验证上述环形计数器的功能正确性,可以编写如下测试平台(Testbench): ```verilog module tb_twist_ring_counter(); reg clk; reg rst_n; wire [7:0] out; // 被测单元实例化 twist_ring_counter uut ( .clk(clk), .rst_n(rst_n), .q(out) ); initial begin // 初始条件设置 clk = 0; rst_n = 0; // 复位释放并启动仿真 #10 rst_n = 1; #500 $stop; // 停止仿真的时间可以根据实际需求调整 end // 产生周期性的时钟波形 always #5 clk = !clk; // 可选:观察输出变化情况 initial begin $monitor("At time %t ps, the counter value is %b", $time, out); end endmodule ``` 这段测试程序创建了一个名为`tb_twist_ring_counter`的模块来模拟环境中的激励源,并通过调用之前编写的环形计数器模块来进行功能验证。这里设置了基本的时间控制语句用于生成时钟信号和初始化序列;还加入了监控命令以便于查看每一次更新后计数值的变化状况.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值