我一直在研究使用Verilog HDL实现的FSM。在确定下一个状态输出的情况下,我需要分配两个输出。因此,我尝试使用begin
和end
将两个赋值放在一个案例中。但这仍然行不通。我不确定是否存在某些语法错误,无法以这种方式编写代码。
module Vending_FSM(
input [2:0] INPUT,
input CLK,
output REL,
output [3:0] AMT
);
// Declaring state and next_state variable
reg[2:0] state, next_state;
// Declaring 6 state parameters
parameter
S0 = 3'b000, // WAIT
S1 = 3'b001, // $5
S2 = 3'b010, // $10
S3 = 3'b011, // $15
S4 = 3'b100, // $20
S5 = 3'b101; // $25
// Determning next state transition
always @(posedge CLK)
begin
state <= next_state; // Positive-edge triggering
end
// Determing next state input
always @(INPUT or state)
begin
case (state)
S0: case (INPUT) // WAIT
3'b000: next_state = S1; // $5
3'b001: next_state = S2; // $10
3'b010: next_state = S4; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S0; // $100
3'b101: next_state = S0; // PUR
3'b110: next_state = S0; // REF
endcase
S1: case (INPUT) // $5
3'b000: next_state = S2; // $5
3'b001: next_state = S3; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S1; // $100
3'b101: next_state = S1; // PUR
3'b110: next_state = S0; // REF
endcase
S2: case (INPUT) // $10
3'b000: next_state = S3; // $5
3'b001: next_state = S4; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S2; // $100
3'b101: next_state = S2; // PUR
3'b110: next_state = S0; // REF
endcase
S3: case (INPUT) // $15
3'b000: next_state = S4; // $5
3'b001: next_state = S5; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S3; // $100
3'b101: next_state = S3; // PUR
3'b110: next_state = S0; // REF
endcase
S4: case (INPUT) // $20
3'b000: next_state = S5; // $5
3'b001: next_state = S5; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S4; // $100
3'b101: next_state = S4; // PUR
3'b110: next_state = S0; // REF
endcase
S5: case (INPUT) // $25
3'b000: next_state = S5; // $5
3'b001: next_state = S5; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S5; // $100
3'b101: next_state = S0; // PUR
3'b110: next_state = S0; // REF
endcase
endcase
end
// Determing next state output
always @(INPUT or state)
begin
case (state)
S0: case (INPUT) // WAIT
3'b000: begin
REL = 1'b0; // $5
AMT = 4'b0000;
end
3'b001: begin
REL = 1'b0; // $10
AMT = 4'b0000;
end
3'b010: begin
REL = 1'b0; // $20
AMT = 4'b0000;
end
3'b011: begin
REL = 1'b0; // $50
AMT = 4'b0101;
end
3'b100: begin
REL = 1'b0; // $100
AMT = 4'b1011;
end
3'b101: begin
REL = 1'b0; // PUR
AMT = 4'b0000;
end
3'b110: begin
REL = 1'b0; // REF
AMT = 4'b0000;
end
endcase
S1: case (INPUT) // $5
3'b000: begin
REL = 1'b0; // $5
AMT = 4'b0000;
end
3'b001: begin
REL = 1'b0; // $10
AMT = 4'b0000;
end
3'b010: begin
REL = 1'b0; // $20
AMT = 4'b0000;
end
3'b011: begin
REL = 1'b0; // $50
AMT = 4'b0110;
end
3'b100: begin
REL = 1'b0; // $100
AMT = 4'b1011;
end
3'b101: begin
REL = 1'b0; // PUR
AMT = 4'b0000;
end
3'b110: begin
REL = 1'b0; // REF
AMT = 4'b0001;
end
endcase
S2: case (INPUT) // $10
3'b000: begin
REL = 1'b0; // $5
AMT = 4'b0000;
end
3'b001: begin
REL = 1'b0; // $10
AMT = 4'b0000;
end
3'b010: begin
REL = 1'b0; // $20
AMT = 4'b0001;
end
3'b011: begin
REL = 1'b0; // $50
AMT = 4'b0111;
end
3'b100: begin
REL = 1'b0; // $100
AMT = 4'b1011;
end
3'b101: begin
REL = 1'b0; // PUR
AMT = 4'b0000;
end
3'b110: begin
REL = 1'b0; // REF
AMT = 4'b0010;
end
endcase
S3: case (INPUT) // $15
3'b000: begin
REL = 1'b0; // $5
AMT = 4'b0000;
end
3'b001: begin
REL = 1'b0; // $10
AMT = 4'b0000;
end
3'b010: begin
REL = 1'b0; // $20
AMT = 4'b0010;
end
3'b011: begin
REL = 1'b0; // $50
AMT = 4'b1000;
end
3'b100: begin
REL = 1'b0; // $100
AMT = 4'b1011;
end
3'b101: begin
REL = 1'b0; // PUR
AMT = 4'b0000;
end
3'b110: begin
REL = 1'b0; // REF
AMT = 4'b0011;
end
endcase
S4: case (INPUT) // $20
3'b000: begin
REL = 1'b0; // $5
AMT = 4'b0000;
end
3'b001: begin
REL = 1'b0; // $10
AMT = 4'b0001;
end
3'b010: begin
REL = 1'b0; // $20
AMT = 4'b0011;
end
3'b011: begin
REL = 1'b0; // $50
AMT = 4'b1001;
end
3'b100: begin
REL = 1'b0; // $100
AMT = 4'b1011;
end
3'b101: begin
REL = 1'b0; // PUR
AMT = 4'b0000;
end
3'b110: begin
REL = 1'b0; // REF
AMT = 4'b0100;
end
endcase
S5: case (INPUT) // $25
3'b000: begin
REL = 1'b0; // $5
AMT = 4'b0001;
end
3'b001: begin
REL = 1'b0; // $10
AMT = 4'b0010;
end
3'b010: begin
REL = 1'b0; // $20
AMT = 4'b0100;
end
3'b011: begin
REL = 1'b0; // $50
AMT = 4'b1010;
end
3'b100: begin
REL = 1'b0; // $100
AMT = 4'b1011;
end
3'b101: begin
REL = 1'b1; // PUR
AMT = 4'b0000;
end
3'b110: begin
REL = 1'b0; // REF
AMT = 4'b0101;
end
endcase
endcase
end
endmodule
先谢谢您。
REL
和AMT
必须为reg
类型。由于推断出wire
类型,因此无法始终在这些块中进行分配。
module Vending_FSM(
input [2:0] INPUT,
input CLK,
output reg REL,
output reg [3:0] AMT
);
也next_state
,REL
和AMT
是推断的锁存器,因为当INPUT
等于state
-S0
之外的3'b111和S5
时,没有明确分配它。您可以在case语句中定义所有案例,或者/并且可以在case
上方为flop常量指定默认值。示例:
always @* begin
// default assignment
next_state = state;
// update
case(state)
S0: case (INPUT) // WAIT
//... your existing code, maybe added 3'b111/default case
endcase
// S1..S5: ... your existing code, maybe added case 3'b111/default for INPUT
default : next_state = S0; // in case state not inside S0..S5
endcase
end
always @* begin
// default assignment
REL = 1'b0;
ATM = 4'b0000;
// update
case(state)
//... your existing code
endcase
end
[其他说明:
always @(INPUT or state)
从技术上讲还可以,但不再推荐。使用always @*
或always @(*)
进行自动灵敏度设定。 Verilog-1995需要为灵敏度列表指定信号。 Verilog-2001增加了自动灵敏度,从而降低了灵敏度列表不完整的风险;加号减少打字。
为了获得更清晰的输出信号和更容易的时序分析,我建议将输出翻转。示例:
always @* begin
// default assignment
next_REL = 1'b0;
next_AMT = 4'b0000;
// update
case(state)
//... your existing code but REL and AMT prefixed with next_
endcase
end
always @(posedge clk) begin
state <= next_state;
REL <= next_REL;
AMT <= next_AMT;
end
module Vending_FSM(
input [2:0] INPUT
,input CLK
,output reg REL
,output reg [3:0] AMT
);
// Declaring state and next_state variable
reg[2:0] state, next_state;
reg n_AMT,n_REL;
// Declaring 6 state parameters
parameter
S0 = 3'b000, // WAIT
S1 = 3'b001, // $5
S2 = 3'b010, // $10
S3 = 3'b011, // $15
S4 = 3'b100, // $20
S5 = 3'b101; // $25
always@(posedge clk)
state <= next_state;
// Determing next state input
always@*
case (state)
S0: case (INPUT) // WAIT
3'b000: next_state = S1; // $5
3'b001: next_state = S2; // $10
3'b010: next_state = S4; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S0; // $100
3'b101: next_state = S0; // PUR
3'b110: next_state = S0; // REF
endcase
S1: case (INPUT) // $5
3'b000: next_state = S2; // $5
3'b001: next_state = S3; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S1; // $100
3'b101: next_state = S1; // PUR
3'b110: next_state = S0; // REF
endcase
S2: case (INPUT) // $10
3'b000: next_state = S3; // $5
3'b001: next_state = S4; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S2; // $100
3'b101: next_state = S2; // PUR
3'b110: next_state = S0; // REF
endcase
S3: case (INPUT) // $15
3'b000: next_state = S4; // $5
3'b001: next_state = S5; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S3; // $100
3'b101: next_state = S3; // PUR
3'b110: next_state = S0; // REF
endcase
S4: case (INPUT) // $20
3'b000: next_state = S5; // $5
3'b001: next_state = S5; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S4; // $100
3'b101: next_state = S4; // PUR
3'b110: next_state = S0; // REF
endcase
S5: case (INPUT) // $25
3'b000: next_state = S5; // $5
3'b001: next_state = S5; // $10
3'b010: next_state = S5; // $20
3'b011: next_state = S5; // $50
3'b100: next_state = S5; // $100
3'b101: next_state = S0; // PUR
3'b110: next_state = S0; // REF
endcase
default: next_state = 'x;
endcase
always @* begin
n_REL = 1'b0;
n_AMT = 4'b0;
case (state)
S0: if(INPUT == 3'b100) n_AMT = 4'b1011;
else if(INPUT == 3'b011) n_AMT = 4'b0101;
S1: if(INPUT == 3'b011) n_AMT = 4'b0110;
else if(INPUT == 3'b100) n_AMT = 4'b1011;
else if(INPUT == 3'b110) n_AMT = 4'b0001;
S2: if(INPUT == 3'b010) n_AMT = 4'b0001;
else if(INPUT == 3'b011) n_AMT = 4'b0111;
else if(INPUT == 3'b100) n_AMT = 4'b1011;
else if(INPUT == 3'b110) n_AMT = 4'b0010;
S3: if(INPUT == 3'b010) n_AMT = 4'b0010;
else if(INPUT == 3'b011) n_AMT = 4'b1000;
else if(INPUT == 3'b100) n_AMT = 4'b1011;
else if(INPUT == 3'b110) n_AMT = 4'b0011;
S4: if(INPUT == 3'b001) n_AMT = 4'b0001;
else if(INPUT == 3'b010) n_AMT = 4'b0011;
else if(INPUT == 3'b011) n_AMT = 4'b1001;
else if(INPUT == 3'b100) n_AMT = 4'b1011;
else if(INPUT == 3'b110) n_AMT = 4'b0100;
S5: if(INPUT == 3'b000) n_AMT = 4'b0001;
else if(INPUT == 3'b001) n_AMT = 4'b0010;
else if(INPUT == 3'b010) n_AMT = 4'b0100;
else if(INPUT == 3'b011) n_AMT = 4'b1010;
else if(INPUT == 3'b100) n_AMT = 4'b1011;
else if(INPUT == 3'b101) n_REL = 1'b1;
else if(INPUT == 3'b110) n_AMT = 4'b0101;
endcase
end
always @(posedge clk) begin
REL <= #1 n_REL;
AMT <= #1 n_AMT;
end
endmodule