|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | import tlul_pkg::*; | 
|  | import trial1_reg_pkg::*; | 
|  |  | 
|  | module trial1_test ( | 
|  | input                   clk, | 
|  | input                   rst_n, | 
|  |  | 
|  | output tl_h2d_t         tl_h2d, | 
|  | input  tl_d2h_t         tl_d2h, | 
|  |  | 
|  | input  trial1_reg2hw_t  reg2hw, | 
|  | output trial1_hw2reg_t  hw2reg | 
|  | ); | 
|  |  | 
|  | int errorcount = 0; | 
|  | logic DEBUG = 1'b1; | 
|  | // for now always accept read responses | 
|  | assign  tl_h2d.d_ready = 1'b1; | 
|  |  | 
|  | task automatic send_wr ( | 
|  | input bit [11:0] waddr, | 
|  | input bit [31:0] wdata | 
|  | ); | 
|  | begin | 
|  | tl_h2d.a_address <= waddr; | 
|  | tl_h2d.a_data <= wdata; | 
|  | tl_h2d.a_mask <= 4'hF; | 
|  | tl_h2d.a_size <= 'h2; | 
|  | tl_h2d.a_opcode <= PutFullData; | 
|  | tl_h2d.a_source <= '0; | 
|  | tl_h2d.a_param <= '0; | 
|  | tl_h2d.a_valid <= 1'b1; | 
|  | @(posedge clk); | 
|  | while (!tl_d2h.a_ready) @(posedge clk); | 
|  | tl_h2d.a_valid <= 1'b0; | 
|  | while (!tl_d2h.d_valid) @(posedge clk); | 
|  | end | 
|  | endtask | 
|  |  | 
|  | task automatic send_rd ( | 
|  | input  bit [11:0] raddr, | 
|  | output bit [31:0] rdata | 
|  | ); | 
|  | begin | 
|  | tl_h2d.a_address  <= raddr; | 
|  | tl_h2d.a_opcode <= Get; | 
|  | tl_h2d.a_mask <= 4'hF; | 
|  | tl_h2d.a_size <= 'h2; | 
|  | tl_h2d.a_source <= '0; | 
|  | tl_h2d.a_param <= '0; | 
|  | tl_h2d.a_valid <= 1'b1; | 
|  | @(posedge clk); | 
|  | while (!tl_d2h.a_ready) @(posedge clk); | 
|  | tl_h2d.a_valid <= 1'b0; | 
|  | while (!tl_d2h.d_valid) @(negedge clk); | 
|  | rdata = tl_d2h.d_data; | 
|  | @(posedge clk); | 
|  | end | 
|  | endtask | 
|  |  | 
|  | task automatic test_q ( | 
|  | string regname, | 
|  | input bit [31:0] gotval, | 
|  | input bit [31:0] expval | 
|  | ); | 
|  | begin | 
|  | if (gotval !== expval) begin | 
|  | $error("ERROR: expected q value for %s is %x got %x", regname, expval, gotval); | 
|  | errorcount++; | 
|  | end else if (DEBUG) begin | 
|  | $display("INFO: got expected q value for %s of %x", regname, expval); | 
|  | end | 
|  | end | 
|  | endtask | 
|  |  | 
|  | // these registers need capturers to see the qe effect | 
|  |  | 
|  | logic [31:0] rwtype5_capture; | 
|  | always_ff @(posedge clk or negedge rst_n) begin | 
|  | if (!rst_n) | 
|  | rwtype5_capture <= 32'h0; | 
|  | else if (reg2hw.rwtype5.qe) | 
|  | rwtype5_capture <= reg2hw.rwtype5.q; | 
|  | end | 
|  |  | 
|  | logic [31:0] rwtype6_capture; | 
|  | always_ff @(posedge clk or negedge rst_n) begin | 
|  | if (!rst_n) | 
|  | rwtype6_capture <= 32'hc8c8c8c8; | 
|  | else if (reg2hw.rwtype6.qe) | 
|  | rwtype6_capture <= reg2hw.rwtype6.q; | 
|  | end | 
|  | // externalized register | 
|  | assign hw2reg.rwtype6.d = rwtype6_capture; | 
|  |  | 
|  | logic [31:0] rotype1_capture, my_rotype1_d; | 
|  | logic my_rotype1_de; | 
|  | always_ff @(posedge clk or negedge rst_n) begin | 
|  | if (!rst_n) | 
|  | rotype1_capture <= 32'h66aa66aa; | 
|  | else if (my_rotype1_de) | 
|  | rotype1_capture <= my_rotype1_d; | 
|  | end | 
|  | // externalized register | 
|  | assign hw2reg.rotype1.d = rotype1_capture; | 
|  |  | 
|  | task automatic test_capture ( | 
|  | string regname, | 
|  | input bit [31:0] gotval, | 
|  | input bit [31:0] expval | 
|  | ); | 
|  | begin | 
|  | if (gotval !== expval) begin | 
|  | $error("ERROR: expected hwqe captured value for %s is %x got %x", regname, expval, | 
|  | gotval); | 
|  | errorcount++; | 
|  | end else if (DEBUG) begin | 
|  | $display("INFO: got expected hwqe captured value for %s of %x", regname, expval); | 
|  | end | 
|  | end | 
|  | endtask | 
|  |  | 
|  | task automatic test_reg ( | 
|  | string regname, | 
|  | input bit [11:0] addr, | 
|  | input bit [31:0] expval | 
|  | ); | 
|  | begin | 
|  | logic [31:0] gotval; | 
|  | send_rd(addr, gotval); | 
|  | if (gotval !== expval) begin | 
|  | $error("ERROR: expected rd value for %s is %x got %x", regname, expval, gotval); | 
|  | errorcount++; | 
|  | end else if (DEBUG) begin | 
|  | $display("INFO: got expected rd value for %s of %x", regname, expval); | 
|  | end | 
|  | end | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype0(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("RWTYPE0", 12'h0, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE0", reg2hw.rwtype0.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("RWTYPE0", 12'h0, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE0", reg2hw.rwtype0.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype1(input bit [31:0] expdata); | 
|  | logic [31:0] maskexp; | 
|  | maskexp = expdata & 32'h0000ff13; | 
|  | test_reg("RWTYPE1", 12'h4, maskexp); | 
|  | // test q's | 
|  | test_q("RWTYPE1.field0", reg2hw.rwtype1.field0.q, maskexp[0]); | 
|  | test_q("RWTYPE1.field1", reg2hw.rwtype1.field1.q, maskexp[1]); | 
|  | test_q("RWTYPE1.field4", reg2hw.rwtype1.field4.q, maskexp[4]); | 
|  | test_q("RWTYPE1.field15_8", reg2hw.rwtype1.field15_8.q, maskexp[15:8]); | 
|  | // hold value | 
|  | repeat(5) @(posedge clk); | 
|  | test_reg("RWTYPE1", 12'h4, maskexp); | 
|  | // test q | 
|  | test_q("RWTYPE1.field0", reg2hw.rwtype1.field0.q, maskexp[0]); | 
|  | test_q("RWTYPE1.field1", reg2hw.rwtype1.field1.q, maskexp[1]); | 
|  | test_q("RWTYPE1.field4", reg2hw.rwtype1.field4.q, maskexp[4]); | 
|  | test_q("RWTYPE1.field15_8", reg2hw.rwtype1.field15_8.q, maskexp[15:8]); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype2(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("RWTYPE2", 12'h8, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE2", reg2hw.rwtype2.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("RWTYPE2", 12'h8, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE2", reg2hw.rwtype2.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype3(input bit [31:0] expdata); | 
|  | test_reg("RWTYPE3", 12'hc, expdata); | 
|  | // test q's | 
|  | test_q("RWTYPE3.field0", reg2hw.rwtype3.field0.q, expdata[15:0]); | 
|  | test_q("RWTYPE3.field1", reg2hw.rwtype3.field1.q, expdata[31:16]); | 
|  | // hold value | 
|  | repeat(5) @(posedge clk); | 
|  | test_reg("RWTYPE3", 12'hc, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE3.field0", reg2hw.rwtype3.field0.q, expdata[15:0]); | 
|  | test_q("RWTYPE3.field1", reg2hw.rwtype3.field1.q, expdata[31:16]); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype4(input bit [31:0] expdata); | 
|  | test_reg("RWTYPE4", 12'h200, expdata); | 
|  | // test q's | 
|  | test_q("RWTYPE4.field0", reg2hw.rwtype4.field0.q, expdata[15:0]); | 
|  | test_q("RWTYPE4.field1", reg2hw.rwtype4.field1.q, expdata[31:16]); | 
|  | // hold value | 
|  | repeat(5) @(posedge clk); | 
|  | test_reg("RWTYPE4", 12'h200, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE4.field0", reg2hw.rwtype4.field0.q, expdata[15:0]); | 
|  | test_q("RWTYPE4.field1", reg2hw.rwtype4.field1.q, expdata[31:16]); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rotype0(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("ROTYPE0", 12'h204, expdata); | 
|  | // test q | 
|  | test_q("ROTYPE0", reg2hw.rotype0.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("ROTYPE0", 12'h204, expdata); | 
|  | // test q | 
|  | test_q("ROTYPE0", reg2hw.rotype0.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_w1ctype0(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("W1CTYPE0", 12'h208, expdata); | 
|  | // test q | 
|  | test_q("W1CTYPE0", reg2hw.w1ctype0.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("W1CTYPE0", 12'h208, expdata); | 
|  | // test q | 
|  | test_q("W1CTYPE0", reg2hw.w1ctype0.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_w1ctype1(input bit [31:0] expdata); | 
|  | test_reg("W1CTYPE1", 12'h20c, expdata); | 
|  | // test q's | 
|  | test_q("W1CTYPE1.field0", reg2hw.w1ctype1.field0.q, expdata[15:0]); | 
|  | test_q("W1CTYPE1.field1", reg2hw.w1ctype1.field1.q, expdata[31:16]); | 
|  | // hold value | 
|  | repeat(5) @(posedge clk); | 
|  | test_reg("W1CTYPE1", 12'h20c, expdata); | 
|  | // test q | 
|  | test_q("W1CTYPE1.field0", reg2hw.w1ctype1.field0.q, expdata[15:0]); | 
|  | test_q("W1CTYPE1.field1", reg2hw.w1ctype1.field1.q, expdata[31:16]); | 
|  | endtask | 
|  |  | 
|  | task automatic test_w1ctype2(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("W1CTYPE2", 12'h210, expdata); | 
|  | // test q | 
|  | test_q("W1CTYPE2", reg2hw.w1ctype2.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("W1CTYPE2", 12'h210, expdata); | 
|  | // test q | 
|  | test_q("W1CTYPE2", reg2hw.w1ctype2.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_w1stype2(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("W1STYPE2", 12'h214, expdata); | 
|  | // test q | 
|  | test_q("W1STYPE2", reg2hw.w1stype2.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("W1STYPE2", 12'h214, expdata); | 
|  | // test q | 
|  | test_q("W1STYPE2", reg2hw.w1stype2.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_w0ctype2(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("W0CTYPE2", 12'h218, expdata); | 
|  | // test q | 
|  | test_q("W0CTYPE2", reg2hw.w0ctype2.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("W0CTYPE2", 12'h218, expdata); | 
|  | // test q | 
|  | test_q("W0CTYPE2", reg2hw.w0ctype2.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_r0w1ctype2(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("R0W1CTYPE2", 12'h21c, 0); | 
|  | // test q | 
|  | test_q("R0W1CTYPE2", reg2hw.r0w1ctype2.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("R0W1CTYPE2", 12'h21c, 0); | 
|  | // test q | 
|  | test_q("R0W1CTYPE2", reg2hw.r0w1ctype2.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rctype0(input bit [31:0] expdata); | 
|  | // test q | 
|  | test_q("RCTYPE0", reg2hw.rctype0.q, expdata); | 
|  | // test register read | 
|  | test_reg("RCTYPE0", 12'h220, expdata); | 
|  | // second read returns zero value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("RCTYPE0", 12'h220, 32'h0); | 
|  | // test q | 
|  | test_q("RCTYPE0", reg2hw.rctype0.q, 32'h0); | 
|  | endtask | 
|  |  | 
|  | task automatic test_wotype0(input bit [31:0] expdata); | 
|  | // test register read, always returns zero | 
|  | test_reg("WOTYPE0", 12'h224, 0); | 
|  | // test q | 
|  | test_q("WOTYPE0", reg2hw.wotype0.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("WOTYPE0", 12'h224, 32'h0); | 
|  | // test q | 
|  | test_q("WOTYPE0", reg2hw.wotype0.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_mixtype0(input bit [31:0] expdata); | 
|  | // test q's | 
|  | test_q("MIXTYPE0.field0", reg2hw.mixtype0.field0.q, expdata[3:0]); | 
|  | test_q("MIXTYPE0.field1", reg2hw.mixtype0.field1.q, expdata[7:4]); | 
|  | test_q("MIXTYPE0.field2", reg2hw.mixtype0.field2.q, expdata[11:8]); | 
|  | test_q("MIXTYPE0.field3", reg2hw.mixtype0.field3.q, expdata[15:12]); | 
|  | test_q("MIXTYPE0.field4", reg2hw.mixtype0.field4.q, expdata[19:16]); | 
|  | test_q("MIXTYPE0.field5", reg2hw.mixtype0.field5.q, expdata[23:20]); | 
|  | test_q("MIXTYPE0.field6", reg2hw.mixtype0.field6.q, expdata[27:24]); | 
|  | test_q("MIXTYPE0.field7", reg2hw.mixtype0.field7.q, expdata[31:28]); | 
|  | // test register | 
|  | test_reg("MIXTYPE0", 12'h228, expdata & 32'h0fffffff);  // [31:28] is write-only | 
|  | // hold value | 
|  | repeat(5) @(posedge clk); | 
|  | // [31:28] is write-only, [27:24] is read-clear | 
|  | test_reg("MIXTYPE0", 12'h228, expdata & 32'h00ffffff); | 
|  | // test q | 
|  | test_q("MIXTYPE0.field0", reg2hw.mixtype0.field0.q, expdata[3:0]); | 
|  | test_q("MIXTYPE0.field1", reg2hw.mixtype0.field1.q, expdata[7:4]); | 
|  | test_q("MIXTYPE0.field2", reg2hw.mixtype0.field2.q, expdata[11:8]); | 
|  | test_q("MIXTYPE0.field3", reg2hw.mixtype0.field3.q, expdata[15:12]); | 
|  | test_q("MIXTYPE0.field4", reg2hw.mixtype0.field4.q, expdata[19:16]); | 
|  | test_q("MIXTYPE0.field5", reg2hw.mixtype0.field5.q, expdata[23:20]); | 
|  | test_q("MIXTYPE0.field6", reg2hw.mixtype0.field6.q, 4'h0); // read-clear | 
|  | test_q("MIXTYPE0.field7", reg2hw.mixtype0.field7.q, expdata[31:28]); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype5(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("RWTYPE5", 12'h22c, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE5", reg2hw.rwtype5.q, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("RWTYPE5", 12'h22c, expdata); | 
|  | // test q | 
|  | test_q("RWTYPE5", reg2hw.rwtype5.q, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype5_capture(input bit [31:0] expdata); | 
|  | // test captured value | 
|  | test_capture("RWTYPE5", rwtype5_capture, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype6(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("RWTYPE6", 12'h230, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("RWTYPE6", 12'h230, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype6_capture(input bit [31:0] expdata); | 
|  | // test captured value | 
|  | test_capture("RWTYPE6", rwtype6_capture, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rwtype7(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("RWTYPE7", 12'h23c, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("RWTYPE7", 12'h23c, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rotype1(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("ROTYPE1", 12'h234, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("ROTYPE1", 12'h234, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rotype1_capture(input bit [31:0] expdata); | 
|  | // test captured value | 
|  | test_capture("ROTYPE1", rotype1_capture, expdata); | 
|  | endtask | 
|  |  | 
|  | task automatic test_rotype2(input bit [31:0] expdata); | 
|  | // test register read | 
|  | test_reg("ROTYPE2", 12'h238, expdata); | 
|  | // holds value | 
|  | repeat(5) @(posedge clk); | 
|  | // test register read | 
|  | test_reg("ROTYPE2", 12'h238, expdata); | 
|  | endtask | 
|  |  | 
|  | // so far just these registers we need to drive back into | 
|  | // RWTYPE2[31:0] | 
|  | // RWTYPE3.FIELD0[15:0] | 
|  | // RWTYPE3.FIELD1[15:0] | 
|  | // ROTYPE0[31:0] | 
|  | // W1CTYPE2[31:0] | 
|  | // W1STYPE2[31:0] | 
|  | // W0CTYPE2[31:0] | 
|  | // R0W1CTYPE2[31:0] | 
|  | // RCTYPE0[31:0] | 
|  | // MIXTYPE0.FIELD1[3:0] | 
|  | // MIXTYPE0.FIELD3[3:0] | 
|  | // MIXTYPE0.FIELD4[3:0] | 
|  | // MIXTYPE0.FIELD5[3:0] | 
|  | // MIXTYPE0.FIELD6[3:0] | 
|  | // RWTYPE5[31:0] | 
|  |  | 
|  | logic [31:0] hold_wd, hold_q; | 
|  | initial begin | 
|  | hw2reg.rwtype2.de = 1'b0; | 
|  | hw2reg.rwtype2.d  = 32'hxxxxxxxx; | 
|  | hw2reg.rwtype3.field0.de = 1'b0; | 
|  | hw2reg.rwtype3.field0.d  = 16'hxxxx; | 
|  | hw2reg.rwtype3.field1.de = 1'b0; | 
|  | hw2reg.rwtype3.field1.d  = 16'hxxxx; | 
|  | hw2reg.rotype0.de = 1'b0; | 
|  | hw2reg.rotype0.d  = 32'hxxxxxxxx; | 
|  | hw2reg.w1ctype2.de = 1'b0; | 
|  | hw2reg.w1ctype2.d  = 32'hxxxxxxxx; | 
|  | hw2reg.w1stype2.de = 1'b0; | 
|  | hw2reg.w1stype2.d  = 32'hxxxxxxxx; | 
|  | hw2reg.w0ctype2.de = 1'b0; | 
|  | hw2reg.w0ctype2.d  = 32'hxxxxxxxx; | 
|  | hw2reg.r0w1ctype2.de = 1'b0; | 
|  | hw2reg.r0w1ctype2.d  = 32'hxxxxxxxx; | 
|  | hw2reg.rctype0.de = 1'b0; | 
|  | hw2reg.rctype0.d  = 32'hxxxxxxxx; | 
|  | hw2reg.mixtype0.field1.de = 1'b0; | 
|  | hw2reg.mixtype0.field1.d  = 4'hx; | 
|  | hw2reg.mixtype0.field3.de = 1'b0; | 
|  | hw2reg.mixtype0.field3.d  = 4'hx; | 
|  | hw2reg.mixtype0.field4.de = 1'b0; | 
|  | hw2reg.mixtype0.field4.d  = 4'hx; | 
|  | hw2reg.mixtype0.field5.de = 1'b0; | 
|  | hw2reg.mixtype0.field5.d  = 4'hx; | 
|  | hw2reg.mixtype0.field6.de = 1'b0; | 
|  | hw2reg.mixtype0.field6.d  = 4'hx; | 
|  | hw2reg.rwtype5.de = 1'b0; | 
|  | hw2reg.rwtype5.d  = 32'hxxxxxxxx; | 
|  | my_rotype1_de = 1'b0; | 
|  | my_rotype1_d = 32'hxxxxxxxx; | 
|  | tl_h2d.a_valid = 1'b0; | 
|  | tl_h2d.a_opcode = Get; | 
|  | tl_h2d.a_user = 16'h0; | 
|  | repeat(20) @(posedge clk); | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE0 | 
|  | // | 
|  | // default value is 12345678 | 
|  | test_rwtype0(12345678); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h0, hold_wd); | 
|  | test_rwtype0(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h0, hold_wd); | 
|  | test_rwtype0(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE1 | 
|  | // | 
|  | // default value is 32'h00006411 | 
|  | test_rwtype1(32'h00006411); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h4, hold_wd); | 
|  | test_rwtype1(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h4, hold_wd); | 
|  | test_rwtype1(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE2, RW + HRW | 
|  | // | 
|  | // default value is 0x04000400 | 
|  | test_rwtype2(32'h04000400); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h8, hold_wd); | 
|  | test_rwtype2(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h8, hold_wd); | 
|  | test_rwtype2(hold_wd); | 
|  | // write from HW side | 
|  | hold_wd = $urandom; | 
|  | hw2reg.rwtype2.de <= 1'b1; | 
|  | hw2reg.rwtype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype2.de <= 1'b0; | 
|  | hw2reg.rwtype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype2(hold_wd); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.rwtype2.de <= 1'b1; | 
|  | hw2reg.rwtype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype2.de <= 1'b0; | 
|  | hw2reg.rwtype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype2(hold_wd); | 
|  | // try and get both the we and the de at the same time, we should win | 
|  | hold_wd = 32'haaaaaaaa; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'h8, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.rwtype2.de <= 1'b1; | 
|  | hw2reg.rwtype2.d  <= 32'h55555555; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype2.de <= 1'b0; | 
|  | hw2reg.rwtype2.d  <= 32'hxxxxxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | test_rwtype2(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE3, separate HRW fields | 
|  | // | 
|  | // default value is 0xee66cc55 | 
|  | test_rwtype3(32'hee66cc55); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'hc, hold_wd); | 
|  | test_rwtype3(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'hc, hold_wd); | 
|  | test_rwtype3(hold_wd); | 
|  | // write one field from HW side | 
|  | hold_q = hold_wd; | 
|  | hold_wd = $urandom; | 
|  | hw2reg.rwtype3.field0.de <= 1'b1; | 
|  | hw2reg.rwtype3.field0.d  <= hold_wd[15:0]; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype3.field0.de <= 1'b0; | 
|  | hw2reg.rwtype3.field0.d  <= 16'hxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype3({hold_q[31:16],hold_wd[15:0]}); | 
|  | // write other field from HW side | 
|  | hw2reg.rwtype3.field1.de <= 1'b1; | 
|  | hw2reg.rwtype3.field1.d  <= hold_wd[31:16]; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype3.field1.de <= 1'b0; | 
|  | hw2reg.rwtype3.field1.d  <= 16'hxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype3(hold_wd); | 
|  | // write inverted | 
|  | hold_q = hold_wd; | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.rwtype3.field1.de <= 1'b1; | 
|  | hw2reg.rwtype3.field1.d  <= hold_wd[31:16]; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype3.field1.de <= 1'b0; | 
|  | hw2reg.rwtype3.field1.d  <= 16'hxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype3({hold_wd[31:16],hold_q[15:0]}); | 
|  | // write other field from HW side | 
|  | hw2reg.rwtype3.field0.de <= 1'b1; | 
|  | hw2reg.rwtype3.field0.d  <= hold_wd[15:0]; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype3.field0.de <= 1'b0; | 
|  | hw2reg.rwtype3.field0.d  <= 16'hxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype3(hold_wd); | 
|  | // try and get both the we and one de at the same time, we should win | 
|  | hold_q = 32'h55555555; | 
|  | hold_wd = 32'haaaaaaaa; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'hc, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.rwtype3.field0.de <= 1'b1; | 
|  | hw2reg.rwtype3.field0.d  <= hold_q[15:0]; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype3.field0.de <= 1'b0; | 
|  | hw2reg.rwtype3.field0.d  <= 16'hxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | test_rwtype3(hold_wd); | 
|  | hold_q = 32'h77777777; | 
|  | hold_wd = 32'hcccccccc; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'hc, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.rwtype3.field1.de <= 1'b1; | 
|  | hw2reg.rwtype3.field1.d  <= hold_q[15:0]; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype3.field1.de <= 1'b0; | 
|  | hw2reg.rwtype3.field1.d  <= 16'hxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | test_rwtype3(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE4 | 
|  | // | 
|  | // default value is 80004000 | 
|  | test_rwtype4(32'h80004000); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h200, hold_wd); | 
|  | test_rwtype4(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h200, hold_wd); | 
|  | test_rwtype4(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test ROTYPE0 | 
|  | // | 
|  | // default value is 0x11111111 | 
|  | hold_wd = 32'h11111111; | 
|  | test_rotype0(hold_wd); | 
|  | // write value, should be ignored | 
|  | send_wr(12'h204, 32'hdeadbeef); | 
|  | test_rotype0(hold_wd); | 
|  | // write opposite | 
|  | send_wr(12'h204, ~32'hdeadbeef); | 
|  | test_rotype0(hold_wd); | 
|  | // write from HW side | 
|  | hold_wd = $urandom; | 
|  | hw2reg.rotype0.de <= 1'b1; | 
|  | hw2reg.rotype0.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rotype0.de <= 1'b0; | 
|  | hw2reg.rotype0.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rotype0(hold_wd); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.rotype0.de <= 1'b1; | 
|  | hw2reg.rotype0.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rotype0.de <= 1'b0; | 
|  | hw2reg.rotype0.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rotype0(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test W1CTYPE0 | 
|  | // | 
|  | // default value is 0xbbccddee | 
|  | hold_q = 32'hbbccddee; | 
|  | test_w1ctype0(hold_q); | 
|  | // write value, should clear those bits | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h208, hold_wd); | 
|  | test_w1ctype0(hold_q); | 
|  | // write opposite, should clear everything by now | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h208, hold_wd); | 
|  | test_w1ctype0(hold_q); | 
|  | /////// | 
|  | // | 
|  | // test W1CTYPE1 | 
|  | // | 
|  | // default value is 0x7777eeee | 
|  | hold_q = 32'h7777eeee; | 
|  | test_w1ctype1(hold_q); | 
|  | // write value, should clear those bits | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h20c, hold_wd); | 
|  | test_w1ctype1(hold_q); | 
|  | // write opposite, shoudl clear everything by now | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h20c, hold_wd); | 
|  | test_w1ctype1(hold_q); | 
|  | /////// | 
|  | // | 
|  | // test W1CTYPE2, W1C + HRW | 
|  | // | 
|  | // default value is 0xaa775566 | 
|  | hold_q = 32'haa775566; | 
|  | test_w1ctype2(hold_q); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h210, hold_wd); | 
|  | test_w1ctype2(hold_q); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h210, hold_wd); | 
|  | test_w1ctype2(hold_q); | 
|  | // write from HW side | 
|  | hold_wd = $urandom; | 
|  | hw2reg.w1ctype2.de <= 1'b1; | 
|  | hw2reg.w1ctype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.w1ctype2.de <= 1'b0; | 
|  | hw2reg.w1ctype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_w1ctype2(hold_wd); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.w1ctype2.de <= 1'b1; | 
|  | hw2reg.w1ctype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.w1ctype2.de <= 1'b0; | 
|  | hw2reg.w1ctype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_w1ctype2(hold_wd); | 
|  | // write value | 
|  | hold_q = hold_wd; | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h210, hold_wd); | 
|  | test_w1ctype2(hold_q); | 
|  | // try and get both the we and the de at the same time, we should clear bits in d | 
|  | hold_wd = 32'h44444444; | 
|  | hold_q = 32'heeddbb77; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'h210, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.w1ctype2.de <= 1'b1; | 
|  | hw2reg.w1ctype2.d  <= hold_q; | 
|  | @(posedge clk); | 
|  | hw2reg.w1ctype2.de <= 1'b0; | 
|  | hw2reg.w1ctype2.d  <= 32'hxxxxxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | hold_q &= ~hold_wd; | 
|  | test_w1ctype2(hold_q); | 
|  | /////// | 
|  | // | 
|  | // test W1STYPE2, W1S + HRW | 
|  | // | 
|  | // default value is 0x11224488 | 
|  | hold_q = 32'h11224488; | 
|  | test_w1stype2(hold_q); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q |= hold_wd; | 
|  | send_wr(12'h214, hold_wd); | 
|  | test_w1stype2(hold_q); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | hold_q |= hold_wd; | 
|  | send_wr(12'h214, hold_wd); | 
|  | test_w1stype2(hold_q); | 
|  | // write from HW side | 
|  | hold_wd = $urandom; | 
|  | hw2reg.w1stype2.de <= 1'b1; | 
|  | hw2reg.w1stype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.w1stype2.de <= 1'b0; | 
|  | hw2reg.w1stype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_w1stype2(hold_wd); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.w1stype2.de <= 1'b1; | 
|  | hw2reg.w1stype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.w1stype2.de <= 1'b0; | 
|  | hw2reg.w1stype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_w1stype2(hold_wd); | 
|  | // write value | 
|  | hold_q = hold_wd; | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q |= hold_wd; | 
|  | send_wr(12'h214, hold_wd); | 
|  | test_w1stype2(hold_q); | 
|  | // try and get both the we and the de at the same time, we should set bits in d | 
|  | hold_wd = 32'h44444444; | 
|  | hold_q = 32'h9955cc33; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'h214, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.w1stype2.de <= 1'b1; | 
|  | hw2reg.w1stype2.d  <= hold_q; | 
|  | @(posedge clk); | 
|  | hw2reg.w1stype2.de <= 1'b0; | 
|  | hw2reg.w1stype2.d  <= 32'hxxxxxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | hold_q |= hold_wd; | 
|  | test_w1stype2(hold_q); | 
|  | /////// | 
|  | // | 
|  | // test W0CTYPE2, W0C + HRW | 
|  | // | 
|  | // default value is 0xfec8137f | 
|  | hold_q = 32'hfec8137f; | 
|  | test_w0ctype2(hold_q); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= hold_wd; | 
|  | send_wr(12'h218, hold_wd); | 
|  | test_w0ctype2(hold_q); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | hold_q &= hold_wd; | 
|  | send_wr(12'h218, hold_wd); | 
|  | test_w0ctype2(hold_q); | 
|  | // write from HW side | 
|  | hold_wd = $urandom; | 
|  | hw2reg.w0ctype2.de <= 1'b1; | 
|  | hw2reg.w0ctype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.w0ctype2.de <= 1'b0; | 
|  | hw2reg.w0ctype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_w0ctype2(hold_wd); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.w0ctype2.de <= 1'b1; | 
|  | hw2reg.w0ctype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.w0ctype2.de <= 1'b0; | 
|  | hw2reg.w0ctype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_w0ctype2(hold_wd); | 
|  | // write value | 
|  | hold_q = hold_wd; | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= hold_wd; | 
|  | send_wr(12'h218, hold_wd); | 
|  | test_w0ctype2(hold_q); | 
|  | // try and get both the we and the de at the same time, we should set bits in d | 
|  | hold_wd = 32'hee77bbcc; | 
|  | hold_q = 32'hbcada8e4; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'h218, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.w0ctype2.de <= 1'b1; | 
|  | hw2reg.w0ctype2.d  <= hold_q; | 
|  | @(posedge clk); | 
|  | hw2reg.w0ctype2.de <= 1'b0; | 
|  | hw2reg.w0ctype2.d  <= 32'hxxxxxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | hold_q &= hold_wd; | 
|  | test_w0ctype2(hold_q); | 
|  | /////// | 
|  | // | 
|  | // test R0W1CTYPE2, R0W1C + HRW | 
|  | // | 
|  | // default value is 0xaa775566 | 
|  | hold_q = 32'haa775566; | 
|  | test_r0w1ctype2(hold_q); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h21c, hold_wd); | 
|  | test_r0w1ctype2(hold_q); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h21c, hold_wd); | 
|  | test_r0w1ctype2(hold_q); | 
|  | // write from HW side | 
|  | hold_wd = $urandom; | 
|  | hw2reg.r0w1ctype2.de <= 1'b1; | 
|  | hw2reg.r0w1ctype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.r0w1ctype2.de <= 1'b0; | 
|  | hw2reg.r0w1ctype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_r0w1ctype2(hold_wd); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.r0w1ctype2.de <= 1'b1; | 
|  | hw2reg.r0w1ctype2.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.r0w1ctype2.de <= 1'b0; | 
|  | hw2reg.r0w1ctype2.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_r0w1ctype2(hold_wd); | 
|  | // write value | 
|  | hold_q = hold_wd; | 
|  | hold_wd = 32'hdeadbeef; | 
|  | hold_q &= ~hold_wd; | 
|  | send_wr(12'h21c, hold_wd); | 
|  | test_r0w1ctype2(hold_q); | 
|  | // try and get both the we and the de at the same time, we should clear bits in d | 
|  | hold_wd = 32'h44444444; | 
|  | hold_q = 32'heeddbb77; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'h21c, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.r0w1ctype2.de <= 1'b1; | 
|  | hw2reg.r0w1ctype2.d  <= hold_q; | 
|  | @(posedge clk); | 
|  | hw2reg.r0w1ctype2.de <= 1'b0; | 
|  | hw2reg.r0w1ctype2.d  <= 32'hxxxxxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | hold_q &= ~hold_wd; | 
|  | test_r0w1ctype2(hold_q); | 
|  | /////// | 
|  | // | 
|  | // test RCTYPE0 (read-only clear) | 
|  | // | 
|  | // default value is 0x77443399 | 
|  | hold_wd = 32'h77443399; | 
|  | test_rctype0(hold_wd); | 
|  | // write value, should be ignored | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h220, hold_wd); | 
|  | test_rctype0(0); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h220, hold_wd); | 
|  | test_rctype0(0); | 
|  | // write from HW side | 
|  | hold_wd = $urandom; | 
|  | hw2reg.rctype0.de <= 1'b1; | 
|  | hw2reg.rctype0.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rctype0.de <= 1'b0; | 
|  | hw2reg.rctype0.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rctype0(hold_wd); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.rctype0.de <= 1'b1; | 
|  | hw2reg.rctype0.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rctype0.de <= 1'b0; | 
|  | hw2reg.rctype0.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rctype0(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test WOTYPE0 | 
|  | // | 
|  | // default value is 0x11223344 | 
|  | hold_wd = 32'h11223344; | 
|  | test_wotype0(hold_wd); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h224, hold_wd); | 
|  | test_wotype0(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h224, hold_wd); | 
|  | test_wotype0(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test MIXTYPE0 | 
|  | // | 
|  | // default value is 0x87654321 | 
|  | hold_q = 32'h87654321; | 
|  | test_mixtype0(hold_q); | 
|  | // read cleared bits [27:24] | 
|  | hold_q  &= 32'hf0ffffff; | 
|  | // write value | 
|  | hold_wd = 32'h55555555; | 
|  | send_wr(12'h228, hold_wd); | 
|  | @(posedge clk); | 
|  | hold_q = { hold_wd[31:28],                  // write-only | 
|  | hold_q[27:24],  // read-only-clear | 
|  | hold_wd[23:20] | hold_q[23:20],  // rw1s | 
|  | ~hold_wd[19:16] & hold_q[19:16],  // rw1c | 
|  | hold_q[15:12],  // ro | 
|  | hold_q[11: 8],  // ro | 
|  | hold_wd[ 7: 4],                  // rw | 
|  | hold_wd[ 3: 0]};                 // rw | 
|  | test_mixtype0(hold_q); | 
|  | // write opposite | 
|  | hold_wd = 32'haaaaaaaa; | 
|  | send_wr(12'h228, hold_wd); | 
|  | @(posedge clk); | 
|  | hold_q = { hold_wd[31:28],                  // write-only | 
|  | hold_q[27:24],  // read-only-clear | 
|  | hold_wd[23:20] | hold_q[23:20],  // rw1s | 
|  | ~hold_wd[19:16] & hold_q[19:16],  // rw1c | 
|  | hold_q[15:12],  // ro | 
|  | hold_q[11: 8],  // ro | 
|  | hold_wd[ 7: 4],                  // rw | 
|  | hold_wd[ 3: 0]};                 // rw | 
|  | test_mixtype0(hold_q); | 
|  | repeat(2) begin | 
|  | // write one field at a time from HW side | 
|  | hold_wd = $urandom; | 
|  | // field 1 | 
|  | $display("INFO: trying field[1] with %h", hold_wd); | 
|  | hw2reg.mixtype0.field1.de <= 1'b1; | 
|  | hw2reg.mixtype0.field1.d  <= hold_wd[7:4]; | 
|  | @(posedge clk); | 
|  | hw2reg.mixtype0.field1.de <= 1'b0; | 
|  | hw2reg.mixtype0.field1.d  <= 4'hx; | 
|  | @(posedge clk); | 
|  | hold_q = {hold_q[31:8],hold_wd[7:4],hold_q[3:0]}; | 
|  | test_mixtype0(hold_q); | 
|  | // field 3 | 
|  | $display("INFO: trying field[3] with %h", hold_wd); | 
|  | hw2reg.mixtype0.field3.de <= 1'b1; | 
|  | hw2reg.mixtype0.field3.d  <= hold_wd[15:12]; | 
|  | @(posedge clk); | 
|  | hw2reg.mixtype0.field3.de <= 1'b0; | 
|  | hw2reg.mixtype0.field3.d  <= 4'hx; | 
|  | @(posedge clk); | 
|  | hold_q = {hold_q[31:16],hold_wd[15:12],hold_q[11:0]}; | 
|  | test_mixtype0(hold_q); | 
|  | // field 4 | 
|  | $display("INFO: trying field[4] with %h", hold_wd); | 
|  | hw2reg.mixtype0.field4.de <= 1'b1; | 
|  | hw2reg.mixtype0.field4.d  <= hold_wd[19:16]; | 
|  | @(posedge clk); | 
|  | hw2reg.mixtype0.field4.de <= 1'b0; | 
|  | hw2reg.mixtype0.field4.d  <= 4'hx; | 
|  | @(posedge clk); | 
|  | hold_q = {hold_q[31:20],hold_wd[19:16],hold_q[15:0]}; | 
|  | test_mixtype0(hold_q); | 
|  | // field 5 | 
|  | $display("INFO: trying field[5] with %h", hold_wd); | 
|  | hw2reg.mixtype0.field5.de <= 1'b1; | 
|  | hw2reg.mixtype0.field5.d  <= hold_wd[23:20]; | 
|  | @(posedge clk); | 
|  | hw2reg.mixtype0.field5.de <= 1'b0; | 
|  | hw2reg.mixtype0.field5.d  <= 4'hx; | 
|  | @(posedge clk); | 
|  | hold_q = {hold_q[31:24],hold_wd[23:20],hold_q[19:0]}; | 
|  | test_mixtype0(hold_q); | 
|  | // field 6 | 
|  | $display("INFO: trying field[6] with %h", hold_wd); | 
|  | hw2reg.mixtype0.field6.de <= 1'b1; | 
|  | hw2reg.mixtype0.field6.d  <= hold_wd[27:24]; | 
|  | @(posedge clk); | 
|  | hw2reg.mixtype0.field6.de <= 1'b0; | 
|  | hw2reg.mixtype0.field6.d  <= 4'hx; | 
|  | @(posedge clk); | 
|  | hold_q = {hold_q[31:28],hold_wd[27:24],hold_q[23:0]}; | 
|  | test_mixtype0(hold_q); | 
|  | hold_q &= 32'hf0ffffff; // read-clear | 
|  | end | 
|  | // try and get both the we and the de's at the same time, we should win | 
|  | repeat(2) begin | 
|  | // bits [11:8] (field2) can never be changed | 
|  | hold_q  = ($urandom & 32'hfffff0ff) | (hold_q & 32'h00000f00); | 
|  | hold_wd = $urandom; | 
|  | $display("INFO: trying field collision with we %h de %h", hold_wd, hold_q); | 
|  | fork | 
|  | begin | 
|  | send_wr(12'h228, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.mixtype0.field1.de <= 1'b1; | 
|  | hw2reg.mixtype0.field1.d  <= hold_q[7:4]; | 
|  | hw2reg.mixtype0.field3.de <= 1'b1; | 
|  | hw2reg.mixtype0.field3.d  <= hold_q[15:12]; | 
|  | hw2reg.mixtype0.field4.de <= 1'b1; | 
|  | hw2reg.mixtype0.field4.d  <= hold_q[19:16]; | 
|  | hw2reg.mixtype0.field5.de <= 1'b1; | 
|  | hw2reg.mixtype0.field5.d  <= hold_q[23:20]; | 
|  | hw2reg.mixtype0.field6.de <= 1'b1; | 
|  | hw2reg.mixtype0.field6.d  <= hold_q[27:24]; | 
|  | @(posedge clk); | 
|  | hw2reg.mixtype0.field1.de <= 1'b0; | 
|  | hw2reg.mixtype0.field1.d  <= 4'hx; | 
|  | hw2reg.mixtype0.field3.de <= 1'b0; | 
|  | hw2reg.mixtype0.field3.d  <= 4'hx; | 
|  | hw2reg.mixtype0.field4.de <= 1'b0; | 
|  | hw2reg.mixtype0.field4.d  <= 4'hx; | 
|  | hw2reg.mixtype0.field5.de <= 1'b0; | 
|  | hw2reg.mixtype0.field5.d  <= 4'hx; | 
|  | hw2reg.mixtype0.field6.de <= 1'b0; | 
|  | hw2reg.mixtype0.field6.d  <= 4'hx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | hold_q = { hold_wd[31:28],                  // write-only | 
|  | hold_q[27:24],  // read-only-clear | 
|  | hold_wd[23:20] | hold_q[23:20],  // rw1s | 
|  | ~hold_wd[19:16] & hold_q[19:16],  // rw1c | 
|  | hold_q[15:12],  // ro | 
|  | hold_q[11: 8],  // ro | 
|  | hold_wd[ 7: 4],                  // rw | 
|  | hold_wd[ 3: 0]};                 // rw | 
|  | test_mixtype0(hold_q); | 
|  | end | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE5, RW + HRW + HWQE | 
|  | // test that only sw writes effect captured value | 
|  | // | 
|  | // default value is 0xbabababa | 
|  | test_rwtype5(32'hbabababa); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h22c, hold_wd); | 
|  | test_rwtype5(hold_wd); | 
|  | test_rwtype5_capture(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h22c, hold_wd); | 
|  | test_rwtype5(hold_wd); | 
|  | test_rwtype5_capture(hold_wd); | 
|  | // write from HW side | 
|  | hold_q = hold_wd; | 
|  | hold_wd = $urandom; | 
|  | hw2reg.rwtype5.de <= 1'b1; | 
|  | hw2reg.rwtype5.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype5.de <= 1'b0; | 
|  | hw2reg.rwtype5.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype5(hold_wd); | 
|  | test_rwtype5_capture(hold_q); | 
|  | // write from HW side inverted | 
|  | hold_wd = ~hold_wd; | 
|  | hw2reg.rwtype5.de <= 1'b1; | 
|  | hw2reg.rwtype5.d  <= hold_wd; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype5.de <= 1'b0; | 
|  | hw2reg.rwtype5.d  <= 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rwtype5(hold_wd); | 
|  | test_rwtype5_capture(hold_q); | 
|  | // try and get both the we and the de at the same time, we should win | 
|  | hold_wd = 32'haaaaaaaa; | 
|  | fork | 
|  | begin | 
|  | send_wr(12'h22c, hold_wd); | 
|  | end | 
|  | begin | 
|  | hw2reg.rwtype5.de <= 1'b1; | 
|  | hw2reg.rwtype5.d  <= 32'h55555555; | 
|  | @(posedge clk); | 
|  | hw2reg.rwtype5.de <= 1'b0; | 
|  | hw2reg.rwtype5.d  <= 32'hxxxxxxxx; | 
|  | end | 
|  | join | 
|  | @(posedge clk); | 
|  | test_rwtype5(hold_wd); | 
|  | test_rwtype5_capture(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE6, RW + HRW + HWEXT | 
|  | // create a true external register | 
|  | // | 
|  | // default value is 0xc8c8c8c8 | 
|  | test_rwtype6(32'hc8c8c8c8); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h230, hold_wd); | 
|  | test_rwtype6(hold_wd); | 
|  | test_rwtype6_capture(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h230, hold_wd); | 
|  | test_rwtype6(hold_wd); | 
|  | test_rwtype6_capture(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test ROTYPE1, RO + HRW + HWEXT | 
|  | // create a true external register, writable only by us | 
|  | // | 
|  | // default value is 0x66aa66aa | 
|  | hold_q = 32'h66aa66aa; | 
|  | test_rotype1(hold_q); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h234, hold_wd); | 
|  | test_rotype1(hold_q); | 
|  | test_rotype1_capture(hold_q); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h234, hold_wd); | 
|  | test_rotype1(hold_q); | 
|  | test_rotype1_capture(hold_q); | 
|  | // simulate write from our side | 
|  | @(posedge clk); | 
|  | hold_wd = 32'h66778899; | 
|  | my_rotype1_de = 1'b1; | 
|  | my_rotype1_d = hold_wd; | 
|  | @(posedge clk); | 
|  | my_rotype1_de = 1'b0; | 
|  | my_rotype1_d = 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rotype1(hold_wd); | 
|  | test_rotype1_capture(hold_wd); | 
|  | @(posedge clk); | 
|  | hold_wd = ~32'h66778899; | 
|  | my_rotype1_de = 1'b1; | 
|  | my_rotype1_d = hold_wd; | 
|  | @(posedge clk); | 
|  | my_rotype1_de = 1'b0; | 
|  | my_rotype1_d = 32'hxxxxxxxx; | 
|  | @(posedge clk); | 
|  | test_rotype1(hold_wd); | 
|  | test_rotype1_capture(hold_wd); | 
|  | /////// | 
|  | // | 
|  | // test ROTYPE2, RO + HWNONE | 
|  | // | 
|  | // constant value is 0x9b908a79 | 
|  | hold_q = 32'h9b908a79; | 
|  | test_rotype2(hold_q); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h238, hold_wd); | 
|  | test_rotype2(hold_q); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h238, hold_wd); | 
|  | test_rotype2(hold_q); | 
|  | /////// | 
|  | // | 
|  | // test RWTYPE7, RW + HWNONE | 
|  | // | 
|  | // default value is 0xf6f6f6f6 | 
|  | test_rwtype7(32'hf6f6f6f6); | 
|  | // write value | 
|  | hold_wd = 32'hdeadbeef; | 
|  | send_wr(12'h23c, hold_wd); | 
|  | test_rwtype7(hold_wd); | 
|  | // write opposite | 
|  | hold_wd = ~32'hdeadbeef; | 
|  | send_wr(12'h23c, hold_wd); | 
|  | test_rwtype7(hold_wd); | 
|  |  | 
|  | $display("INFO: test completed with %d errors", errorcount); | 
|  | dv_test_status_pkg::dv_test_status(.passed(errorcount == 0)); | 
|  | end | 
|  |  | 
|  | endmodule |