HDLBits Exams/review2015 fancytimer

1.原题复现

Exams/review2015 fancytimer

HDLBits Exams/review2015 fancytimer_第1张图片

2.思路以及代码

历时2个小时,终于把这道题给弄得差不多了,但是还是有一些细节没弄明白,特此记录一下。
根据题意得要求 可以大概划分为以下几个电路:
1.序列检测模块
2.移位断定延迟时间模块
3.计数器模块
4.检测ack模块

如果刷过HDLBits 就可以知道这道题得前面几道题,其实对应的就是这几个小模块电路

因此,参考前面几个模块电路,可以给出如下代码:
其中S1,S11,S110状态是处于序列检测,
B0,B1,B2,B3是处于4个时钟周期内用来断定延迟时间的状态
最后Counting处于计数阶段
Waiting处于等待检测ack状态。

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

    reg  cout_finish;//计数到0的完成标志

    reg [3:0]state,next_state;//
    
    parameter IDLE=0,S1=1,S11=2,S110=3,B0=4,B1=5,B2=6,B3=7,Counting=8,Waiting=9; //
    always@(*)begin
        case(state)
            	IDLE:	next_state = data?S1:IDLE;
                S1:		next_state = data?S11:IDLE;
                S11:	next_state = data?S11:S110;
                S110:	next_state = data?B0:IDLE;
                B0:		next_state = B1;
                B1:		next_state = B2;
                B2:		next_state = B3;
                B3:		next_state = Counting;
                Counting:next_state = cout_finish?Waiting:Counting;
                Waiting:next_state = ack?IDLE:Waiting;
        endcase
    end
    
    always@(posedge clk)begin  ;//
        if(reset)begin
           state<=IDLE; 
        end
        else begin
           state<=next_state; ;//
        end
    end
    
    
      reg  shift_ena;
    assign shift_ena = (state== B0) || (state== B1) ||( state== B2) ||(state== B3);//
        reg [3:0]q;//shift_register
    //移位模块
    always@(posedge clk )begin
        if (reset)begin
            q<=0;
        end
        //相当于移位模块
        else if(shift_ena)begin
            q<={q[2:0],data};
        end
        //相当于down counter 模块 
        else if (cout_1k == 999 ) begin//为什么不能把当q==0的情况与上cout_1k计数到1000时候,使得cout_finish拉高为1 写到if语句里面?
                q<=q-1;
        end
            else  begin
               q<= q; 
            end 
    end
    
    reg [15:0]cout_1k;//计数1000
    reg cout_1k_finish;//1k的标志
    
    //计数1000电路
    always@(posedge clk)begin
         if(state == Counting)begin
            if(cout_1k<999)begin
               cout_1k<=cout_1k+1; 
            end
            else if(cout_1k == 999 ) begin
               cout_1k<=0; 
            end
        end
        else begin
           cout_1k<=0; 
        end
    end
    
    assign cout_finish = (cout_1k == 999)&& (q==0);//把这句放到时序电路if语句里面为什么就不行。/
    assign count = q;
    assign counting = (state == Counting);
    assign done = (state==Waiting);
endmodule

该代码的问题在于:刚开始修改代码的时候,是把cout_finish放在时序电路里面来实现的,但是发现这样做会一直仿真失败,后来将该变量从时序电路里面拿出来,利用assign语句来写,就能够仿真成功。 这是为什么呢?

参考博客:HDLbits参考Exams/review2015 fsm和Exams/review2015 fancytimer

你可能感兴趣的:(HDL专栏,fpga开发)