Verilog专题(三十六)多功能Timer设计

HDLBits网址:https://hdlbits.01xz.net/wiki/Main_Page

 

    本题是一组系列题(5题)的最后一题,从移位器、计数器、序列检测器、状态机到最后多功能Timer设计,前面的题目比较简单,所以这一系列的题目就只放最后一题。

 

题目

    创建一个计时器:①当检测到特定模式(1101)时启动;②再移4位以确定延迟时间;③等待计数器完成计数,然后通知用户并等待用户确认计时器。

    当接收到模式1101时,状态机必须在4个时钟周期内断言输出shift_ena。此后,状态机声明其计数输出以指示其正在等待计数器,并等待直到输入done_counting为高。

    串行数据在数据输入引脚上可用。当接收到模式1101时,电路必须随后移入接下来的4位,即最高有效位在前。这4位确定定时器延迟的持续时间。将其称为delay [3:0]。

    此后,状态机声明其计数输出以指示其正在计数。状态机必须精确计数(delay [3:0] + 1)* 1000个时钟周期。例如,delay = 0表示计数1000个周期,而delay = 5表示计数6000个周期。同时输出当前剩余时间。这应该等于1000个周期的延迟,然后等于1000个周期的delay-1,依此类推,直到1000个周期为0。当电路不计数时,count [3:0]输出无关紧要。

    此时,电路必须断言完成,以通知用户计时器已超时,并等待直到输入ack为1才复位,以查找下一次出现的启动序列(1101)。电路应重置为开始搜索输入序列1101的状态。

    这是预期输入和输出的示例。“ x”状态可能会使阅读有些混乱,它们表明FSM在该周期中不应关心该特定输入信号。例如,一旦读取了1101和delay [3:0],电路将不再查看数据输入,直到在完成所有其他操作后恢复搜索为止。在此示例中,电路的计数为2000个时钟周期,因为delay [3:0]值为4'b0001。最后几个周期以delay [3:0] = 4'b1110开始另一个计数,该计数将计数15000个周期。

Verilog专题(三十六)多功能Timer设计_第1张图片

Verilog专题(三十六)多功能Timer设计_第2张图片

 

Module Declaration

module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output [3:0] count,
    output counting,
    output done,
    input ack );

 

我的设计

    根据题目的要求,先列出状态转移图,然后就可以进行设计了。

Verilog专题(三十六)多功能Timer设计_第3张图片

module top_module (    input clk,    input reset,      // Synchronous reset    input data,    output [3:0] count,    output counting,    output done,    input ack );    parameter IDLE = 0, S1 = 1, S2 = 2, S3 = 3, B0 = 4, B1 = 5, B2 = 6, B3 = 7, COUNT = 8, WAIT = 9;        reg[3:0] state, next_state;    reg[3:0] shift;    reg[13:0] counter;    wire done_counting;    wire shift_ena;        assign shift_ena = (state == B0 || state == B1 || state == B2 || state == B3);        always@(*)begin        case(state)            IDLE:next_state=data?S1:IDLE;            S1:next_state=data?S2:IDLE;            S2:next_state=data?S2:S3;            S3:next_state=data?B0:IDLE;            B0:next_state=B1;            B1:next_state=B2;            B2:next_state=B3;            B3:next_state=COUNT;            COUNT:next_state=done_counting?WAIT:COUNT;            WAIT:next_state=ack?IDLE:WAIT;        endcase    end        //state    always@(posedge clk)begin        if(reset)            state <= IDLE;        else            state <= next_state;    end        //shift    always@(posedge clk)begin        if(reset)            shift <= 0;        else if(shift_ena)            shift <= {shift[2:0], data};                end        //counter    always@(posedge clk)begin        if(reset)            counter <= 0;        else            case(state)                COUNT:counter <= counter + 1;                default:counter <= 0;            endcase    end              assign done_counting = (counter == (shift + 1) * 1000 - 1);    assign count = shift - counter / 1000;    assign counting = state == COUNT;    assign done = state == WAIT;    endmodule

 

微信公众号

     建立了一个微信公众号“Andy的ICer之路”,此公众号主要分享数字IC相关的学习经验,做公众号的目的就是记录自己的学习过程,很多东西回过头来可能就忘记了,为了记住知识和分享知识,希望自己可以保持更新,有兴趣的朋友可以关注一下!

 

 

你可能感兴趣的:(HDLBits_Verilog)