1.普通计数器 1. 用verilog实现一个4bit二进制计数器。
a) 异步复位
b) 同步复位
module count_2( input clk, input rst_n, output reg [3:0] o_cnt ) always @ (posedge clk or negedge rst_n) begin //异步复位 if(!rst_n) begin o_cnt <= 4‘b0000; end else if(o_cnt == 4‘b1111) begin o_cnt <= 4‘b0000; end else begin o_cnt <= o_cnt + 4‘b0001; end end /* always @ (posedge clk) begin //同步复位 if(!rst_n) begin o_cnt <= 4‘b0000; end else if(o_cnt == 4‘b1111) begin o_cnt <= 4‘b0000; end else begin o_cnt <= o_cnt + 4‘b0001; end end */ endmodule
module count_tb( ); reg clk, rst_n; wire [3:0] o_cnt; //generate system clock with the period == 2ns; always begin #1 clk = ~clk; end initial begin clk = 0; end //initialization initial begin rst_n = 0; #4 rst_n = 1; #32 rst_n = 0; #4 rst_n = 1; end //Instantiation count_2 u0( .clk(clk), .rst_n(rst_n), .o_cnt(o_cnt) ); endmodule
2.
用verilog实现4bit约翰逊(Johnson)计数器。
约翰逊(Johnson)计数器又称扭环计数器,是一种用n位触发器来表示2n个状态的计数器。它与环形计数器不同,后者用n位触发器仅可表示n个状态。2进制计数器(n为触发器的个数)有2^n个状态。若以四位二进制计数器为例,它可表示16个状态。但由于8421码每组代码之间可能有二位或二位以上的二进制代码发生改变,这在计数器中特别是异步计数器中就有可能产生错误的译码信号,从而造成永久性的错误。而约翰逊计数器的状态表中,相邻两组代码只可能有一位二进制代码不同,故在计数过程中不会产生错误的译码信号。鉴于上述优点,约翰逊计数器在同步计数器中应用比较广泛。
代码实现:
module johnson_counter( clk, rst_n, out ); input clk; input rst_n; output [3:0]out; reg [3:0]counter; always@(posedge clk or negedge rst_n) if(!rst_n) counter<=4‘b0; else if(counter[0]==0) counter<={1‘b1,counter[3:1]}; else counter<={1‘b0,counter[3:1]}; assign out=counter; endmodule
tb:
`timescale 1ns/1ps module johnson_counter_tb; reg clk; reg rst_n; wire [3:0]out; johnson_counter johnson_counter( .clk(clk), .rst_n(rst_n), .out(out) ); initial clk=0; always #10 clk=~clk; initial begin rst_n=0; #21; rst_n=1; end endmodule
仿真:
可以看到相邻状态间的切换只有一位变化。
3.用verilog实现4bit环形计数器:复位有效时输出0001,复位释放后依次输出0010,0100,1000,0001,0010...
代码实现:
module circle_counter( clk, rst_n, out ); input clk; input rst_n; output [3:0]out; reg [3:0]counter; always@(posedge clk or negedge rst_n) if(!rst_n) counter<=4‘b0001; else counter<={counter[2:0],counter[3]}; assign out=counter; endmodule
tb:
`timescale 1ns/1ps module circle_counter_tb; reg clk; reg rst_n; wire [3:0]out; circle_counter circle_counter( .clk(clk), .rst_n(rst_n), .out(out) ); initial clk=0; always #10 clk=~clk; initial begin rst_n=0; #21; rst_n=1; end endmodule
4.总结一下这三种计数器的特点。
假设都是N位的计数器,二进制计数器有2^N个状态,Johnson计数器由2N个状态,而环形计数器由N个状态;
相对于二进制计数器,Johnson计数器相邻两组代码只可能有一位二进制代码不同,环形计数器有两位二进制代码不同。
原文:https://www.cnblogs.com/ajiaoa/p/12772706.html