0
votes

I want to write a synthesizable state machine that read/write wishbone commands in an ordered sequence.

Currently I defined some verilog macros :

`define WB_READ(READ_ADDR) \
        begin \
        wb_addr_o <= UART_DIV;\
        wb_stb_o  <= 1'b1; wb_cyc_o  <= 1'b1; wb_we_o <= 1'b0; end

`define WB_WRITE(WR_ADDR, WVALUE) \
        begin \
        wb_addr_o <= WR_ADDR;\
        wb_wdat_o <= WVALUE;\
        wb_stb_o  <= 1'b1; wb_cyc_o  <= 1'b1; wb_we_o <= 1'b1; end\

`define WB_NOPE \
        begin\
        wb_stb_o  <= 1'b0; wb_cyc_o  <= 1'b0; wb_we_o <= 1'b0; end

And used in in my FSM process :

  always @(posedge clk or posedge rst)
    if(rst) begin
      count <= 8'h00; 
      wb_addr_o <= 8'h00;
      wb_wdat_o <= 8'h00;
      wb_stb_o  <= 1'b0; 
      wb_cyc_o  <= 1'b0; 
      wb_we_o   <= 1'b0; 
    end
    else begin
        case(count)
            {7'h01, 1'b1}: `WB_READ(UARD_DIV)
            {7'h02, 1'b1}: `WB_READ(UARD_DIV)
            {7'h03, 1'b1}: `WB_WRITE(UART_LCR, 8'h60)
            {7'h04, 1'b1}: `WB_WRITE(UART_DIV, 8'h01) 
            {7'h05, 1'b1}: `WB_WRITE(UART_THR, 8'h55) 
            default: `WB_NOPE
        endcase
        if (count < {7'h06, 1'b1})
            count <= count + 1;
    end

Each time count is even, WB_NOPE state is «executed» and each time it's odd, the command given is executed.

That works in simulation but if I want to add a command in the middle of state machine, I have to re-indent all {7'hxx, 1'b1} states. and increment the if(count < ...) at the end.

Is somebody know how to improve this (with macro ?) to avoid it ?

1

1 Answers

1
votes

You can just use an integer value in the case statements, and increment it for each step. Here's a slightly stripped back version of your code that does what you want (or at least something close enough that you can fix it :-) )

module testcase (input logic clk,input logic rst);

enum logic [1:0] { READ,WRITE,NOP } op;
logic [7:0] count;

`define WB_READ  begin op <= READ; end
`define WB_WRITE begin op <= WRITE; end
`define WB_NOPE  begin op <= NOP; end
logic [6:0] fsm_step_number;

  always @(posedge clk or posedge rst)
    if(rst) begin
      count <= 8'h00; 
      op <= NOP;
    end
    else begin
        fsm_step_number=1;
        case(count)
            {(fsm_step_number++), 1'b1}: `WB_READ
            {(fsm_step_number++), 1'b1}: `WB_READ
            {(fsm_step_number++), 1'b1}: `WB_WRITE
            {(fsm_step_number++), 1'b1}: `WB_WRITE
            {(fsm_step_number++), 1'b1}: `WB_WRITE
            default: `WB_NOPE
        endcase
        if (count < {(fsm_step_number), 1'b1})
            count <= count + 1;
    end

    assert

endmodule