FPGA project : HCSR04

犯下的错误:

1,由于使用cnt_base 做echo回响信号高电平时间的测量,它的数据应该很大,位宽也很大。也可以采用cnt_us计数器,计算这个高电平时间的。我为了精确计算距离,所以才仍然用的cnt_base计数器。

2,在RESPOUND状态下,cnt_base归零条件写错了。呜呜。

因为这个add_cnt_base信号是我写代码时后加上去的,没有画它的时序图。也是我对时序逻辑赋值延后条件一个时钟周期的认识还不够深刻吧。导致这个归零条件错了一个sys_clk.

遇到的警告与解决办法:

Error:(vsim-3601) Iteration limit reached at time 55445 ns.(仿真时遇到的)

在55445ns的时候,超出了迭代的限制。一般modelsim的迭代限制为5000次。

一般认为出现这种错误,是因为在代码里面出现了回环,通常是组合电路的问题。比方说在一个组合逻辑块里面,对敏感变量进行赋值。

作为敏感变量,只要变化,就会触发组合逻辑块的赋值,而赋值又会立马让敏感变量变化,然后再触发组合逻辑块赋值。

这样循环往复,每次触发变化的时间,是几乎可以忽略不计的。一旦敏感变量触发组合电路的赋值,便会不断地,触发--赋值--触发---赋值。。。

并且组合电路动作,几乎不花时间,这样实际上就是一个死循环。

解决办法:找到代码中采用电平敏感描述组合的逻辑块,查找问题;具体,就是避免在敏感变量A所触发的逻辑块中,再次对敏感变量A进行赋值操作。

hc_sr04的代码里64行,就是活生生的例子。

 

 

 

module hc_sr04 (
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire            echo        ,

    output      reg             trig        ,
    output      reg     [19:0]  distance
);
    // parameter 
    parameter       MS_500     = 20'd499_999 ;
    // localparam
    localparam      WAIT_500MS = 3'b001 ,
                    TRIGER     = 3'b010 ,
                    RESPOUND   = 3'b100 ;
    // wire signal define
    wire            flag_base           ;
    wire            nege                ;
    wire            pose                ;
    wire            WAIT_500MStoTRIGER  ;  
    wire            TRIGERtoRESPOUND    ;    
    wire            RESPOUNDtoWAIT_500MS;
    // reg signal define
    reg             echo_reg0   ;
    reg             echo_reg1   ;
    reg             echo_reg2   ;
    reg             flag        ;
    reg             add_cnt_base;
    reg     [2:0]   state_c     ;
    reg     [2:0]   state_n     ;
    reg     [31:0]  cnt_base    ;
    reg     [19:0]  cnt_us      ;

/*******************************************************************************/
    // wire            flag_base;
    assign flag_base = (cnt_base == 49) ? 1'b1 : 1'b0 ;
    // wire            flag    ;
    // assign flag = (state_c != RESPOUND) ? ((state_c == WAIT_500MS && cnt_us == MS_500) ?  1'b1 : (state_c == TRIGER && cnt_us == 10) ? 1'b1 : 1'b0) : 1'b0 ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            flag <= 0 ;
        end else begin
            case (state_c)
            WAIT_500MS: begin
                            if(cnt_us == MS_500) begin
                                flag <= 1 ;
                            end else begin
                                flag <= 0 ;
                            end
                        end
            TRIGER    : begin
                            if(cnt_us == 10) begin
                                flag <= 1 ;
                            end else begin
                                flag <= 0 ;
                            end
                        end
            RESPOUND  : flag <= 0 ;
            default   : flag <= 0 ;
            endcase
        end
    end
    // wire            nege    ;
    // wire            pose    ;
    assign nege = ~echo_reg1 &&  echo_reg2 ;
    assign pose =  echo_reg1 && ~echo_reg2 ;
    // // wire            add_cnt_base;
    // assign add_cnt_base = (pose || nege) ? ~add_cnt_base : 1'b0 ; 这里产生了迭代。不利于仿真,所以改成时序逻辑。
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            add_cnt_base <= 1'b0 ;
        end else begin
            if(pose || nege) begin
                add_cnt_base <= ~add_cnt_base ;
            end else begin
                add_cnt_base <=  add_cnt_base ;
            end
        end
    end
    // reg signal define
    // reg             echo_reg0;
    // reg             echo_reg1;
    // reg             echo_reg2;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            echo_reg0 <= 1'b0 ;
            echo_reg1 <= 1'b0 ;
            echo_reg2 <= 1'b0 ;
        end else begin
            echo_reg0 <= echo      ;
            echo_reg1 <= echo_reg0 ;
            echo_reg2 <= echo_reg1 ;
        end
    end
    // reg     [2:0]   state_c  ;
    // reg     [2:0]   state_n  ; 三段式状态机,状态转移描述,状态转移条件描述,与状机有关信号描述
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            state_c <= WAIT_500MS ;
        end else begin
            state_c <= state_n ;
        end
    end
    always @(*) begin
        case (state_c)
        WAIT_500MS :begin
                        if(WAIT_500MStoTRIGER) begin
                            state_n <= TRIGER ;
                        end else begin
                            state_n <= WAIT_500MS ;
                        end
                    end
        TRIGER     :begin
                        if(TRIGERtoRESPOUND) begin
                            state_n <= RESPOUND ;
                        end else begin
                            state_n <= TRIGER ;
                        end
                    end
        RESPOUND   :begin
                        if(RESPOUNDtoWAIT_500MS) begin
                            state_n <= WAIT_500MS ;
                        end else begin
                            state_n <= RESPOUND ;
                        end
                    end
            default:state_n <= WAIT_500MS ;
        endcase
    end
    assign  WAIT_500MStoTRIGER      = (state_c == WAIT_500MS) && (flag_base && flag) ;
    assign  TRIGERtoRESPOUND        = (state_c == TRIGER    ) && (flag_base && flag) ;
    assign  RESPOUNDtoWAIT_500MS    = (state_c == RESPOUND  ) && (nege) ;
    // reg     [19:0]  cnt_base ; // 用来产生1us信号,也用来计算距离。
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_base <= 32'd0 ;
        end else begin
            case (state_c)
            WAIT_500MS :begin
                            if(cnt_base == 49) begin
                                cnt_base <= 32'd0 ;
                            end else begin
                                cnt_base <= cnt_base + 1'b1 ;
                            end
                        end
            TRIGER     :begin
                            if(cnt_base == 49) begin
                                cnt_base <= 32'd0 ;
                            end else begin
                                cnt_base <= cnt_base + 1'b1 ;
                            end
                        end
            RESPOUND   :begin
                            if(nege) begin
                                cnt_base <= 32'd0 ;
                            end else begin
                                if(add_cnt_base) begin
                                    cnt_base <= cnt_base + 1'b1 ;
                                end else begin
                                    cnt_base <= cnt_base ;
                                end
                            end
                        end
                default:cnt_base <= 32'd0 ;
            endcase
        end
    end
    // reg     [19:0]  cnt_us   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_us <= 20'd0 ;
        end else begin
            case (state_c)
            WAIT_500MS: begin
                            if(flag_base && cnt_us == MS_500) begin
                                cnt_us <= 20'd0 ;
                            end else begin
                                if(flag_base) begin
                                    cnt_us <= cnt_us + 1'b1 ;
                                end else begin
                                    cnt_us <= cnt_us ;
                                end
                            end
                        end
            TRIGER    : begin
                            if(flag_base && cnt_us == 10) begin
                                cnt_us <= 20'd0 ;
                            end else begin
                                if(flag_base) begin
                                    cnt_us <= cnt_us + 1'b1 ;
                                end else begin
                                    cnt_us <= cnt_us ;
                                end
                            end
                        end
            RESPOUND  :cnt_us <= 20'd0 ;
                default: cnt_us <= 20'd0 ;
            endcase
        end
    end
    // reg             trig     ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            trig <= 1'b0 ;
        end else begin
            if(state_c == TRIGER) begin
                trig <= 1'b1 ;
            end else begin
                trig <= 1'b0 ;
            end
        end
    end
    // reg     [19:0]  distance
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            distance <= 20'd0 ;
        end else begin
            if(nege) begin
                distance <= (cnt_base * 20'd34 / 20'd10000) ;
            end else begin
                distance <= distance ;
            end
        end
    end
endmodule

 

module top(
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire            echo        ,

    output      wire            trig        ,
    output      wire            ds          ,
    output      wire            oe          ,
    output      wire            shcp        ,
    output      wire            stcp    
);

    // 例化间连线
    wire    [19:0]      distance_w ;
    wire    [05:0]      point_w    ;
    wire                sign_w     ;
    wire                seg_en_w   ;
    assign              point_w = 6'b000_010 ;
    assign              sign_w  = 1'b0       ;
    assign              seg_en_w= 1'b1       ;
    
hc_sr04 hc_sr04_insert(
    .sys_clk                    ( sys_clk    ) ,
    .sys_rst_n                  ( sys_rst_n  ) ,
    .echo                       ( echo       ) ,

    .trig                       ( trig       ) ,
    .distance                   ( distance_w )
);

seg_595_dynamic seg_595_dynamic_insert(
    .sys_clk                    ( sys_clk    ) ,
    .sys_rst_n                  ( sys_rst_n  ) ,
    .data                       ( distance_w ) ,
    .point                      ( point_w    ) ,
    .sign                       ( sign_w     ) ,
    .seg_en                     ( seg_en_w   ) ,

    .ds                         ( ds         ) ,
    .oe                         ( oe         ) ,
    .shcp                       ( shcp       ) ,
    .stcp                       ( stcp       )    
);

endmodule

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值