首页 > 解决方案 > Verilog:条件分支

问题描述

我希望iState(从底部开始的第二个条)在时钟的上升沿(最顶部的条)为 0,并且当它的当前值为 1110(假设iSkip并且iRev都是 0)或 1010(假设iSkip是1 并且iRev都是 0)。但是,它改为 1111。有谁知道为什么会发生这种情况以及我应该怎么做?谢谢。

在此处输入图像描述 有谁知道我应该怎么做?谢谢。

module CounterSkipReverse(iClk, iRst, iSkip, iRev, oState);
   input iClk, iRst, iSkip, iRev;
   //declare oState:
    output integer oState;
   //declare internal wires and reg types here:
    always @ (posedge iClk) begin
        if (iRst == 1)
            oState <= 0;
        else
            if (iSkip == 0 & iRev == 0) oState <= oState + 4'd1;
            else if (iSkip == 1 & iRev == 0) oState <= oState + 4'd5;
            else if (iSkip == 0 & iRev == 1) oState <= oState - 4'd1;
            else if (iSkip == 1 & iRev == 1) oState <= oState + 4'd9;
            if (oState < 0) oState <= oState + 4'd14;
            if (oState > 14) oState <= oState - 4'd14;
    end 
 
endmodule
 
module StateToCountSequence(iState, oV);
    //declare the input and output 
    input iState;
    output reg [3:0]oV;
  
    //declare any internal wire and reg types here.
    
    always @ (iState) begin
        case(iState)
            4'd0: oV = 4'd3;
            4'd1: oV = 4'd2;
            4'd2: oV = 4'd4;
            4'd3: oV = 4'd9;
            4'd4: oV = 4'd9;
            4'd5: oV = 4'd0;
            4'd6: oV = 4'd7;
            4'd7: oV = 4'd1;
            4'd8: oV = 4'd1;
            4'd9: oV = 4'd5;
            4'd10: oV = 4'd1;
            4'd11: oV = 4'd7;
            4'd12: oV = 4'd0;
            4'd13: oV = 4'd8;
            4'd14: oV = 4'd9;
        endcase
    end
  
    //Have you checked for inferred latches in this module?
endmodule 

module CompleteCounter(iClk, iRst, iSkip, iRev, oV, oState);
    input iClk, iRst, iSkip, iRev;
    output [3:0] oV;
    //declare oState next line
    output [3:0]oState;
    
    CounterSkipReverse cntr(.iClk(iClk), .iRst(iRst), .iSkip(iSkip), .iRev(iRev), .oState(oState));
    StateToCountSequence statemap(.iState(oState), .oV(oV));
endmodule

`timescale 1ns / 1ps
module AssignmentTestBench;
 
   //declare internal signals and instantiate module CompleteCounter.
    reg iClk, iRst, iSkip, iRev;
    wire [3:0]oState;
    wire [3:0]oV;
    
    initial begin
        iClk = 1'b1;
        iRst = 0;
        iSkip = 0;
        iRev = 0;
    end
    
    CompleteCounter counter(iClk, iRst, iSkip, iRev, oV, oState);
    
   //generate test sequences for all state transitions
    always begin
        #5 iClk = ~iClk;  //period 10 ns for clock
    end
    
    always begin  // control w input and reset
        #1;
        
        // iSkip = 0, iRev = 0
        #10 iRst = 1'b1;
        #10 iRst = 1'b0;
        #300;  // 30 clock cycles
        
        // iSkip = 1, iRev = 0
        #10 iRst = 1'b1;
        #10 iRst = 1'b0;
            iSkip = 1'b1;
        #80;
        
        // iSkip = 1, iRev = 1
        #10 iRst = 1'b1;
        #10 iRst = 1'b0;
            iRev = 1'b1;
        #40;
        
        // iSkip = 0, iRev = 1
        #10 iRst = 1'b1;
        #10 iRst = 1'b0;
            iSkip = 1'b0;
        #150;

        $display("Finished test");
        $finish;  // remove for modelsim
        $stop;
    end
  
endmodule

标签: verilog

解决方案


工作的方式是在块完成后将<=值分配给oState 。因此,在接下来的oState计划为 15 时,if语句仍将其视为14.

    oState <= oState + 1;
    ...
    if (oState > 14) ...

至少,您需要if(oState >= 14);

此外,在以下声明中

            if (oState > 14) oState <= oState - 4'd14;

如果oState确实大于 14,即 15,则15 - 14 = 1

你可能需要

            if (oState > 14) oState <= 0;

您还需要弄清楚表达式的另一面。问题是这if (oState <= 0)会给你带来麻烦ostate <= 0。您可能需要以下内容:if (iSkip == 0 && iRev == 1 && oState <= 0)

还有几个问题:

BT oStateCounterSkipReverseinteger中,它是 32 位宽有符号的。另一方面,istate 是StateToCountSequence输入。您需要使它们都具有相同的宽度。您的 case 语句不适用于 1 位 iState。one-bit wide

此外,不要&在条件语句中使用singel。使用`&&。尽管在您的情况下并不重要,但在我上面提供的建议中确实很重要。

不使用always @(iState),使用always @*


推荐阅读