SystemVerilog FSM中重复SPI读取状态能否封装为可综合Task?
用SystemVerilog Task封装SPI字节读取逻辑实现可复用状态机(Gowin FPGA适配)
完全可以用SystemVerilog Task封装你的SPI字节读取逻辑,Gowin IDE支持符合规则的可综合Task,这种写法能直接替代原来的RXSPIBITS状态+ReturnState机制,让状态机结构更简洁、复用性更强。
一、可综合的GetSPIByte Task实现
Gowin对可综合Task的要求是:不能包含#延迟、fork-join、wait(除同步时钟沿检测)等不可综合语句,逻辑必须和模块的时钟/复位同步。下面是适配你需求的Task:
task automatic GetSPIByte( input logic sck_rising, input logic mosi, output logic [7:0] rx_byte, output logic byte_done ); static logic [2:0] bit_cnt; // 静态变量保存计数,替代原BitCnt寄存器 static logic [7:0] rx_shift; // 静态变量保存移位数据,替代原RxBits寄存器 if (sck_rising) begin rx_shift <= {rx_shift[6:0], mosi}; bit_cnt <= bit_cnt + 1'b1; if (bit_cnt == 3'd7) begin rx_byte <= rx_shift; byte_done <= 1'b1; bit_cnt <= 3'd0; // 完成后复位计数,准备下一次调用 end else begin byte_done <= 1'b0; end end else begin byte_done <= 1'b0; end endtask
说明:
- 使用
static变量在Task调用间保持状态,替代原来模块级的BitCnt和RxBits寄存器byte_done作为完成标志,通知调用状态字节读取完成automatic关键字确保Task在多状态调用时不会出现状态冲突(Gowin推荐添加)
二、修改后的状态机实现
原来的GetCommand、GetParams状态可以直接调用Task,不需要单独的RXSPIBITS状态和returnstate变量:
typedef enum logic [1:0] { IDLE, GetCommand, GetParams, Execute } state_t; state_t current_state, next_state; logic [7:0] cmd_byte, param_byte; logic cmd_done, param_done; always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) begin current_state <= IDLE; cmd_byte <= 8'd0; param_byte <= 8'd0; end else begin current_state <= next_state; case (current_state) IDLE: begin // 触发条件:比如CS拉低 if (!cs_n) begin next_state <= GetCommand; end end GetCommand: begin // 调用Task读取命令字节 GetSPIByte(SCK_risingedge, mosi, cmd_byte, cmd_done); if (cmd_done) begin next_state <= GetParams; end end GetParams: begin // 调用Task读取参数字节 GetSPIByte(SCK_risingedge, mosi, param_byte, param_done); if (param_done) begin next_state <= Execute; end end Execute: begin // 执行指令逻辑 next_state <= IDLE; end endcase end end
三、Gowin综合器的关键注意事项
- Task不能包含动态行为:禁止使用
#1、wait(!sck)这类非同步逻辑,所有操作必须绑定到时钟沿 - 静态变量的使用:
static变量在Gowin综合中会被综合为寄存器,确保Task调用间的状态保持 - 参数传递方式:推荐用
input/output传递信号,避免直接访问模块内部寄存器(如果需要访问模块信号,用ref类型参数,Gowin支持) - 综合选项配置:在Gowin IDE的综合设置中,确保开启
SystemVerilog Support(默认已开启),无需额外配置即可综合此类Task
四、对比原实现的优势
- 去掉了
RXSPIBITS状态和returnstate变量,状态机分支更清晰 - 读取逻辑集中在Task中,修改时只需维护一处代码
- 各状态调用逻辑一致,降低了出错概率
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

