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设计
文章图片

Verilog专题(三十六)多功能Timer设计
文章图片


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设计】根据题目的要求,先列出状态转移图,然后就可以进行设计了。
Verilog专题(三十六)多功能Timer设计
文章图片

module top_module (input clk,input reset,// Synchronous resetinput 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@(*)begincase(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; endcaseend//statealways@(posedge clk)beginif(reset)state <= IDLE; elsestate <= next_state; end//shiftalways@(posedge clk)beginif(reset)shift <= 0; else if(shift_ena)shift <= {shift[2:0], data}; end//counteralways@(posedge clk)beginif(reset)counter <= 0; elsecase(state)COUNT:counter <= counter + 1; default:counter <= 0; endcaseendassign done_counting = (counter == (shift + 1) * 1000 - 1); assign count = shift - counter / 1000; assign counting = state == COUNT; assign done = state == WAIT; endmodule


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



    推荐阅读