module cpu_model (pclk, prst_n, psel, 
pwrite, paddr, pwdata, penable, pready); 

input pclk, prst_n;
output psel, pwrite, penable;
output [2:0] paddr;
output [7:0] pwdata;

input pready;

reg processing;

always @(negedge prst_n) begin
   psel = 0;
   pwrite = 0; 
   penable = 0;
   paddr = 0;
   pwdata = 0;
   processing = 0;   
end

task MOVT;
input [2:0] addr;
input [7:0] data;

  begin
  processing = 1;
$display(“CPU are stating the write to addr = %h, data = %h”, addr, data);
  @(posedge clk);
  #1;
  PSEL = 1;
  PADDR = addr;
  PWDATA = data;
  PENABLE = 0;
  PWRITE = 1;
@(posedge clk);
#1;
  PENABLE = 1;
@(posedge clk);
If (~PREADY)  begin// IP DECODE  is busy
@(posedge PREADY); // waiting for IP DECODE is ready
#1;
@(posedge clk);
end
#1;
  PSEL = 0;
  PADDR = 3'b000;
  PWDATA = 8'h00;
  PENABLE = 0;
  PWRITE = 0;
  
$display(“CPU completes the write transfer to addr =%h”, addr);
  processing = 0;
  end
Endtask
endmodule

module top();
cpu_model … CPU;
ip_decode ….IP;

// Clk generator;

// Reset generator;
reg [2:0] addr, addr_tmp;
reg [7:0] data, reg_tmp;

initial
begin
  addr = $random();
  data = $random();

  forever # 10; begin 
    CPU.MOVT(addr, data);
    If (CPU.processing == 1) begin
	  addr_tmp = addr;
    end
    If (CPU.processing == 0) begin
      case (addr_tmp)
        3'b000: reg_tmp = IP.regA;
		3'b001: reg_tmp = IP.regB;
		3'b010: reg_tmp = IP.regC;
		3'b011: reg_tmp = IP.regD;
		3'b100: reg_tmp = IP.regE;
		3'b101: reg_tmp = IP.regF;
		3'b110: reg_tmp = IP.regG;
		3'b111: reg_tmp = IP.regH;
      endcase
      if (reg_tmp == data) 
        $display(“Reg at address = %h is OK”, addr_tmp)
      else begin
        $display(“At time = %t, Reg at address = %h is not OK”, $time, addr_tmp)
		$finish(); 
	  end	
    end
	   addr = $random();
	   data = $random(); 
  end
  
  initial
    begin
	  #10000;
	  $finish();
	end
  
endmoule
