对称型计数器Verilog代码学习(三段式状态机写法)

对称型计数器Verilog代码学习(三段式状态机写法)

symme_timer.v

代码如下:

// Create Date: 2024/04/14
// Module Name: symme_timer.v

module symme_timer(
                clk      ,
                rst_n    ,
                en       ,
                cfg_max  ,
                cnt        //这样写端口方便例化操作
);
input           clk;
input           rst_n;
input           en;
input  [31:0]   cfg_max;
output [31:0]   cnt;
reg    [31:0]   cnt;

//-----------------状态机局部参数的定义----------------------
localparam   IDLE  =  2'd0;
localparam   INC   =  2'd1;
localparam   DEC   =  2'd2;

//----------------------------------------------------------
reg    [1:0]    state;
reg    [1:0]    state_next;
wire            max_pre_vld;
wire            one_vld;
wire   [31:0]   cfg_max_limit;

//----------------------------------------------------------
assign cfg_max_limit = (cfg_max == 32'd0) ? 32'd1 : cfg_max;
assign max_pre_vld = (cnt == cfg_max_limit - 32'd1);  //注意看波形的变化
assign one_vld = (cnt == 32'd1);

//----------------------------------------------------------
//first segment:state transfer
always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
        state <= IDLE;
    else
        state <= state_next;
end

//----------------------------------------------------------
//second segment:state transfer condition
always @ (*)
begin
    case (state)
        IDLE:
        begin
            if(en)
                state_next = INC;
            else
                state_next = IDLE;
        end

        INC:
        begin
            if(~en)
                state_next = IDLE;
            else if (max_pre_vld)
                state_next = DEC;
            else
                state_next = INC;
        end

        DEC:
        begin
            if(~en)
                state_next = IDLE;
            else if (one_vld)
                state_next = INC;
            else
                state_next = DEC;
        end

        default: state_next = IDLE;
    endcase
end

//-------------------------------------------------------------
//third segment:state output
always @ (posedge clk or negedge rst_n)
begin
    if (!rst_n)
        cnt <= 32'd0;
    else
        case(state)
            IDLE: cnt <= 32'd0;
            INC:  cnt <= cnt + 32'd1;
            DEC:  cnt <= cnt - 32'd1;
        endcase
end

endmodule

symme_timer_tb.v

代码如下:

// Create Date: 2024/04/14
// Module Name: symme_timer_tb.v

module symme_timer_tb;

logic             clk          ;
logic             rstn         ;    //绿皮书:logic类型只能有一个驱动
reg               en           ;

initial
begin
	$fsdbDumpfile("tb.fsdb");
	$fsdbDumpvars(0);
end

initial
begin
    clk = 1'b0;
    forever
    begin
        #(1e9/(2.0*40e6))  clk = ~clk;  //时间单位为ns,时钟频率为40MHz
    end
end

initial
begin
    rstn = 0;
    #30 rstn = 1;  //仿真开始时刻复位信号为0,30ns过后,复位信号为1
end

initial
begin
    en = 0;

    @(posedge rstn);
    #100;
    @(posedge clk);
    #1;
    en = 1;    //使能信号是在时钟上升沿1n后,从0变为1

    #1000;
    @(posedge clk);
    #1;
    en = 0;   //使能信号是在时钟上升沿1n后,从1变为0

    #100;
    $finish;
end

symme_timer  symme_timer_u1(
               .clk    (clk   ),
               .rst_n  (rstn  ),
               .en     (en    ),
               .cfg_max(5     ),   //例化时可以将端口信号直接赋值?
               .cnt    (      )    //例化时不使用的端口可以悬空
);

endmodule

波形图

在这里插入图片描述
要重点关注标记M1、M2、M3、M4点,clk、en、state、cnt的变化情况!!!

ps:源代码来自《数字IC设计入门》白栎旸◎编著

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值