verilog 5:JK触发器设计简易功能16位加法脉动计数器

本文详细描述了使用下降沿敏感JK触发器设计并实现了一个16位异步计数器,包括计数器代码实现、testbench测试以及模拟仿真过程。作者展示了如何通过全加器模块处理初始值和计数操作,以及在测试中对计数器功能进行了验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

本文主要介绍使用下降沿敏感JK触发器设计一个16位脉动计数器。该设计使用了16个JK触发器,该计数器为异步计数器,并且该计数器可以进行异步复位,可以自行设定初始值进行计数。在初始值基础上进行计数的操作由一个16位全加器模块完成。

一. 异步计数器

异步二进制计数器的工作原理和结构均较简单,但各触发器不是在同一时钟沿作用下同时翻转,而是逐级脉动翻转实现计数进位的,故也称之为纹波计数器

二. 实现代码

1.计数器代码

// +FHDR----------------------------------------------------------------------------
//            
//                
// ---------------------------------------------------------------------------------
// Filename      : ripple_carry_counter.v
// Author        : xibei
// Created On    : 2024-03-08 22:00
// Last Modified : 2024-03-12 23:30
// ---------------------------------------------------------------------------------
// Description   : 下降沿敏感JK触发器实现异步复位16位脉动计数器,可以自定义初始值,在计数值不溢出情况下
//                 J=1,K=1时进行计数,当aerset=1时进行复位,当有使能信号set_enable=1时,可自行
//                 行设定初始值,初始值由输入端set_num进行设置,通过初始值于计数值相加的方法,
//                 该过程由一个16位全加器组成。
// -FHDR----------------------------------------------------------------------------
module ripple_carry_counter(
    output [15:0] Q,
    input   set_enable, 
    input  [15:0] set_num,
    input   J,
    input   K,
    input clk,
    input areset
);
    wire [15:0] j;
    wire [15:0] k;
    wire cin,cout; 
    wire [15:0] q;
    reg [15:0] Q_all;
    wire [15:0] sum_all;
    assign cin = 1'b0;

    assign j[15:0] = {16{J}};
    assign k[15:0] = {16{K}};
    
    adder in(.sum(sum_all),.a(set_num),.b(q),.cin(cin),.cout()); //全加器模块例化,没用输出可以悬空
    //genvar-for实现16个JK触发器模块例化
    generate
        genvar i;
        for (i=0;i<16;i=i+1) begin:JK
            if(i==0) begin
                JK_FF jkff_in (.q(q[0]),.J(j[0]),.K(k[0]),.clk(clk),.areset(areset));
            end
            else begin
                JK_FF jkff_in (.q(q[i]),.J(j[i]),.K(k[i]),.clk(q[i-1]),.areset(areset));
            end
        end
    endgenerate

    always @(negedge clk or posedge areset) begin
        if(areset)                  Q_all<=16'h0;
        else if(set_enable==1)      Q_all<=sum_all;
        else                        Q_all<=q;
    end

    assign Q=Q_all;
endmodule
// JK触发器模块
module JK_FF(
        output  reg q,
        input   clk,
        input   areset,
        input   J,
        input   K
        );
        always @(negedge clk or posedge areset) begin
            if(areset)           q<=1'b0;
            else                 q<=(J&~q) | (~K&q);
        end
endmodule
//全加器模块
module adder( 
    input [15:0] a, b,
    input cin, 
    output cout,
    output [15:0] sum );

    assign {cout,sum}= a+b+cin;

endmodule

2.testbench(激励文件)

// +FHDR----------------------------------------------------------------------------
//            
//                
// ---------------------------------------------------------------------------------
// Filename      : ripple_carry_counter_tb.v
// Author        : xibei
// Created On    : 2024-03-09 15:00
// Last Modified : 2024-03-09 17:30
// ---------------------------------------------------------------------------------
// Description   : testbench文件  
//                 设定J=1,K=1,set_enable=1,set_num=16'h000A
//                 测试从10开始计数,55ns后进行计数,955ns复位
// -FHDR----------------------------------------------------------------------------
`timescale 1ns/1ps
module ripple_carry_counter_tb;
reg clk;
reg areset;
reg J,K;
reg [15:0] set_num;
reg set_enable;
wire [15:0] Q;

ripple_carry_counter tb(.Q(Q),.clk(clk),.areset(areset),.J(J),.K(K),.set_enable(set_enable),.set_num(set_num));
initial clk=1'b0;
always begin
    #5 clk=~clk;
end

initial  areset=1'b1;
initial begin
    #55  areset=1'b0;
    #900 areset=1'b1;
    #10  areset=1'b0;
    #50  $finish;
end

initial begin
    J=1'b1;K=1'b1; 
end

initial begin
    set_enable=1'b1;
    #965 set_enable=1'b0;
end
initial begin
    set_num=16'h000A;
end
initial begin
    $monitor($time, " Q= %d",Q[15:0]);
end
/*
initial begin
    $dumpfile("ripple_carry_counter_tb.vcd");
    $dumpvars(0,ripple_carry_counter_tb);
end
*/ 
//使用iverilog和Gtkwave需要添加

endmodule

三. 模拟仿真

1.RTL view

rtl

2.波形图

wave

四 .总结

本文只介绍了简单加法异步计数器,额外置位功能大概率不太完善,可能会有bug,本人水平有限只能进行简单实现,本来还想添加加法减法模式切换功能但没有找到简单切入点,只能暂时实现这些简单功能。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值