Fsm1
状态机设计:3 段式(推荐)
状态机设计如下:
- (0) 首先,根据状态机的个数确定状态机编码。利用编码给状态寄存器赋值,代码可读性更好。
- (1) 状态机第一段,时序逻辑,非阻塞赋值,传递寄存器的状态。
- (2) 状态机第二段,组合逻辑,阻塞赋值,根据当前状态和当前输入,确定下一个状态机的状态。
- (3) 状态机第三代,时序逻辑,非阻塞赋值,因为是 Mealy 型状态机,根据当前状态和当前输入,确定输出信号。
下面的是两段式:
module top_module (
input clk,
input in,
input areset,
output out
);
// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
// It doesn't really matter what assignment is used, as long as they're unique.
parameter A=0, B=1;
reg state; // Ensure state and next are big enough to hold the state encoding.
reg next;
// A finite state machine is usually coded in three parts:
// State transition logic
// State flip-flops
// Output logic
// It is sometimes possible to combine one or more of these blobs of code
// together, but be careful: Some blobs are combinational circuits, while some
// are clocked (DFFs).
// Combinational always block for state transition logic. Given the current state and inputs,
// what should be next state be?
// Combinational always block: Use blocking assignments.
always@(*) begin
case (state)
A: next = in ? A : B;
B: next = in ? B : A;
endcase
end
// Edge-triggered always block (DFFs) for state flip-flops. Asynchronous reset.
always @(posedge clk, posedge areset) begin
if (areset) state <= B; // Reset to state B
else state <= next; // Otherwise, cause the state to transition
end
// Combinational output logic. In this problem, an assign statement is the simplest.
// In more complex circuits, a combinational always block may be more suitable.
assign out = (state==B);
endmodule
标准形式
// vending-machine
// 2 yuan for a bottle of drink
// only 2 coins supported: 5 jiao and 1 yuan
// finish the function of selling and changing
module vending_machine_p3 (
input clk ,
input rstn ,
input [1:0] coin , //01 for 0.5 jiao, 10 for 1 yuan
output [1:0] change ,
output sell //output the drink
);
//machine state decode
parameter IDLE = 3'd0 ;
parameter GET05 = 3'd1 ;
parameter GET10 = 3'd2 ;
parameter GET15 = 3'd3 ;
//machine variable
reg [2:0] st_next ;
reg [2:0] st_cur ;
//(1) state transfer
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
st_cur <= 'b0 ;
end
else begin
st_cur <= st_next ;
end
end
//(2) state switch, using block assignment for combination-logic
//all case items need to be displayed completely
always @(*) begin
//st_next = st_cur ;//如果条件选项考虑不全,可以赋初值消除latch
case(st_cur)
IDLE:
case (coin)
2'b01: st_next = GET05 ;
2'b10: st_next = GET10 ;
default: st_next = IDLE ;
endcase
GET05:
case (coin)
2'b01: st_next = GET10 ;
2'b10: st_next = GET15 ;
default: st_next = GET05 ;
endcase
GET10:
case (coin)
2'b01: st_next = GET15 ;
2'b10: st_next = IDLE ;
default: st_next = GET10 ;
endcase
GET15:
case (coin)
2'b01,2'b10:
st_next = IDLE ;
default: st_next = GET15 ;
endcase
default: st_next = IDLE ;
endcase
end
//(3) output logic, using non-block assignment
reg [1:0] change_r ;
reg sell_r ;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
change_r <= 2'b0 ;
sell_r <= 1'b0 ;
end
else if ((st_cur == GET15 && coin ==2'h1)
|| (st_cur == GET10 && coin ==2'd2)) begin
change_r <= 2'b0 ;
sell_r <= 1'b1 ;
end
else if (st_cur == GET15 && coin == 2'h2) begin
change_r <= 2'b1 ;
sell_r <= 1'b1 ;
end
else begin
change_r <= 2'b0 ;
sell_r <= 1'b0 ;
end
end
assign sell = sell_r ;
assign change = change_r ;
endmodule
Fsm3onehot
“通过检查得出方程”是什么意思?
One-hot 状态机编码保证恰好有一个状态位为 1。这意味着可以通过仅检查一个状态位而不是所有状态位来确定状态机是否处于特定状态。通过检查状态转换图中每个状态的输入边,这导致了状态转换的简单逻辑方程。
比如上面的状态机中,状态机如何才能达到状态A?它必须使用两个传入边之一:“当前处于状态 A 且 in=0”或“当前处于状态 C 且 in = 0”。由于 one-hot 编码,用于测试“当前处于状态 A”的逻辑方程只是状态 A 的状态位。这导致状态位 A 的下一个状态的最终逻辑方程:next_state[0] =状态[0]&(~in) |状态[2]&(~in)。 one-hot 编码保证一次最多有一个子句(乘积项)是“活动的”,因此这些子句可以被 ORed 在一起。
当练习要求“通过检查”获得状态转移方程时,请使用此特定方法。法官将使用非单热输入进行测试,以确保您的逻辑方程遵循此方法,而不是对状态位的非法(非单热)组合执行其他操作(例如重置 FSM)。
虽然知道这个算法对于 RTL 级设计(逻辑合成器处理这个)不是必需的,但它说明了为什么 one-hot FSM 通常具有更简单的逻辑(以更多的状态位存储为代价),并且这个主题经常显示参加数字逻辑课程的考试。
module top_module(
input in,
input [3:0] state,
output [3:0] next_state,
output out); //
parameter A=0, B=1, C=2, D=3;
// State transition logic: Derive an equation for each state flip-flop.
assign next_state[A] = state[A]&~in | state[C]&~in ;
assign next_state[B] = state[B]&in | state[D]&in | state[A]∈
assign next_state[C] = state[B]&~in | state[D]&~in;
assign next_state[D] = state[C]∈
// Output logic:
assign out = (state[D] == 1'b1);
endmodule
虽然写出来了,但是对于这道题为什么叫做独热码很疑惑,明明没有用到独热码啊?
Exams/ece241 2013 q4
这是一个水位控制系统,S1,S2,S3是三个水位传感器。FR3,FR2,FR1为三个控制水流量的开关,开得越多流量越大。ΔFR是检测水位变化的标志,若前一时间的水位高于当前时间的水位就置一(这个也是题中给的不够明确的地方,假如两个时间水位相同的情况没有明确,但根据作者的DEBUG调试可以看出,作者想让发生这种情况的时候保持原来的ΔFR的值)
题目信息看的不清不楚
抄了
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
reg [1:0] state,next_state;
reg [2:0] outfr;
parameter t1 = 2'b00,
t2 = 2'b01,
t3 = 2'b10,
t4 = 2'b11;
assign {fr3,fr2,fr1} = outfr;
always@(posedge clk) begin
if(reset)
state <= t1;
else
state <= next_state;
end
always@(*) begin
case(s)
3'b000:next_state = t1;
3'b001:next_state = t2;
3'b011:next_state = t3;
3'b111:next_state = t4;
default:next_state = t1;
endcase
end
always@(posedge clk) begin
if(reset)
outfr <= 3'b111;
else begin
case(next_state)
t1:outfr <= 3'b111;
t2:outfr <= 3'b011;
t3:outfr <= 3'b001;
t4:outfr <= 3'b000;
endcase
end
end
always@(posedge clk)begin
if(reset)
dfr <= 1;
else begin
if(next_state < state)
dfr <= 1;
else if(next_state > state)
dfr <= 0;
else
dfr <= dfr;
end
end
endmodule
标准答案
module top_module (
input clk,
input reset,
input [3:1] s,
output reg fr3,
output reg fr2,
output reg fr1,
output reg dfr
);
// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
// It doesn't really matter what assignment is used, as long as they're unique.
// We have 6 states here.
parameter A2=0, B1=1, B2=2, C1=3, C2=4, D1=5;
reg [2:0] state, next; // Make sure these are big enough to hold the state encodings.
// Edge-triggered always block (DFFs) for state flip-flops. Synchronous reset.
always @(posedge clk) begin
if (reset) state <= A2;
else state <= next;
end
// Combinational always block for state transition logic. Given the current state and inputs,
// what should be next state be?
// Combinational always block: Use blocking assignments.
always@(*) begin
case (state)
A2: next = s[1] ? B1 : A2;
B1: next = s[2] ? C1 : (s[1] ? B1 : A2);
B2: next = s[2] ? C1 : (s[1] ? B2 : A2);
C1: next = s[3] ? D1 : (s[2] ? C1 : B2);
C2: next = s[3] ? D1 : (s[2] ? C2 : B2);
D1: next = s[3] ? D1 : C2;
default: next = 'x;
endcase
end
// Combinational output logic. In this problem, a procedural block (combinational always block)
// is more convenient. Be careful not to create a latch.
always@(*) begin
case (state)
A2: {fr3, fr2, fr1, dfr} = 4'b1111;
B1: {fr3, fr2, fr1, dfr} = 4'b0110;
B2: {fr3, fr2, fr1, dfr} = 4'b0111;
C1: {fr3, fr2, fr1, dfr} = 4'b0010;
C2: {fr3, fr2, fr1, dfr} = 4'b0011;
D1: {fr3, fr2, fr1, dfr} = 4'b0000;
default: {fr3, fr2, fr1, dfr} = 'x;
endcase
end
endmodule