之前都是用的一段式状态机,逻辑与输出混在一起,复杂点的就比较吃力了。
所以就开始着手三段式状态机。
组合逻辑与时序逻辑分开,这样就能简单许多了。
但是两者在思考方式上也有着很大的区别。
三段式,分作:状态寄存器,次态组合逻辑,输出逻辑。
以下今天写完的程序。
1 //state register 2 always@(posedge clk) 3 begin 4 if(!rst)begin 5 current <= IDLE; 6 end 7 else begin 8 current <= next; 9 end 10 end 11 //next state logic 12 always@(S_AXIS_tready or run or current) 13 begin 14 case(current) 15 IDLE:if(S_AXIS_tready)begin 16 if(run) next = WRIT; 17 else next = IDLE; 18 end 19 else begin 20 next = IDLE; 21 end 22 WRIT:if(S_AXIS_tready)begin 23 if(run) next = WRIT; 24 else next = IDLE; 25 end 26 else begin 27 if(run) next = WAIT; 28 else next = IDLE; 29 end 30 WAIT:if(S_AXIS_tready)begin 31 if(run) next = WRIT; 32 else next = IDLE; 33 end 34 else begin 35 if(run) next = WAIT; 36 else next = IDLE; 37 end 38 default:next = IDLE; 39 endcase 40 end 41 //output logic 42 always@(posedge clk) 43 begin 44 if(!rst)begin 45 S_AXIS_tvalid <= 1'b0; 46 S_AXIS_tlast <= 1'b0; 47 S_AXIS_tdata <= 32'h00000000; 48 Gdata <= 32'h00000000; 49 end 50 else begin 51 case(next) 52 IDLE:begin 53 S_AXIS_tlast <= 1'b0; 54 S_AXIS_tvalid <= 1'b0; 55 S_AXIS_tdata <= 32'h00000000; 56 Gdata <= 32'h00000000; 57 end 58 WRIT:begin 59 S_AXIS_tvalid <= 1'b1; 60 if(S_AXIS_tdata <= 32'h3ff)begin 61 Gdata <= Gdata + 1'b1; 62 S_AXIS_tdata <= Gdata; 63 end 64 else begin 65 S_AXIS_tdata <= S_AXIS_tdata;//32'h00000000; 66 S_AXIS_tlast <= 1'b1; 67 end 68 end 69 WAIT:begin 70 S_AXIS_tlast <= 1'b0; 71 S_AXIS_tvalid <= 1'b0; 72 S_AXIS_tdata <= S_AXIS_tdata; 73 end 74 default:begin 75 S_AXIS_tvalid <= 1'bx; 76 S_AXIS_tlast <= 1'bx; 77 S_AXIS_tdata <= 32'hx; 78 end 79 endcase 80 end 81 end
下面是改成三段式前的代码
1 always@(posedge clk) begin 2 if(!rst) begin 3 S_AXIS_tvalid <= 1'b0; 4 S_AXIS_tlast <= 1'b0; 5 S_AXIS_tdata <= 32'd0; 6 state <= IDLE; 7 end 8 else begin 9 case(state) //状态机 10 IDLE: begin // idle 11 if(start_posedge && S_AXIS_tready) begin //启动信号到来且FIFO可写 12 S_AXIS_tvalid <= 1'b1; //设置写FIFO有效 13 state <= WRIT; 14 end 15 else begin 16 S_AXIS_tvalid <= 1'b0; 17 Gdata <= 32'h0; 18 state <= IDLE; 19 end 20 end 21 WRIT:begin 22 if(S_AXIS_tready) begin //FIFO可写 23 Gdata <= Gdata + 1'b1; 24 // S_AXIS_tdata <= Gdata; 25 S_AXIS_tdata <= S_AXIS_tdata; 26 if(S_AXIS_tdata == 32'hfff) begin //判断是否结束 27 S_AXIS_tlast <= 1'b1;//发送最后一个数据 28 state <= WAIT; 29 end 30 else begin//等待数据发完 31 S_AXIS_tlast <= 1'b0; 32 state <= WRIT; 33 end 34 end 35 else begin//等待FIFO可写 36 S_AXIS_tdata <= S_AXIS_tdata; 37 state <= WRIT; 38 end 39 end 40 WAIT:begin 41 if(!S_AXIS_tready) begin //FIFO满则等待 42 S_AXIS_tvalid <= 1'b1; 43 S_AXIS_tlast <= 1'b1; 44 S_AXIS_tdata <= S_AXIS_tdata; 45 state <= WAIT; 46 end 47 else begin //写入结束 48 S_AXIS_tvalid <= 1'b0; 49 S_AXIS_tlast <= 1'b0; 50 S_AXIS_tdata <= 16'd0; 51 state <= IDLE; 52 end 53 end 54 default: state <= IDLE; 55 endcase 56 end 57 end
参考
https://www.cnblogs.com/lifan3a/articles/4583577.html
https://blog.csdn.net/jason_child/article/details/60466050