为什么我的有限状态机(FSM)不导致组合逻辑?

huangapple go评论62阅读模式
英文:

Why does my FSM not result in combinational logic?

问题

I'm trying to make a fsm and decoder file. The decoder section gives me no issues, all of my errors point to the fsm part of my code. The main issue are the errors about latches and non combinational logic in my always_comb blocks for the fsm.

I already know that I need to include defaults to my case statements to prevent latches, but my code still gives me issues.

Here is what I have:

    input CU_RST,
    input CU_INTR,
    input [6:0] CU_OP_TYPE,
    input [2:0] CU_FUNCT3,
    input CU_OP3,
    input CU_CLK,
    input CU_INT_TAKEN_DCDR,
    input CU_BReq,
    input CU_BRlt,
    input CU_ltu,
    output logic CU_PCWrite,
    output logic CU_regWrite,
    output logic CU_memWE2,
    output logic CU_memRDEN1,
    output logic CU_memRDEN2,
    output logic CU_reset,
    output logic CU_csr_WE,
    output logic CU_INT_TAKEN_FSM,
    output logic CU_mret_exec,
    output logic [3:0] CU_alu_fun,
    output logic [1:0] CU_alu_srcA,
    output logic [2:0] CU_alu_srcB,
    output logic [2:0] CU_pcSource,
    output logic [1:0] CU_rf_wr_sel
    );
    
    //creating FSM
    typedef enum{ST_INIT, ST_FETCH, ST_EXEC, ST_WB} state_type;
    state_type PS, NS;
    
    always_ff@(posedge CU_CLK)
    begin
        if(CU_RST)
            PS <= ST_INIT;
        else 
            PS <= NS;
    end
    
    assign CU_INT_TAKEN_FSM = CU_INT_TAKEN_DCDR;
    
    always_comb
    begin
        case(PS)
            ST_INIT: //Start of program
            begin
                CU_reset = 1;
                CU_PCWrite = 0;
                NS = ST_FETCH;
            end
            ST_FETCH:   //Grabs instruction
            begin
                CU_reset = 0;
                CU_memRDEN1 = 1;
                CU_PCWrite = 0;
                CU_regWrite = 0;
                NS = ST_EXEC;
            end
            ST_EXEC:    //Executes instruction based on its type
            begin
                NS = ST_FETCH;
                case(CU_OP_TYPE)
                    7'b0110011 | 7'b0010011 | 7'b1100111 | 7'b1101111 | 7'b0110111 | 7'b0010111: 
                    //R-TYPEs and I-TYPEs that act like R-TYPEs, U-TYPES, and J-TYPES
                    begin
                        CU_PCWrite = 1;
                        CU_regWrite = 1;
                        CU_memWE2 = 0;
                        CU_memRDEN1 = 0;
                        CU_memRDEN2 = 0;
                        CU_reset = 0;
                        //CSR stuff (dw bout it)
                        CU_csr_WE = 0;
                        CU_INT_TAKEN_FSM = 0;
                        CU_mret_exec = 0;
                    end
                    7'b0000011: // all load instructions
                    begin
                        CU_PCWrite = 0;
                        CU_regWrite = 0;
                        CU_memWE2 = 0;
                        CU_memRDEN1 = 0;
                        CU_memRDEN2 = 1;
                        CU_reset = 0;
                        //CSR stuff (dw bout it)
                        CU_csr_WE = 0;
                        CU_INT_TAKEN_FSM = 0;
                        CU_mret_exec = 0;
                        NS = ST_WB;
                    end
                    7'b0100011: // S-TYPES
                    begin
                        CU_PCWrite = 1;
                        CU_regWrite = 0;
                        CU_memWE2 = 1;
                        CU_memRDEN1 = 0;
                        CU_memRDEN2 = 0;
                        CU_reset = 0;
                        //CSR stuff (dw bout it)
                        CU_csr_WE = 0;
                        CU_INT_TAKEN_FSM = 0;
                        CU_mret_exec = 0;
                    end
                    7'b1100011: // B-TYPES
                    begin
                        CU_PCWrite = 1;
                        CU_regWrite = 0;
                        CU_memWE2 = 0;
                        CU_memRDEN1 = 0;
                        CU_memRDEN2 = 0;
                        CU_reset = 0;
                        //CSR stuff (dw bout it)
                        CU_csr_WE = 0;
                        CU_INT_TAKEN_FSM = 0;
                        CU_mret_exec = 0;
                    end
                    default: begin
                    CU_PCWrite = 1;
                        CU_regWrite = 0;
                        CU_memWE2 = 0;
                        CU_memRDEN1 = 0;
                        CU_memRDEN2 = 0;
                        CU_reset = 0;
                        //CSR stuff (dw bout it)
                        CU_csr_WE = 0;
                        CU_INT_TAKEN_FSM = 0;
                        CU_mret_exec = 0;; //resets program if wrong
                    end
                endcase
            end
            ST_WB:  //writes value from load instruction back to register file
            begin
                CU_PCWrite = 1;
                CU_regWrite = 1;
                CU_memWE2 = 0;
                CU_memRDEN1 = 0;
                CU_memRDEN2 = 0;
                CU_reset = 0;
                //CSR stuff (dw bout it)
                CU_csr_WE = 0;
                CU_INT_TAKEN_FSM = 0;
                CU_mret_exec = 0;
                NS = ST_FETCH;
            end
            default: 
            begin
            CU_PCWrite = 1;
                CU_regWrite = 1;
                CU_memWE2 = 0;
                CU_memRDEN1 = 0;
                CU_memRDEN2 = 0;
                CU_reset = 0;
                //CSR stuff (dw bout it)
                CU_csr_WE = 0;
                CU_INT_TAKEN_FSM = 0;
                CU_mret_exec = 0;
                NS = ST_FETCH;
            end
        endcase
    end
    
    //creating Decoder
    always_comb 
    begin
        CU_alu_fun = 4'b0000;
        CU_alu_srcA = 2'b00;
        CU_alu_srcB = 3'b000;
        CU_pcSource = 3'b000;
        CU_rf_wr_sel = 2'b00;
        case(CU_OP_TYPE)
            7'b0110011: //R-TYPES
            begin
                //All R-types behave the same besides what ALU does to values
                CU_alu_srcA = 2'b00;
                CU_alu_srcB = 3'b000;
                CU_pcSource = 3'b000;
                CU_rf_wr_sel = 2'b11;
                case

<details>
<summary>英文:</summary>

I&#39;m trying to make a fsm and decoder file. The decoder section gives me no issues, all of my errors point to the fsm part of my code. The main issue are the errors about latches and non combinational logic in my always_comb blocks for the fsm.

I already know that I need to include defaults to my case statements to prevent latches, but my code still gives me issues.

Here is what I have:
`

module ControlUnit(
input CU_RST,
input CU_INTR,
input [6:0] CU_OP_TYPE,
input [2:0] CU_FUNCT3,
input CU_OP3,
input CU_CLK,
input CU_INT_TAKEN_DCDR,
input CU_BReq,
input CU_BRlt,
input CU_ltu,
output logic CU_PCWrite,
output logic CU_regWrite,
output logic CU_memWE2,
output logic CU_memRDEN1,
output logic CU_memRDEN2,
output logic CU_reset,
output logic CU_csr_WE,
output logic CU_INT_TAKEN_FSM,
output logic CU_mret_exec,
output logic [3:0] CU_alu_fun,
output logic [1:0] CU_alu_srcA,
output logic [2:0] CU_alu_srcB,
output logic [2:0] CU_pcSource,
output logic [1:0] CU_rf_wr_sel
);

//creating FSM
typedef enum{ST_INIT, ST_FETCH, ST_EXEC, ST_WB} state_type;
state_type PS, NS;

always_ff@(posedge CU_CLK)
begin
    if(CU_RST)
        PS &lt;= ST_INIT;
    else 
        PS &lt;= NS;
end

assign CU_INT_TAKEN_FSM = CU_INT_TAKEN_DCDR;

always_comb
begin
    case(PS)
        ST_INIT: //Start of program
        begin
            CU_reset = 1;
            CU_PCWrite = 0;
            NS = ST_FETCH;
        end
        ST_FETCH:   //Grabs instruction
        begin
            CU_reset = 0;
            CU_memRDEN1 = 1;
            CU_PCWrite = 0;
            CU_regWrite = 0;
            NS = ST_EXEC;
        end
        ST_EXEC:    //Executes instruction based on its type
        begin
            NS = ST_FETCH;
            case(CU_OP_TYPE)
                7&#39;b0110011 | 7&#39;b0010011 | 7&#39;b1100111 | 7&#39;b1101111 | 7&#39;b0110111 | 7&#39;b0010111: 
                //R-TYPEs and I-TYPEs that act like R-TYPEs, U-TYPES, and J-TYPES
                begin
                    CU_PCWrite = 1;
                    CU_regWrite = 1;
                    CU_memWE2 = 0;
                    CU_memRDEN1 = 0;
                    CU_memRDEN2 = 0;
                    CU_reset = 0;
                    //CSR stuff (dw bout it)
                    CU_csr_WE = 0;
                    CU_INT_TAKEN_FSM = 0;
                    CU_mret_exec = 0;
                end
                7&#39;b0000011: // all load instructions
                begin
                    CU_PCWrite = 0;
                    CU_regWrite = 0;
                    CU_memWE2 = 0;
                    CU_memRDEN1 = 0;
                    CU_memRDEN2 = 1;
                    CU_reset = 0;
                    //CSR stuff (dw bout it)
                    CU_csr_WE = 0;
                    CU_INT_TAKEN_FSM = 0;
                    CU_mret_exec = 0;
                    NS = ST_WB;
                end
                7&#39;b0100011: // S-TYPES
                begin
                    CU_PCWrite = 1;
                    CU_regWrite = 0;
                    CU_memWE2 = 1;
                    CU_memRDEN1 = 0;
                    CU_memRDEN2 = 0;
                    CU_reset = 0;
                    //CSR stuff (dw bout it)
                    CU_csr_WE = 0;
                    CU_INT_TAKEN_FSM = 0;
                    CU_mret_exec = 0;
                end
                7&#39;b1100011: // B-TYPES
                begin
                    CU_PCWrite = 1;
                    CU_regWrite = 0;
                    CU_memWE2 = 0;
                    CU_memRDEN1 = 0;
                    CU_memRDEN2 = 0;
                    CU_reset = 0;
                    //CSR stuff (dw bout it)
                    CU_csr_WE = 0;
                    CU_INT_TAKEN_FSM = 0;
                    CU_mret_exec = 0;
                end
                default: begin
                CU_PCWrite = 1;
                    CU_regWrite = 0;
                    CU_memWE2 = 0;
                    CU_memRDEN1 = 0;
                    CU_memRDEN2 = 0;
                    CU_reset = 0;
                    //CSR stuff (dw bout it)
                    CU_csr_WE = 0;
                    CU_INT_TAKEN_FSM = 0;
                    CU_mret_exec = 0;; //resets program if wrong
                end
            endcase
        end
        ST_WB:  //writes value from load instruction back to register file
        begin
            CU_PCWrite = 1;
            CU_regWrite = 1;
            CU_memWE2 = 0;
            CU_memRDEN1 = 0;
            CU_memRDEN2 = 0;
            CU_reset = 0;
            //CSR stuff (dw bout it)
            CU_csr_WE = 0;
            CU_INT_TAKEN_FSM = 0;
            CU_mret_exec = 0;
            NS = ST_FETCH;
        end
        default: 
        begin
        CU_PCWrite = 1;
            CU_regWrite = 1;
            CU_memWE2 = 0;
            CU_memRDEN1 = 0;
            CU_memRDEN2 = 0;
            CU_reset = 0;
            //CSR stuff (dw bout it)
            CU_csr_WE = 0;
            CU_INT_TAKEN_FSM = 0;
            CU_mret_exec = 0;
            NS = ST_FETCH;
        end
    endcase
end

//creating Decoder
always_comb 
begin
    CU_alu_fun = 4&#39;b0000;
    CU_alu_srcA = 2&#39;b00;
    CU_alu_srcB = 3&#39;b000;
    CU_pcSource = 3&#39;b000;
    CU_rf_wr_sel = 2&#39;b00;
    case(CU_OP_TYPE)
        7&#39;b0110011: //R-TYPES
        begin
            //All R-types behave the same besides what ALU does to values
            CU_alu_srcA = 2&#39;b00;
            CU_alu_srcB = 3&#39;b000;
            CU_pcSource = 3&#39;b000;
            CU_rf_wr_sel = 2&#39;b11;
            case(CU_FUNCT3) //specify what to do to values at ALU
                3&#39;b010: CU_alu_fun = 4&#39;b0010; // slt
                3&#39;b100: CU_alu_fun = 4&#39;b000; // xor
                default: CU_alu_fun = 4&#39;b0000;  //add
            endcase
        end
        7&#39;b0010011: //I_TYPES like R_TYPES
        begin
            CU_alu_srcA = 2&#39;b00;
            CU_alu_srcB = 3&#39;b001;
            CU_pcSource = 3&#39;b000;
            CU_rf_wr_sel = 2&#39;b11;
            case(CU_FUNCT3)
                3&#39;b000: CU_alu_fun = 4&#39;b0000; //addi
                3&#39;b001: CU_alu_fun = 4&#39;b0001; //slli
            endcase
        end
        7&#39;b0110111: // lui
        begin
            CU_alu_fun = 4&#39;b1001;
            CU_alu_srcA = 2&#39;b01;
            CU_alu_srcB = 3&#39;b000;
            CU_pcSource = 3&#39;b000;
            CU_rf_wr_sel = 2&#39;b11;
        end
        7&#39;b1100011: // B_TYPES
        begin
            CU_pcSource = 3&#39;b010;
        end
        default:
        begin
            CU_alu_fun = 4&#39;b0000;
            CU_alu_srcA = 2&#39;b00;
            CU_alu_srcB = 3&#39;b000;
            CU_pcSource = 3&#39;b000;
            CU_rf_wr_sel = 2&#39;b00;
        end
    endcase
end

endmodule

I appreciate any advice.

</details>


# 答案1
**得分**: 0

有些变量在所有情况下都没有赋值。例如,在ST_INIT情况下的CU_regWrite。如果在情况块中难以管理赋值,可以在开头为所有变量设置默认赋值,然后在情况中覆盖一些变量。例如:

```verilog
always @*
begin
  state_next = state;  // 默认值
  reg_wr = 0;  // 默认值
  reg_rd = 0;  // 默认值
  case ( state )
    0:
      if ( cmd_wr )
        state_next = 1;
      else if ( cmd_rd )
        state_next = 2;
    1:
    begin
      reg_wr = 1;
      state_next = 3;  
    end
    2:
    begin
      reg_rd = 1;
      state_next = 3;  
    end
    default: state_next = 0;
  endcase
end
```

<details>
<summary>英文:</summary>

Some variables are not assigned in all cases. For example, CU_regWrite in ST_INIT case. If you feel hard to manage the assignment in case blocks, you may put the default assignment to all variables at the beginning, then overwrite some of the variables in the cases. For example:

    always @*
    begin
      state_next = state;  // Default value
      reg_wr = 0;  // Default value
      reg_rd = 0;  // Default value
      case ( state )
        0:
          if ( cmd_wr )
            state_next = 1;
          else if ( cmd_rd )
            state_next = 2;
        1:
        begin
          reg_wr = 1;
          state_next = 3;  
        end
        2:
        begin
          reg_rd = 1;
          state_next = 3;  
        end
        default: state_next = 0;
      endcase
    end



</details>



huangapple
  • 本文由 发表于 2023年3月1日 12:13:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75599504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定