Modified code to let SPI master control the housekeeping SPI through a configuration bit setting in the SPI master. Revised the "sysctrl" testbench to work with the SPI master controlling the housekeeping SPI.
diff --git a/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl.c b/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl.c index 70b5b4a..3d2cefd 100644 --- a/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl.c +++ b/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl.c
@@ -2,46 +2,147 @@ // -------------------------------------------------------- -// NOTE: Testbench to be completed. Needs to use the new -// architecture in which the SPI master is enabled and used -// to access the housekeeping SPI directly as an SPI slave - /* * System Control Test + * - Enables SPI master + * - Uses SPI master to internally access the housekeeping SPI * - Reads default value of SPI-Controlled registers - * - Flags failure/success using gpio + * - Flags failure/success using mprj_io */ void main() { - int i; + int i; + uint32_t value; - reg_gpio_datal = 0; - reg_gpio_ena = 0x0000; + reg_mprj_datal = 0; - // start test - reg_gpio_datal = 0xA040; + // Configure upper 16 bits of user GPIO for generating testbench + // checkpoints. - // Read Product ID value - if(0x05 != reg_spi_prod_id) reg_gpio_datal = 0xAB40; - reg_gpio_datal = 0xAB41; + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; - // Read Manufacturer ID value - if(0x456 != reg_spi_mfgr_id) reg_gpio_datal = 0xAB50; - reg_gpio_datal = 0xAB51; + // Configure next 8 bits for writing the SPI value read on GPIO + reg_mprj_io_15 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_MGMT_STD_OUTPUT; - // Read Mask revision - if(0x1 != reg_spi_mask_rev) reg_gpio_datal = 0xAB60; - reg_gpio_datal = 0xAB61; + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); - // Read PLL-Bypass - if(0x1 != reg_spi_pll_bypass) reg_gpio_datal = 0xAB70; - reg_gpio_datal = 0xAB71; + // Start test + reg_mprj_datal = 0xA0400000; - if(0x7FFDFFF != reg_spi_pll_config) reg_gpio_datal = 0xAB80; - reg_gpio_datal = 0xAB81; + // Enable SPI master + // SPI master configuration bits: + // bits 7-0: Clock prescaler value (default 2) + // bit 8: MSB/LSB first (0 = MSB first, 1 = LSB first) + // bit 9: CSB sense (0 = inverted, 1 = noninverted) + // bit 10: SCK sense (0 = noninverted, 1 = inverted) + // bit 11: mode (0 = read/write opposite edges, 1 = same edges) + // bit 12: stream (1 = CSB ends transmission) + // bit 13: enable (1 = enabled) + // bit 14: IRQ enable (1 = enabled) + // bit 15: Connect to housekeeping SPI (1 = connected) - // Read spi enables - if(0x83 != reg_spi_enables) reg_gpio_datal = 0xAB90; - reg_gpio_datal = 0xAB91; + reg_spimaster_config = 0xa002; // Enable, prescaler = 2, + // connect to housekeeping SPI + + // Apply stream read (0x40 + 0x03) and read back one byte + + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x40; // Write 0x40 (read mode) + reg_spimaster_data = 0x01; // Write 0x01 (start address) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0410000 | (value << 8); // Mfgr ID (high) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0420000 | (value << 8); // Mfgr ID (low) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0430000 | (value << 8); // Prod ID + + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x40; // Write 0x40 (read mode) + reg_spimaster_data = 0x08; // Write 0x08 (start address) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0440000 | (value << 8); // PLL enable + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0450000 | (value << 8); // PLL bypass + + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x40; // Write 0x40 (read mode) + reg_spimaster_data = 0x0d; // Write 0x0d (start address) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0460000 | (value << 8); // PLL trim (2 high bits) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0470000 | (value << 8); // PLL trim (2nd byte) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0480000 | (value << 8); // PLL trim (3rd byte) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0490000 | (value << 8); // PLL trim (low byte) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA04a0000 | (value << 8); // PLL select (3 lowest bits) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA04b0000 | (value << 8); // PLL divider (5 lowest bits) + + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + reg_spimaster_config = 0x2102; // Release housekeeping SPI + + // End test + reg_mprj_datal = 0xA0900000; }
diff --git a/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl_tb.v b/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl_tb.v index c1a1e2a..adcbb48 100644 --- a/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl_tb.v +++ b/verilog/dv/caravel/mgmt_soc/sysctrl/sysctrl_tb.v
@@ -10,6 +10,7 @@ wire gpio; wire [15:0] checkbits; + wire [7:0] spivalue; wire [36:0] mprj_io; wire flash_csb; wire flash_clk; @@ -18,6 +19,7 @@ wire SDO; assign checkbits = mprj_io[31:16]; + assign spivalue = mprj_io[15:8]; // External clock is used by default. Make this artificially fast for the // simulation. Normally this would be a slow clock and the digital PLL @@ -42,72 +44,88 @@ $finish; end - always @(checkbits) begin - if(checkbits == 16'hA040) begin - $display("System control Test started"); - end - else if(checkbits == 16'hAB40) begin - $display("%c[1;31m",27); - $display("Monitor: System control (RTL) Test failed"); - $display("%c[0m",27); - $finish; - end - else if(checkbits == 16'hAB41) begin - $display("Monitor: System control product ID read passed"); - end - else if(checkbits == 16'hAB50) begin - $display("%c[1;31m",27); - $display("Monitor: System control manufacture ID read failed"); - $display("%c[0m",27); - $finish; - end else if(checkbits == 16'hAB51) begin - $display("Monitor: System control manufacture ID read passed"); - end - else if(checkbits == 16'hAB60) begin - $display("%c[1;31m",27); - $display("Monitor: System control mask rev read failed"); - $display("%c[0m",27); - $finish; - end else if(checkbits == 16'hAB61) begin - $display("Monitor: System control mask rev read passed"); - end - else if(checkbits == 16'hAB70) begin - $display("%c[1;31m",27); - $display("Monitor: System control pll-bypass read failed"); - $display("%c[0m",27); - $finish; - end else if(checkbits == 16'hAB71) begin - $display("Monitor: System control pll-bypass read passed"); - end - else if(checkbits == 16'hAB80) begin - $display("%c[1;31m",27); - $display("Monitor: System control pll-config read failed"); - $display("%c[0m",27); - $finish; - end else if(checkbits == 16'hAB81) begin - $display("Monitor: System control pll-config read passed"); - end - else if(checkbits == 16'hAB90) begin - $display("%c[1;31m",27); - $display("Monitor: System control spi-enables read failed"); - $display("%c[0m",27); - $finish; - end else if(checkbits == 16'hAB91) begin - $display("Monitor: System control spi-enables read passed"); - $display("Monitor: Sysctrl (RTL) test passed."); + // Monitor + initial begin + wait(checkbits == 16'hA040); + $display("Monitor: Test Sysctrl (RTL) Started"); + + wait(checkbits == 16'hA041); + $display(" SPI value = 0x%x (should be 0x04)", spivalue); + if(spivalue !== 32'h04) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA042); + $display(" SPI value = 0x%x (should be 0x56)", spivalue); + if(spivalue !== 32'h56) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA043); + $display(" SPI value = 0x%x (should be 0x10)", spivalue); + if(spivalue !== 32'h10) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA044); + $display(" SPI value = 0x%x (should be 0x01)", spivalue); + if(spivalue !== 32'h01) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA045); + $display(" SPI value = 0x%x (should be 0x01)", spivalue); + if(spivalue !== 32'h01) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA046); + $display(" SPI value = 0x%x (should be 0xff)", spivalue); + if(spivalue !== 32'hff) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA047); + $display(" SPI value = 0x%x (should be 0xef)", spivalue); + if(spivalue !== 32'hef) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA048); + $display(" SPI value = 0x%x (should be 0xff)", spivalue); + if(spivalue !== 32'hff) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA049); + $display(" SPI value = 0x%x (should be 0x03)", spivalue); + if(spivalue !== 32'h03) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA04a); + $display(" SPI value = 0x%x (should be 0x00)", spivalue); + if(spivalue !== 32'h00) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + wait(checkbits == 16'hA04b); + $display(" SPI value = 0x%x (should be 0x04)", spivalue); + if(spivalue !== 32'h04) begin + $display("Monitor: Test Sysctrl (RTL) Failed"); + $finish; + end + + wait(checkbits == 16'hA090); + $display("Monitor: Test Sysctrl (RTL) Passed"); $finish; - end end initial begin - CSB <= 1'b1; - SCK <= 1'b0; - SDI <= 1'b0; RSTB <= 1'b0; #1000; RSTB <= 1'b1; // Release reset #2000; - CSB <= 1'b0; // Apply CSB to start transmission end always @(checkbits) begin
diff --git a/verilog/rtl/housekeeping_spi.v b/verilog/rtl/housekeeping_spi.v index 8ae1b81..42677d4 100644 --- a/verilog/rtl/housekeeping_spi.v +++ b/verilog/rtl/housekeeping_spi.v
@@ -32,7 +32,7 @@ // Caravel defined registers: // Register 0: SPI status and control (unused & reserved) // Register 1 and 2: Manufacturer ID (0x0456) (readonly) -// Register 3: Product ID (= 2) (readonly) +// Register 3: Product ID (= 16) (readonly) // Register 4-7: Mask revision (readonly) --- Externally programmed // with via programming. Via programmed with a script to match // each customer ID.
diff --git a/verilog/rtl/mgmt_core.v b/verilog/rtl/mgmt_core.v index 49b29cd..297b76a 100644 --- a/verilog/rtl/mgmt_core.v +++ b/verilog/rtl/mgmt_core.v
@@ -77,6 +77,7 @@ wire ext_clk_sel; wire pll_clk; wire ext_reset; + wire hk_connect; caravel_clkrst clkrst( `ifdef LVS @@ -165,6 +166,8 @@ .pass_thru_mgmt_sck(pass_thru_mgmt_sck), .pass_thru_mgmt_sdi(pass_thru_mgmt_sdi), .pass_thru_mgmt_sdo(pass_thru_mgmt_sdo), + // SPI master->slave direct connection + .hk_connect(hk_connect), // Logic Analyzer .la_input(la_input), .la_output(la_output), @@ -229,9 +232,9 @@ .vss(vss), `endif .RSTB(porb), - .SCK(mgmt_in_data[4]), - .SDI(mgmt_in_data[2]), - .CSB(mgmt_in_data[3]), + .SCK((hk_connect) ? mgmt_out_data[4] : mgmt_in_data[4]), + .SDI((hk_connect) ? mgmt_out_data[2] : mgmt_in_data[2]), + .CSB((hk_connect) ? mgmt_out_data[3] : mgmt_in_data[3]), .SDO(sdo_out), .sdo_enb(sdo_outenb), .pll_dco_ena(spi_pll_dco_ena),
diff --git a/verilog/rtl/mgmt_soc.v b/verilog/rtl/mgmt_soc.v index e5375ff..5f1050d 100644 --- a/verilog/rtl/mgmt_soc.v +++ b/verilog/rtl/mgmt_soc.v
@@ -122,6 +122,9 @@ input pass_thru_mgmt_sdi, output pass_thru_mgmt_sdo, + // SPI master->slave direct link + output hk_connect, + // WB MI A (Mega project) input mprj_ack_i, input [31:0] mprj_dat_i, @@ -481,6 +484,7 @@ .wb_ack_o(spi_master_ack_o), .wb_dat_o(spi_master_dat_o), + .hk_connect(hk_connect), .csb(mgmt_out_pre[3]), .sck(mgmt_out_pre[4]), .sdi(mgmt_in_data[1]),
diff --git a/verilog/rtl/simple_spi_master.v b/verilog/rtl/simple_spi_master.v index a2a33b6..447f0f1 100755 --- a/verilog/rtl/simple_spi_master.v +++ b/verilog/rtl/simple_spi_master.v
@@ -46,6 +46,9 @@ // irqena: // 0 = disable interrupt // 1 = enable interrupt +// hkconn: +// 0 = housekeeping SPI disconnected +// 1 = housekeeping SPI connected (when SPI master enabled) // prescaler: count (in master clock cycles) of 1/2 SCK cycle. // // reg_dat_we: @@ -78,6 +81,7 @@ output wb_ack_o, output [31:0] wb_dat_o, + output hk_connect, // Connect to housekeeping SPI input sdi, // SPI input output csb, // SPI chip select output sck, // SPI clock @@ -118,6 +122,7 @@ .reg_dat_do(simple_spi_master_reg_dat_do), .reg_dat_wait(reg_dat_wait), + .hk_connect(hk_connect), // Attach to housekeeping SPI slave .sdi(sdi), // SPI input .csb(csb), // SPI chip select .sck(sck), // SPI clock @@ -142,6 +147,7 @@ output irq_out, output err_out, + output hk_connect, // Connect to housekeeping SPI input sdi, // SPI input output csb, // SPI chip select output sck, // SPI clock @@ -171,12 +177,14 @@ reg stream; reg mode; reg enable; + reg hkconn; wire csb; wire irq_out; wire sck; wire sdo; wire sdoenb; + wire hk_connect; // Define behavior for inverted SCK and inverted CSB assign csb = (enable == 1'b0) ? 1'bz : (invcsb) ? ~icsb : icsb; @@ -188,9 +196,11 @@ assign sdo = (enable == 1'b0) ? 1'bz : isdo; assign irq_out = irqena & done; + assign hk_connect = (enable == 1'b1) ? hkconn : 1'b0; // Read configuration and data registers - assign reg_cfg_do = {17'd0, irqena, enable, stream, mode, invsck, invcsb, mlb, prescaler}; + assign reg_cfg_do = {16'd0, hkconn, irqena, enable, stream, mode, + invsck, invcsb, mlb, prescaler}; assign reg_dat_wait = ~done; assign reg_dat_do = done ? rreg : ~0; @@ -205,6 +215,7 @@ irqena <= 1'b0; stream <= 1'b0; mode <= 1'b0; + hkconn <= 1'b0; end else begin if (reg_cfg_we[0]) prescaler <= reg_cfg_di[7:0]; if (reg_cfg_we[1]) begin @@ -215,6 +226,7 @@ stream <= reg_cfg_di[12]; enable <= reg_cfg_di[13]; irqena <= reg_cfg_di[14]; + hkconn <= reg_cfg_di[15]; end //reg_cfg_we[1] end //resetn end //always