3/17/2007

FSM Coding Convention

Two-always blocks with continuous assignment outputs:

module fsm1a (ds, rd, go, ws, clk, rst_n);
 output ds, rd;
 input go, ws;
 input clk, rst_n;
 parameter [1:0] IDLE = 2'b00,
          READ = 2'b01,
          DLY = 2'b10,
          DONE = 2'b11;
 reg [1:0] state, next;

 always @(posedge clk or negedge rst_n)
  if (!rst_n) state <= IDLE;
  else state <= next;

 always @(state or go or ws) begin
  next = 2'bx;
  case (state)
  IDLE: if (go) next = READ;
     else next = IDLE;
  READ: next = DLY;
  DLY: if (ws) next = READ;
     else next = DONE;
  DONE: next = IDLE;
  endcase
 end

 assign rd = (state==READ state==DLY);
 assign ds = (state==DONE);
endmodule

Two-always blocks with combined output assignments:

module fsm1 (ds, rd, go, ws, clk, rst_n);
 output ds, rd;
 input go, ws;
 input clk, rst_n;
 reg ds, rd;
 parameter [1:0] IDLE = 2'b00,
          READ = 2'b01,
          DLY = 2'b10,
          DONE = 2'b11;
 reg [1:0] state, next;

 always @(posedge clk or negedge rst_n)
  if (!rst_n) state <= IDLE;
  else state <= next;

 always @(state or go or ws) begin
  next = 2'bx;
  ds = 1'b0;
  rd = 1'b0;
  case (state)
   IDLE: if (go) next = READ;
      else next = IDLE;
   READ: begin rd = 1'b1;
          next = DLY;
      end
   DLY: begin rd = 1'b1;
         if (ws) next = READ;
         else next = DONE;
      end
   DONE: begin ds = 1'b1;
       next = IDLE;
      end
  endcase
 end
endmodule

Three-always block coding style

module fsm1b (ds, rd, go, ws, clk, rst_n);
 output ds, rd;
 input go, ws;
 input clk, rst_n;
 reg ds, rd;
 parameter [1:0] IDLE = 2'b00,
          READ = 2'b01,
          DLY = 2'b10,
          DONE = 2'b11;
 reg [1:0] state, next;

 always @(posedge clk or negedge rst_n)
  if (!rst_n) state <= IDLE;
  else state <= next;

 always @(state or go or ws) begin
  next = 2'bx;
  case (state)
  IDLE: if (go) next = READ;
     else next = IDLE;
  READ: next = DLY;
  DLY: if (ws) next = READ;
     else next = DONE;
  DONE: next = IDLE;
  endcase
 end

 always @(posedge clk or negedge rst_n)
  if (!rst_n) begin
   ds <= 1'b0;
   rd <= 1'b0;
  end
  else begin
   ds <= 1'b0;
   rd <= 1'b0;
   case (state)
   IDLE: if (go) rd <= 1'b1;
   READ: rd <= 1'b1;
   DLY: if (ws) rd <= 1'b1;
      else ds <= 1'b1;
   endcase
  end
 endmodule

No comments: