根据书中讲解,用Verilog实现了功能,经过简单的仿真,状态机可以正常工作。
文章附图摘自《FSM-based Digitial Design Using Verilog HDL》
1 系统框图
状态机控制下将计数器的数值并行加载到移位寄存器中,并串行发送出去;
2 状态转移图
3. 状态机代码
module tx_fsm(//input
rst,st,re,done,clk,
//output
CB,RC,LD);
input clk;
input rst; // reset of fsm
input st; // start of FSM
input re; // shift done
input done;// counter run out
output CB;//clock counter
output RC;//reset counter
output LD;//loading default counter
parameter S0= 3'b000;
parameter S1= 3'b010;
parameter S2= 3'b110;
parameter S3= 3'b100;
parameter S4= 3'b101;
parameter S5= 3'b111;
parameter S6= 3'b011;
//state diagram
//
reg [2:0] next_state;
reg [2:0] state;
always @(posedge clk or negedge rst) begin
if (~rst)
state <= 3'b000;
else
state <= next_state;
end
always @(*) begin
case(state)
S0: begin // st assert as high, then FSM starts
if (st)
next_state = S1;
else
next_state = S0;
end
S1: begin // release reset from binary counter
next_state = S2;
end
S2: begin // load parallel data into shift reg
next_state = S3;
end
S3: begin
next_state = S4;
end
S4: begin
if (re)
next_state =S5;
else
next_state =S4;
end
S5: begin
if (done)
next_state = S6;
else
next_state = S1;
end
S6: begin
if (st)
next_state = S6;
else
next_state = S0;
end
default: next_state =S0;
endcase
end
assign RC = |state;
assign LD = ~state[2]|~state[1]|state[0];// /LD = AB/C
assign CB = state[2]&~state[1]&~state[0];
endmodule
- 移位寄存器和计数器
module shift_regs (//input
P,Ld,rst,clk,
//output
TX,RE);
input [3:0] P;
input Ld;
input rst;
input clk;
output TX;
output RE;
reg [3:0] shift_regs;
reg [3:0] shift_cnt;
always @(posedge clk or negedge rst) begin
if(~rst) begin
shift_regs <= 4'b0000;
shift_cnt <= 4'b0000;
end else if (~Ld)
shift_regs <= P;
else begin
shift_regs <= {shift_regs[2:0],1'b0};
if(shift_cnt<4'b1000)
shift_cnt <= shift_cnt + 1;
else
shift_cnt <= 4'b0000;
end
end
assign TX = shift_regs[3];
assign RE = shift_cnt[3];
endmodule
module binary_cnt (//input
clk,rst,
//output
q);
input clk;
input rst;
output reg [3:0] q;
always @(posedge clk or negedge rst) begin
if (~rst)
q<=4'b0000;
else
q<=q+1;
end
endmodule
- top and tb
module tx_top (// input
clk,rst,st,
//output
TX);
input clk;
input rst;
input st;
output TX;
wire done;
wire [3:0] q;
assign done = q[3]&q[2]&q[1]&q[0];
wire RE;
wire clk_bin;
wire RC;
wire LD;
// instantiation
tx_fsm u_tx_fsm (
//input
.rst(rst),
.st(st),
.re(RE),
.done(done),
.clk(clk),
//output
.CB(clk_bin),
.RC(RC),
.LD(LD));
binary_cnt u_bin_cnt (
.rst(RC),
.clk(clk_bin),
.q(q));
shift_regs u_sft_regs (
.Ld(LD),
.clk(clk),
.rst(RC),
.P(q),
.RE(RE),
.TX(TX));
endmodule
module tb();
reg clk;
reg rst;
reg st;
wire TX;
initial begin
clk = 0;
rst = 0;
st = 0;
// rstn_r = 0;
// resume = 0;
// seed = 0;
// enable = 0;
#20 rst = 1;
#40 st =1;
#2000 $finish;
end
always #5 clk =~clk;
tx_top u_tx_top (// input
.clk(clk),
.rst(rst),
.st(st),
//output
.TX(TX));
endmodule
- waveform