module march_cminus_bist #(parameter ADDR_W=3, DATA_W=8)(
 input logic clk,rst_n,start, output logic busy,done,fail,
 output logic [7:0] mismatch_count, output logic mem_re,mem_we,
 output logic [ADDR_W-1:0] mem_addr, output logic [DATA_W-1:0] mem_wdata,
 input logic [DATA_W-1:0] mem_rdata, output logic [2:0] element, output logic expected_bit);
 typedef enum logic [2:0] {IDLE,M0_W0,M1_R0W1,M2_R1W0,M3_R0W1,M4_R1W0,M5_R0,DONE} state_t;
 state_t state; logic phase; logic [ADDR_W-1:0] addr;
 always_comb begin
  busy=(state!=IDLE)&&(state!=DONE); done=(state==DONE); mem_re=0; mem_we=0; mem_wdata='0; mem_addr=addr; element=0; expected_bit=0;
  case(state)
   M0_W0: begin element=0; mem_we=1; mem_wdata='0; end
   M1_R0W1: begin element=1; expected_bit=0; if(!phase) mem_re=1; else begin mem_we=1; mem_wdata='1; end end
   M2_R1W0: begin element=2; expected_bit=1; if(!phase) mem_re=1; else begin mem_we=1; mem_wdata='0; end end
   M3_R0W1: begin element=3; expected_bit=0; if(!phase) mem_re=1; else begin mem_we=1; mem_wdata='1; end end
   M4_R1W0: begin element=4; expected_bit=1; if(!phase) mem_re=1; else begin mem_we=1; mem_wdata='0; end end
   M5_R0: begin element=5; expected_bit=0; mem_re=1; end
   default: ;
  endcase
 end
 always_ff @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin state<=IDLE; phase<=0; addr<='0; fail<=0; mismatch_count<=0; end
  else case(state)
   IDLE: if(start) begin state<=M0_W0; phase<=0; addr<='0; fail<=0; mismatch_count<=0; end
   M0_W0: if(addr=={ADDR_W{1'b1}}) begin state<=M1_R0W1; addr<='0; phase<=0; end else addr<=addr+1'b1;
   M1_R0W1: if(!phase) begin if(mem_rdata!={DATA_W{1'b0}}) begin fail<=1; mismatch_count<=mismatch_count+1'b1; end phase<=1; end else begin phase<=0; if(addr=={ADDR_W{1'b1}}) begin state<=M2_R1W0; addr<='0; end else addr<=addr+1'b1; end
   M2_R1W0: if(!phase) begin if(mem_rdata!={DATA_W{1'b1}}) begin fail<=1; mismatch_count<=mismatch_count+1'b1; end phase<=1; end else begin phase<=0; if(addr=={ADDR_W{1'b1}}) begin state<=M3_R0W1; addr<={ADDR_W{1'b1}}; end else addr<=addr+1'b1; end
   M3_R0W1: if(!phase) begin if(mem_rdata!={DATA_W{1'b0}}) begin fail<=1; mismatch_count<=mismatch_count+1'b1; end phase<=1; end else begin phase<=0; if(addr=='0) begin state<=M4_R1W0; addr<={ADDR_W{1'b1}}; end else addr<=addr-1'b1; end
   M4_R1W0: if(!phase) begin if(mem_rdata!={DATA_W{1'b1}}) begin fail<=1; mismatch_count<=mismatch_count+1'b1; end phase<=1; end else begin phase<=0; if(addr=='0) begin state<=M5_R0; addr<='0; end else addr<=addr-1'b1; end
   M5_R0: begin if(mem_rdata!={DATA_W{1'b0}}) begin fail<=1; mismatch_count<=mismatch_count+1'b1; end if(addr=={ADDR_W{1'b1}}) state<=DONE; else addr<=addr+1'b1; end
   DONE: state<=IDLE;
   default: state<=IDLE;
  endcase
 end
endmodule
