Exams/review2015 fancytimer

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

    parameter s0=3'd0,s1=3'd1,s2=3'd2,s3=3'd3,s4=3'd4,s_count=3'd5,s_done=3'd6;
    reg [2:0] n_s,s;
    reg [1:0] cnt;
    reg [3:0] reg_count;

    reg [15:0] delay,cnt1;
    
    always@(*) begin
        case(s)
            s0:n_s=data?s1:s0;
            s1:n_s=data?s2:s0;
            s2:n_s=data?s2:s3;
            s3:n_s=data?s4:s0;
            s4:n_s=(cnt==3'd3)?s_count:s4;    
            s_count:n_s=(cnt1==delay-1)?s_done:s_count;  
            s_done:n_s=ack?s0:s_done;
          
        endcase
    end
    
    always@(posedge clk) begin
        if(reset)
            s<=s0;
        else
            s<=n_s;
    end
    
    //shift_cnt_block
    always@(posedge clk) begin
        if(reset)
            cnt<=0;
        else if(s==s4) begin
            if(cnt<3'd3)
                cnt<=cnt+1;
            else
                cnt<=0;
        end  
    end

    //shift_block
    always@(posedge clk) begin
        if(s==s4)
            reg_count<={reg_count[2:0],data};
       
        else
            reg_count<=reg_count;
        
    end
    
    //delay_counting_block
    always@(*) begin
        if(s==s_count)
            delay=(reg_count+1'd1)*10'd1000;
        else
            delay=0;
    end
    
    //cnt1_counting_block
    always@(posedge clk) begin
        if(reset)
            cnt1<=0;
        else if(s==s_count)
            cnt1<=cnt1+1;
        else
            cnt1<=0;
    end
    
    assign counting=(s==s_count);
    assign done=(s==s_done);
	assign count = reg_count - cnt1/1000;    //cnt1每1000个周期后count递减
endmodule

相比上一题,本题增加了实际的计数逻辑以取代输入信号 done_counting,但状态以及转移关系与上一题相同。

设计 dly_val [3:0] ,在 shft_ena 移位使能的情况下,从数据流中读取 4bit 延迟值。

计数逻辑为一个周期为 1000 的计数器,当计数器输出 16’d999 时,将 dly_val 减 1。

功能是不是听上去很熟悉,没错,我们可以分别使用之前实现的 移位寄存器 以及 周期为 1000 的计数器。并在相应状态产生使能信号控制这两个下层模块。

module shft_reg_cntr (
    input clk,
    input shift_ena,
    input count_ena,
    input data,
    output reg [3:0] q);

    always @(posedge clk ) begin
        if(shift_ena)
            q   <=  {q[2:0],data};
        else if(count_ena) begin
            q   <=  q - 4'd1;
        end  
    end
endmodule

module cntr_1k (
    input clk,
    input reset,
    output reg [9:0] q);

    always @(posedge clk ) begin
        if(reset | q == 10'd999)
            q   <=  10'd0;
        else begin
            q   <=  q + 10'd1;
        end  
    end
endmodule

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

    localparam FSM_W  = 8;
    localparam FSM_W1 = FSM_W - 1'b1;

    reg [FSM_W1:0]   state;
    reg [FSM_W1:0]   nxt_state;

    localparam  IDLE        = 0;
    localparam  S_0         = 1;
    localparam  S_1         = 2;
    localparam  S_11        = 3;
    localparam  S_110       = 4;
    localparam  S_SHFT_ENA  = 5;
    localparam  WAT_CNT_FIN = 6;
    localparam  WAT_ACK     = 7;

    wire            done_counting;

    //assert signal cntr
    reg [1:0]       asrt_cntr;
    wire            asrt_cntr_add;  
    wire            asrt_cntr_clr;  

    //delay val
    wire[3:0]       dly_val;

    wire            dly_val_shft_ena;
    wire            dly_val_dec;

    //delay cntr
    wire [9:0]      dly_cntr;
    wire            dly_cntr_ena;

    //assert signal cntr
    always @(posedge clk) begin
        if(reset) begin
            asrt_cntr              <= 'b0;
        end else if(asrt_cntr_add)begin
            asrt_cntr              <= asrt_cntr + 1'b1;
        end else if(asrt_cntr_clr)begin
            asrt_cntr              <= 'b0;
        end
    end
    assign                  asrt_cntr_add  = state[S_SHFT_ENA];
    assign                  asrt_cntr_clr  = 1'b0; // cntr clear itself

    //delay cntr
    cntr_1k U_cntr_1k(
        .clk        (clk),
        .reset      (~dly_cntr_ena),
        .q          (dly_cntr)
    );
    assign                  dly_cntr_ena  = state[WAT_CNT_FIN   ];

    //delay val
    shft_reg_cntr U_shft_reg_cntr
    (
        .clk        (clk),
        .shift_ena  (dly_val_shft_ena),
        .count_ena  (dly_val_dec),
        .data       (data),
        .q          (dly_val)
    );
    assign                  dly_val_shft_ena    =   state[S_SHFT_ENA ];
    assign                  dly_val_dec         =   (dly_cntr == 16'd999 ) && ~(dly_val == 4'd0);

    assign                  done_counting       =   dly_cntr == 16'd999 && dly_val == 4'd0;

    // State transition logic (combinational)
    always @(*) begin
        nxt_state[IDLE   ]          =   1'b0; // never reach for nxt_state
        nxt_state[S_0    ]          =   (state[IDLE   ] && ~data) || (state[S_1    ] && ~data) || (state[S_0    ] && ~data) 
                            || (state[S_110   ] && ~data) || (state[WAT_ACK       ] && ack);
        nxt_state[S_1    ]          =   (state[IDLE   ] &&  data) || (state[S_0    ] &&  data);
        nxt_state[S_11   ]          =   (state[S_1    ] &&  data) || (state[S_11   ] &&  data);
        nxt_state[S_110  ]          =   (state[S_11   ] && ~data);
        nxt_state[S_SHFT_ENA ]      =   (state[S_110  ] &&  data) || (state[S_SHFT_ENA  ] && ~(asrt_cntr == 2'd3));

        nxt_state[WAT_CNT_FIN   ]   =   (state[S_SHFT_ENA] && asrt_cntr == 2'd3)
                                    || (state[WAT_CNT_FIN   ] && ~done_counting);

        nxt_state[WAT_ACK       ]   =   (state[WAT_CNT_FIN   ] && done_counting) 
                                    || (state[WAT_ACK       ] && ~ack);
    end

    // State flip-flops (sequential)
    always @(posedge clk) begin
        if(reset)
            state   <=  'b10; //SEQ_RCGN
        else begin
            state   <=  nxt_state;
        end  
    end

    //output logic
    assign  done        =   state[WAT_ACK] ;
    assign  counting    =   state[WAT_CNT_FIN];
    assign  count       =   dly_val;
endmodule

三、

module shift_count_module (
    input clk,
	input data,
	input shift_ena,
	input count_ena,
    output reg [3:0] q
	);
 
    always@(posedge clk) begin
        if(shift_ena)
            q<={q[2:0],data};
        else if(count_ena)
            q<=q-1;
    end
    
endmodule
 
module count_1000_module (
	input clk,
	input reset,
    output reg [9:0] q);
    
    always@(posedge clk) begin
        if(reset)
            q<=0;
        else if(q<10'd999)
            q<=q+1;
        else
            q<=0;
    end
    
endmodule

module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output [3:0] count,
    output counting,
    output done,
    input ack );
    
    
    reg [6:0] n_state,state; 
    parameter s0=0,s1=1,s2=2,s3=3,s_shift=4,s_count=5,s_done=6;
    
    always@(*) begin
        case(state)
            s0:n_state=data?s1:s0;
            s1:n_state=data?s2:s0;
            s2:n_state=data?s2:s3;
            s3:n_state=data?s_shift:s0;
            s_shift:n_state=(cnt1==3'd3)?s_count:s_shift;    
            s_count:n_state=(counting_finish_ena)?s_done:s_count;  
            s_done:n_state=ack?s0:s_done;
        endcase
    end
    
    reg [1:0] cnt1;
    always@(posedge clk) begin
        if(reset)
            cnt1<=0;
        else if(state==s_shift)
            cnt1<=cnt1+1;
        else
            cnt1<=0;
    end
    
 
    wire [9:0] counting_doing;
    count_1000_module u_1 (
        .clk(clk),
        .reset(state!=s_count),
        .q(counting_doing)
    );
    
    wire [3:0] count_delay;
    wire counting_finish_ena;
    shift_count_module u_2 (
        .clk(clk),
        .data(data),
        .shift_ena(state==s_shift),
        .count_ena(((counting_doing==10'd999)&&(count_delay!=0))),
        .q(count_delay)
    );
    assign counting_finish_ena= (counting_doing==10'd999)&&(count_delay==0);
    
    always@(posedge clk) begin
        if(reset)
            state<=0;
        else
            state<=n_state;
    end
    
    assign count=count_delay;
    assign counting=(state==s_count);
    assign done=(state==s_done);
    
endmodule

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值