FSM Design T1
用Verilog描述下图所示状态转移图对应的有限状态机,其中,状态右边的数值是当前状态的输出。注:S0~S3为状态机的状态名,状态机的输入信号名为IN,输出信号名为OUT,请同学们按照此命名编写Verilog代码。
1. Analysis
根据图中所示Moore型状态机,可知OUT输出仅与当前状态有关,该状态机共有4个状态(S0/Dout=5、S1/Dout=8、S2/Dout=12、S3/Dout=14)。本题需要利用parameter关键字设置4个状态,端口需要包含CLK时钟、RSTN复位、IN输入、OUT输出等。本文设计的Moore FSM含有三个always过程块,分别实现状态计算逻辑、输出计算逻辑、状态转移逻辑。
2. FSM Diagram
3. Port List
Port Name | Attribute | Width | Meaning |
---|---|---|---|
clock | input | 1 bit | 时钟信号 |
reset | input | 1 bit | 复位信号 |
in | input | 2 bits | 状态机输入信号IN |
out | output | 4 bits | 状态机输出信号OUT |
4. Verilog Code
`timescale 1ns/1ps
module exercise1 (CLK, RST, IN, OUT);
input wire CLK;
input wire RST;
input wire [1:0] IN;
output reg [3:0] OUT;
reg [1:0] cs;
reg [1:0] ns;
parameter s0 = 2'b00;
parameter s1 = 2'b01;
parameter s2 = 2'b10;
parameter s3 = 2'b11;
always @ (posedge CLK or negedge RST) begin
if (!RST) begin
cs <= s0;
end
else begin
cs <= ns;
end
end
always @ (*) begin
case (cs)
s0: begin
if (IN == 2'b00) begin
ns = s0;
end
else begin
ns = s1;
end
end
s1: begin
if (IN == 2'b00) begin
ns = s1;
end
else begin
ns = s2;
end
end
s2: begin
if (IN == 2'b11) begin
ns = s0;
end
else begin
ns = s3;
end
end
s3: begin
if (IN == 2'b11) begin
ns = s3;
end
else begin
ns = s0;
end
end
default: ns = s0;
endcase
end
always @ (*) begin
case (cs)
s0: OUT = 4'd5;
s1: OUT = 4'd8;
s2: OUT = 4'd12;
s3: OUT = 4'd14;
default: OUT = 4'd5;
endcase
end
endmodule
5. Testbench Code
`timescale 1ns/1ps
module exercise1_test;
reg CLK;
reg RST;
reg [1:0] IN;
wire [3:0] OUT;
parameter half_cycle = 5;
parameter s0 = 2'b00;
parameter s1 = 2'b01;
parameter s2 = 2'b10;
parameter s3 = 2'b11;
exercise1 exercise1_inst (
.CLK(CLK),
.RST(RST),
.IN(IN),
.OUT(OUT)
);
initial begin
CLK = 0;
forever begin
CLK = # half_cycle ~ CLK;
end
end
initial begin
RST = 1;
# (1 * half_cycle) RST = 0;
# (2 * half_cycle) RST = 1;
end
initial begin
# (2 * half_cycle) IN = 2'b00;
# (2 * half_cycle) IN = 2'b01;
# (2 * half_cycle) IN = 2'b01;
# (2 * half_cycle) IN = 2'b00;
# (2 * half_cycle) IN = 2'b11;
# (2 * half_cycle) IN = 2'b11;
# (2 * half_cycle) IN = 2'b00;
end
initial begin
# (50 * half_cycle) $finish;
end
initial begin
$fsdbDumpfile("./verdiFsdb/exercise1.fsdb");
$fsdbDumpvars(0);
end
endmodule