之前都是用的一段式状态机,逻辑与输出混在一起,复杂点的就比较吃力了。
所以就开始着手三段式状态机。
组合逻辑与时序逻辑分开,这样就能简单许多了。
但是两者在思考方式上也有着很大的区别。
三段式,分作:状态寄存器,次态组合逻辑,输出逻辑。
以下今天写完的程序。
//state register
always@(posedge clk)
begin
if(!rst)begin
current <= IDLE;
end
else begin
current <= next;
end
end
//next state logic
always@(S_AXIS_tready or run or current)
begin
case(current)
IDLE:if(S_AXIS_tready)begin
if(run) next = WRIT;
else next = IDLE;
end
else begin
next = IDLE;
end
WRIT:if(S_AXIS_tready)begin
if(run) next = WRIT;
else next = IDLE;
end
else begin
if(run) next = WAIT;
else next = IDLE;
end
WAIT:if(S_AXIS_tready)begin
if(run) next = WRIT;
else next = IDLE;
end
else begin
if(run) next = WAIT;
else next = IDLE;
end
default:next = IDLE;
endcase
end
//output logic
always@(posedge clk)
begin
if(!rst)begin
S_AXIS_tvalid <= 'b0;
S_AXIS_tlast <= 'b0;
S_AXIS_tdata <= 'h00000000;
Gdata <= 'h00000000;
end
else begin
case(next)
IDLE:begin
S_AXIS_tlast <= 'b0;
S_AXIS_tvalid <= 'b0;
S_AXIS_tdata <= 'h00000000;
Gdata <= 'h00000000;
end
WRIT:begin
S_AXIS_tvalid <= 'b1;
if(S_AXIS_tdata <= 'h3ff)begin
Gdata <= Gdata + 'b1;
S_AXIS_tdata <= Gdata;
end
else begin
S_AXIS_tdata <= S_AXIS_tdata;//32'h00000000;
S_AXIS_tlast <= 'b1;
end
end
WAIT:begin
S_AXIS_tlast <= 'b0;
S_AXIS_tvalid <= 'b0;
S_AXIS_tdata <= S_AXIS_tdata;
end
default:begin
S_AXIS_tvalid <= 'bx;
S_AXIS_tlast <= 'bx;
S_AXIS_tdata <= 'hx;
end
endcase
end
end
下面是改成三段式前的代码
always@(posedge clk) begin
if(!rst) begin
S_AXIS_tvalid <= 'b0;
S_AXIS_tlast <= 'b0;
S_AXIS_tdata <= 'd0;
state <= IDLE;
end
else begin
case(state) //状态机
IDLE: begin // idle
if(start_posedge && S_AXIS_tready) begin //启动信号到来且FIFO可写
S_AXIS_tvalid <= 'b1; //设置写FIFO有效
state <= WRIT;
end
else begin
S_AXIS_tvalid <= 'b0;
Gdata <= 'h0;
state <= IDLE;
end
end
WRIT:begin
if(S_AXIS_tready) begin //FIFO可写
Gdata <= Gdata + 'b1;
// S_AXIS_tdata <= Gdata;
S_AXIS_tdata <= S_AXIS_tdata;
if(S_AXIS_tdata == 'hfff) begin //判断是否结束
S_AXIS_tlast <= 'b1;//发送最后一个数据
state <= WAIT;
end
else begin//等待数据发完
S_AXIS_tlast <= 'b0;
state <= WRIT;
end
end
else begin//等待FIFO可写
S_AXIS_tdata <= S_AXIS_tdata;
state <= WRIT;
end
end
WAIT:begin
if(!S_AXIS_tready) begin //FIFO满则等待
S_AXIS_tvalid <= 'b1;
S_AXIS_tlast <= 'b1;
S_AXIS_tdata <= S_AXIS_tdata;
state <= WAIT;
end
else begin //写入结束
S_AXIS_tvalid <= 'b0;
S_AXIS_tlast <= 'b0;
S_AXIS_tdata <= 'd0;
state <= IDLE;
end
end
default: state <= IDLE;
endcase
end
end
参考
https://www.cnblogs.com/lifan3a/articles/4583577.html
https://blog.csdn.net/jason_child/article/details/60466050