module march_cminus_bist_tb;
 logic clk=0,rst_n=0,start=0,busy,done,fail,mem_re,mem_we,expected_bit;
 logic [7:0] mismatch_count,mem_wdata,mem_rdata; logic [2:0] mem_addr,element; logic [7:0] mem [0:7];
 integer fault_mode=0,case_id=0,cycle=0,accesses=0,trace_mismatches=0,i;
 localparam FAULT_ADDR=3,FAULT_BIT=2;
 march_cminus_bist dut(.*); always #5 clk=~clk;
 always_comb begin mem_rdata=mem[mem_addr]; if(mem_addr==FAULT_ADDR) begin if(fault_mode==1) mem_rdata[FAULT_BIT]=0; if(fault_mode==2) mem_rdata[FAULT_BIT]=1; end end
 always_ff @(posedge clk) if(mem_we) begin mem[mem_addr]<=mem_wdata; if(mem_addr==FAULT_ADDR&&fault_mode==1) mem[mem_addr][FAULT_BIT]<=0; if(mem_addr==FAULT_ADDR&&fault_mode==2) mem[mem_addr][FAULT_BIT]<=1; end
 always @(posedge clk) if(rst_n&&(mem_re||mem_we)) begin
  cycle=cycle+1; accesses=accesses+1; if(mem_re&&(mem_rdata!=={8{expected_bit}})) trace_mismatches=trace_mismatches+1;
  $display("TRACE,%0d,%0d,%0d,%0d,%0d,%s,%0d,%02x,%02x,%0d",case_id,cycle,element,(element==3||element==4)?0:1,mem_addr,mem_re?"READ":"WRITE",expected_bit,mem_re?mem_rdata:mem_wdata,mem_re?{8{expected_bit}}:mem_wdata,mem_re&&(mem_rdata!=={8{expected_bit}}));
 end
 task run_case(input integer mode); begin
  fault_mode=mode; case_id=mode; cycle=0; accesses=0; trace_mismatches=0; for(i=0;i<8;i=i+1) mem[i]=8'hxx;
  rst_n=0; repeat(2) @(posedge clk); rst_n=1; @(posedge clk); start=1; @(posedge clk); start=0; wait(done); #1;
  $display("SUMMARY,%0d,%0d,%0d,%0d,%0d",case_id,accesses,trace_mismatches,fail,mismatch_count);
  if(accesses!=80) $fatal(1,"expected 80 accesses, got %0d",accesses);
  if(mode==0&&(fail||mismatch_count!=0)) $fatal(1,"fault-free case failed");
  if(mode!=0&&(!fail||mismatch_count==0)) $fatal(1,"injected fault not detected");
  @(posedge clk);
 end endtask
 initial begin $dumpfile("march_cminus_bist.vcd"); $dumpvars(0,march_cminus_bist_tb); run_case(0); run_case(1); run_case(2); $display("PASS,March_Cminus,3,3"); $finish; end
endmodule
