Finite state machines¶
- yosys> help $fsm¶
- Simulation model (verilog)¶
2681module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); 2682 2683 parameter NAME = ""; 2684 2685 parameter CLK_POLARITY = 1'b1; 2686 parameter ARST_POLARITY = 1'b1; 2687 2688 parameter CTRL_IN_WIDTH = 1; 2689 parameter CTRL_OUT_WIDTH = 1; 2690 2691 parameter STATE_BITS = 1; 2692 parameter STATE_NUM = 1; 2693 parameter STATE_NUM_LOG2 = 1; 2694 parameter STATE_RST = 0; 2695 parameter STATE_TABLE = 1'b0; 2696 2697 parameter TRANS_NUM = 1; 2698 parameter TRANS_TABLE = 4'b0x0x; 2699 2700 input CLK, ARST; 2701 input [CTRL_IN_WIDTH-1:0] CTRL_IN; 2702 output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT; 2703 2704 wire pos_clk = CLK == CLK_POLARITY; 2705 wire pos_arst = ARST == ARST_POLARITY; 2706 2707 reg [STATE_BITS-1:0] state; 2708 reg [STATE_BITS-1:0] state_tmp; 2709 reg [STATE_BITS-1:0] next_state; 2710 2711 reg [STATE_BITS-1:0] tr_state_in; 2712 reg [STATE_BITS-1:0] tr_state_out; 2713 reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in; 2714 reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out; 2715 2716 integer i; 2717 2718 task tr_fetch; 2719 input [31:0] tr_num; 2720 reg [31:0] tr_pos; 2721 reg [STATE_NUM_LOG2-1:0] state_num; 2722 begin 2723 tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num; 2724 tr_ctrl_out = TRANS_TABLE >> tr_pos; 2725 tr_pos = tr_pos + CTRL_OUT_WIDTH; 2726 state_num = TRANS_TABLE >> tr_pos; 2727 tr_state_out = STATE_TABLE >> (STATE_BITS*state_num); 2728 tr_pos = tr_pos + STATE_NUM_LOG2; 2729 tr_ctrl_in = TRANS_TABLE >> tr_pos; 2730 tr_pos = tr_pos + CTRL_IN_WIDTH; 2731 state_num = TRANS_TABLE >> tr_pos; 2732 tr_state_in = STATE_TABLE >> (STATE_BITS*state_num); 2733 tr_pos = tr_pos + STATE_NUM_LOG2; 2734 end 2735 endtask 2736 2737 always @(posedge pos_clk, posedge pos_arst) begin 2738 if (pos_arst) begin 2739 state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2740 for (i = 0; i < STATE_BITS; i = i+1) 2741 if (state_tmp[i] === 1'bz) 2742 state_tmp[i] = 0; 2743 state <= state_tmp; 2744 end else begin 2745 state_tmp = next_state; 2746 for (i = 0; i < STATE_BITS; i = i+1) 2747 if (state_tmp[i] === 1'bz) 2748 state_tmp[i] = 0; 2749 state <= state_tmp; 2750 end 2751 end 2752 2753 always @(state, CTRL_IN) begin 2754 next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2755 CTRL_OUT <= 'bx; 2756 // $display("---"); 2757 // $display("Q: %b %b", state, CTRL_IN); 2758 for (i = 0; i < TRANS_NUM; i = i+1) begin 2759 tr_fetch(i); 2760 // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i); 2761 casez ({state, CTRL_IN}) 2762 {tr_state_in, tr_ctrl_in}: begin 2763 // $display("-> %b %b <- MATCH", state, CTRL_IN); 2764 {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out}; 2765 end 2766 endcase 2767 end 2768 end 2769 2770endmodule