目录
前言
3.2.5 Finite State Machines
3.2.5.5 Simple state transitions 3(Fsm3comb)
3.2.5.6 Simple one-hot state transitions 3(Fsm3onehot)
3.2.5.7 Simple FSM 3 (asynchronous reset)(Fsm3)
3.2.5.8 Simple FSM 3 (synchronous reset)(Fsm3s)
3.2.5.9 Design a Moore FSM (Exams/ece241 2013 q4)
结语
HDLbits网站链接
今天接着更新状态机部分的习题答案。
module top_module(
input in,
input [1:0] state,
output [1:0] next_state,
output out); //
parameter A=2'd0, B=2'd1, C=2'd2, D=2'd3;
always@(*)begin
case(state)
A:begin
next_state = in ? B : A;
end
B:begin
next_state = in ? B : C;
end
C:begin
next_state = in ? D : A;
end
D:begin
next_state = in ? B : C;
end
endcase
end
always@(*)begin
if(state == D)begin
out <= 1'b1;
end
else begin
out <= 1'b0;
end
end
endmodule
这道题目作者已经给出了状态转移表,直接按照转移表写出verilog设计就好了。
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[A] & in | state[B] & in | state[D] & in;
assign next_state[C] = state[B] & ~in | state[D] & ~in;
assign next_state[D] = state[C] & in;
// Output logic:
assign out = state[D];
endmodule
这道题目作者是想让我们用one-hot(独热码)的编码逻辑完成。不过大家也注意到了,该题和我们平时使用的one-hot逻辑不同,我们平时使用的one-hot逻辑实在parameter中定义,比如定义四个状态,那么分别是4'b0001、4'b0010、4'b0100、4'b1000,,这道题目中的parameter还是定义为十进制的1、2、3、4,因为这里作者将输入状态和输出状态都定义为4bit,所以1、2、3、4位定义着state和next_state的4位。
大家要注意,一般我们的状态机编码为了方便都是设置为二进制码,但是如果是状态转移是按顺序转移的话,那么我们可以使用格雷码,因为格雷码每次只变化一个bit,这样可以节约功耗。如果要说速度快,那么可以使用one-hot编码,因为每次仅需判断一位就可以了,当然这种编码会消耗更多的寄存器资源,但是消耗更少的组合逻辑资源。关于这一点,不知道大家还记不记得3-8译码器,one-hot编码可以认为是已经进行过译码的编码单元,所以相比二进制编码和格雷码更节约组合逻辑资源。
如果状态较少,建议大家使用one-hot编码,如果状态较多,建议大家使用格雷码,如果功耗的影响不是那么大并且为了尽快完成设计,建议直接使用二进制编码就好了。
module top_module(
input clk,
input in,
input areset,
output out); //
parameter A=2'd0, B=2'd1, C=2'd2, D=2'd3;
reg [1:0] current_state;
reg [1:0] next_state;
always@(posedge clk or posedge areset)begin
if(areset)begin
current_state <= A;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
A:begin
next_state = in ? B : A;
end
B:begin
next_state = in ? B : C;
end
C:begin
next_state = in ? D : A;
end
D:begin
next_state = in ? B : C;
end
endcase
end
always@(*)begin
if(current_state == D)begin
out <= 1'b1;
end
else begin
out <= 1'b0;
end
end
endmodule
和上题一样,只不过加上了时钟,这里注意,这道题目要求异步复位。
module top_module(
input clk,
input in,
input reset,
output out); //
parameter A=2'd0, B=2'd1, C=2'd2, D=2'd3;
reg [1:0] current_state;
reg [1:0] next_state;
always@(posedge clk)begin
if(reset)begin
current_state <= A;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
A:begin
next_state = in ? B : A;
end
B:begin
next_state = in ? B : C;
end
C:begin
next_state = in ? D : A;
end
D:begin
next_state = in ? B : C;
end
endcase
end
always@(*)begin
if(current_state == D)begin
out <= 1'b1;
end
else begin
out <= 1'b0;
end
end
endmodule
和上题相同,只不过这里换成了同步复位。
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
parameter IDLE = 3'd0, SENSOR_1 = 3'd1;
parameter SENSOR_2 = 3'd2, SENSOR_3 = 3'd3;
reg [2:0] current_state;
reg [2:0] next_state;
always@(posedge clk)begin
if(reset)begin
current_state <= 'd0;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
IDLE:begin
case(s)
3'b001:begin
next_state = SENSOR_1;
end
3'b011:begin
next_state = SENSOR_2;
end
3'b111:begin
next_state = SENSOR_3;
end
default:begin
next_state = IDLE;
end
endcase
//next_state = (s == 3'b001) ? SENSOR_1 : IDLE;
end
SENSOR_1:begin
case(s)
3'b001:begin
next_state = SENSOR_1;
end
3'b011:begin
next_state = SENSOR_2;
end
3'b111:begin
next_state = SENSOR_3;
end
default:begin
next_state = IDLE;
end
endcase
//next_state = (s == 3'b011) ? SENSOR_2 : IDLE;
end
SENSOR_2:begin
case(s)
3'b001:begin
next_state = SENSOR_1;
end
3'b011:begin
next_state = SENSOR_2;
end
3'b111:begin
next_state = SENSOR_3;
end
default:begin
next_state = IDLE;
end
endcase
//next_state = (s == 3'b111) ? SENSOR_3 : IDLE;
end
SENSOR_3:begin
case(s)
3'b001:begin
next_state = SENSOR_1;
end
3'b011:begin
next_state = SENSOR_2;
end
3'b111:begin
next_state = SENSOR_3;
end
default:begin
next_state = IDLE;
end
endcase
//next_state = (s == 3'b011) ? SENSOR_2 : ( (s == 3'b001) ? SENSOR_1 : IDLE );
end
default:begin
next_state = IDLE;
end
endcase
end
assign fr3 = (current_state == IDLE);
assign fr2 = (current_state == IDLE || current_state == SENSOR_1);
assign fr1 = (current_state == IDLE || current_state == SENSOR_1 || current_state == SENSOR_2);
//assign dfr = (current_state == SENSOR_2 && next_state == SENSOR_1 || current_state == SENSOR_3 && next_state == SENSOR_1 || current_state == SENSOR_3 && next_state == SENSOR_2);
reg fr3_reg;
reg fr2_reg;
reg fr1_reg;
always@(posedge clk)begin
fr3_reg <= fr3;
end
always@(posedge clk)begin
fr2_reg <= fr2;
end
always@(posedge clk)begin
fr1_reg <= fr1;
end
//assign dfr = ~fr3 & fr3_reg | ~fr2 & fr2_reg | ~fr1 & fr1_reg ? 1'b0 : 1'b1;
always@(*)begin
if(~fr3 & fr3_reg | ~fr2 & fr2_reg | ~fr1 & fr1_reg)begin
dfr = 1'b0;
end
else if(fr3 & ~fr3_reg | fr2 & ~fr2_reg | fr1 & ~fr1_reg)begin
dfr = 1'b1;
end
end
endmodule
/*
//second way
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
*/
这道题目,建议大家认真读几遍题目,博主也是读了几遍题目才弄清楚作者的意图。博主想到的答案是答案一,作者给出的答案是答案二,建议大家使用作者给出的答案,博主的答案太繁琐了,最后还使用了边沿检测来判断dfr,实在是不如作者给出的简洁,不过博主还是厚脸皮地把自己的答案放上去吧,供大家参考。
之后博主会单独出一期边沿检测的相关知识供大家学习,边沿检测的应用实在是太广泛了,不得不重视这部分内容。
今天更新这几道题目吧,重点是one-hot编码的部分,这部分在实际应用以及笔试面试中算是常考题目,包括one-hot编码的优缺点等等,希望大家可以掌握。
https://hdlbits.01xz.net/wiki/Main_Page