| // 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 |