`timescale 1ns/1ps
module sram_controller_tb;
  logic clk=0,rst_n=0,req=0,write=0;logic[2:0]addr=0;logic[7:0]wdata=0;logic ready,rvalid;logic[7:0]rdata;
  logic[7:0]scoreboard[0:7];logic pending=0,pending_write=0,accepted_now;logic[2:0]pending_addr=0;int cycle=0,checks=0,failures=0,i;
  sram_controller dut(.*);always #5 clk=~clk;
  task automatic transact(input logic wr,input logic[2:0]a,input logic[7:0]d);begin while(!ready)@(negedge clk);req=1;write=wr;addr=a;wdata=d;@(negedge clk);req=0;while(!rvalid)@(negedge clk);end endtask
  always @(posedge clk)begin
    cycle=cycle+1;accepted_now=ready&&req;#1;
    $display("TRACE,%0d,%0b,%0b,%0b,%0b,%0d,%0h,%0h,%0b,%0h",cycle,rst_n,req,ready,write,addr,wdata,rdata,rvalid,rdata);
    if(rst_n)begin
      if(pending)begin checks=checks+1;if(!rvalid)begin $display("ASSERT_FAIL,response_latency,cycle=%0d",cycle);failures=failures+1;end if(!pending_write&&rdata!==scoreboard[pending_addr])begin $display("ASSERT_FAIL,read_data,cycle=%0d,expected=%0h,actual=%0h",cycle,scoreboard[pending_addr],rdata);failures=failures+1;end end
      pending=accepted_now;pending_write=write;pending_addr=addr;if(accepted_now&&write)scoreboard[addr]=wdata;
    end
  end
  initial begin for(i=0;i<8;i=i+1)scoreboard[i]=0;$dumpfile("results/sram_controller.vcd");$dumpvars(0,sram_controller_tb);repeat(2)@(negedge clk);rst_n=1;
    transact(1,3,8'h5a);transact(0,3,0);transact(1,6,8'hc3);transact(0,6,0);transact(0,1,0);transact(1,3,8'ha5);transact(0,3,0);repeat(2)@(negedge clk);
    if(failures==0)$display("TEST_PASS,checks=%0d",checks);else $display("TEST_FAIL,failures=%0d",failures);$finish;end
endmodule
