FPGA之有限状态机
独热码编程例:
module fsm(clock,reset,a,f,g);
input clock,reset;
input a;
output f,g;
reg f,g;
reg [3:0]state;
parameter idle=4'b0000,
start=4'b0010,
stop=4'b0100,
clear=4'b1000;
always@(posedge clock)
if(!reset) begin
state=idle;
f<=0;
g<=0;
end
else case(state)
idle: begin
if(a) begin
state<=1;
g<=0;
end
else state<=idle;
end
start:begin
if(!a) state<=stop;
else state<=start;
end
stop: begin
if(a) begin
state<=clear;
f<=1;
end
else state<=stop;
end
clear:begin
if(!a) begin
state<=idle;
f<=0;
g<=1;
end
else state<=clear;
end
default: state<=idle;
endcase
endmodule
Other method to write this code:
module fsm(clock,reset,a,f,g);
inpout clock,reset,a;
output f,g;
reg [1:0] state;
wire [1:0] nextstate;
parameter
idle=2'b00, start=2'b01;
stop=2'b10,clear=2'b11;
always@(posedge clock)
if(!reset) begin
state<=idle;
end
else state<=nextstate;
assign nextstate=
(state==idle) ? (a ? start : idle) :
(state==start) ? (!a ? stop : start):
(state==stop) ? (a ? clear : stop) :
(state==clear) ?(!a ? idle : clear) : idle;
assign f=((state==stop)&&a);
assign g=((state==clear)&&(!a || !reset))
endmodule
combine posedge always module with voltage always module
wire nextstate;
always@(posedge clock)
if(!reset) begin
state<=idle;
f<=0;
g<=0;
end
else state<=nextstate;
always@(a or state)
f=0;
g=0;
if(state==idle)
if(a) nextstate=start;
else nextstate=idle;
else if(state==start)
if(!a) nextstate=stop;
else nextstate=start;
else if(state==stop)
if(a) begin
nextstate=clear;
f=1;
end
else nextstate=stop;
else if(state==clear)
if(a) nextstate=clear;
else begin
nextstate=idle;
f=0;
g=1;
end
else default nextstate=idle;
有限状态机一般步骤:
1.逻辑关系转为状态转换图或者状态转换表;
2.状态编码,Gary码,独热码之类;
3.选定触发器的类型(电平出发还是上升沿或下降沿出触发),并求出状态方程,驱动方程,输出方程;
4.按照方程得出逻辑图;
Carry out a simple processor
module sprocessor(instr, out);// instr 17,16bit choose mode;15-8,data one;7:0;data two;
input [17:0]instr;
output [8:0]out;
reg [8:0]out;
reg fun;
reg [7:0]opr1;
reg [7:0]opr2;
function [16:0]mount;
input [17:0]instr;
reg [1:0]fun_how;
reg [7:0]opr1;
reg [7:0]opr2;
reg ch;
begin
fun_how=instr[17:16];
opr2=instr[7:0];
case(fun_how)
2'b00: begin
ch=1;
opr1=instr[15:8];
end
2'b01: begin
ch=0;
opr1=instr[15:8];
end
2'b10: begin
ch=1;
opr1=1;
end
2'b11: begin
ch=0;
opr1=1;
end
endcase
mount={ch,opr1,opr2};
end
endfunction
always@(instr)
begin
{fun,opr1,opr2}=mount(instr);
if(fun==1) out=opr1+opr2;
else out=opr1-opr2;
end
endmodule