英文:
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'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 <= 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(CU_FUNCT3) //specify what to do to values at ALU
3'b010: CU_alu_fun = 4'b0010; // slt
3'b100: CU_alu_fun = 4'b000; // xor
default: CU_alu_fun = 4'b0000; //add
endcase
end
7'b0010011: //I_TYPES like R_TYPES
begin
CU_alu_srcA = 2'b00;
CU_alu_srcB = 3'b001;
CU_pcSource = 3'b000;
CU_rf_wr_sel = 2'b11;
case(CU_FUNCT3)
3'b000: CU_alu_fun = 4'b0000; //addi
3'b001: CU_alu_fun = 4'b0001; //slli
endcase
end
7'b0110111: // lui
begin
CU_alu_fun = 4'b1001;
CU_alu_srcA = 2'b01;
CU_alu_srcB = 3'b000;
CU_pcSource = 3'b000;
CU_rf_wr_sel = 2'b11;
end
7'b1100011: // B_TYPES
begin
CU_pcSource = 3'b010;
end
default:
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;
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论