Fixed one bad error in clock_div which had been done without my

knowledge and which went undetected since before MPW-one.  Modified
the "pll" and "sysctrl" testbenches so that they run and measure
something useful.  Both exercise the clock monitoring on GPIO
outputs functions.  The PLL test also runs the digital locked
loop (behavioral verilog).  The PLL test overlaps sysctrl, but
"pll" cannot be run on gate level verilog, whereas "sysctrl" can.
This commit is contained in:
Tim Edwards 2021-12-06 21:37:51 -05:00
parent a9bb8bcd0a
commit d4b4b7abb8
5 changed files with 126 additions and 161 deletions

View File

@ -60,7 +60,6 @@ void main()
while (reg_mprj_xfer == 1);
// Start test
reg_mprj_datal = 0xA0400000;
/*
*-------------------------------------------------------------
@ -88,12 +87,14 @@ void main()
*-------------------------------------------------------------
*/
// Write checkpoint for clock counting (PLL bypassed)
reg_mprj_datal = 0xA0410000;
// Monitor the core clock and user clock on mprj_io[14] and mprj_io[15]
// reg_clk_out_dest = 0x6 to turn on, 0x0 to turn off
// Write checkpoint for clock counting (PLL bypassed)
reg_mprj_datal = 0xA0400000;
reg_clk_out_dest = 0x6;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0410000;
// Set PLL enable, no DCO mode
reg_hkspi_pll_ena = 0x1;
@ -103,6 +104,8 @@ void main()
// Write checkpoint for clock counting (PLL bypassed)
reg_mprj_datal = 0xA0420000;
reg_clk_out_dest = 0x6;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0430000;
// Disable PLL bypass
@ -110,6 +113,8 @@ void main()
// Write checkpoint for clock counting
reg_mprj_datal = 0xA0440000;
reg_clk_out_dest = 0x6;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0450000;
// Write 0x03 to feedback divider (was 0x04)
@ -117,6 +122,8 @@ void main()
// Write checkpoint
reg_mprj_datal = 0xA0460000;
reg_clk_out_dest = 0x6;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0470000;
// Write 0x04 to PLL output divider
@ -124,6 +131,8 @@ void main()
// Write checkpoint
reg_mprj_datal = 0xA0480000;
reg_clk_out_dest = 0x6;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0490000;
// End test

View File

@ -84,6 +84,10 @@ module pll_tb;
ccount = 0;
wait(checkbits == 16'hA041);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 129 || ccount != 129) begin
$display("Monitor: Test PLL Failed");
$finish;
end
wait(checkbits == 16'hA042);
$display("Monitor: Test 2 PLL (RTL) Started");
@ -91,6 +95,10 @@ module pll_tb;
ccount = 0;
wait(checkbits == 16'hA043);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 193 || ccount != 193) begin
$display("Monitor: Test PLL Failed");
$finish;
end
wait(checkbits == 16'hA044);
$display("Monitor: Test 3 PLL (RTL) Started");
@ -98,6 +106,10 @@ module pll_tb;
ccount = 0;
wait(checkbits == 16'hA045);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 385 || ccount != 129) begin
$display("Monitor: Test PLL Failed");
$finish;
end
wait(checkbits == 16'hA046);
$display("Monitor: Test 4 PLL (RTL) Started");
@ -105,6 +117,10 @@ module pll_tb;
ccount = 0;
wait(checkbits == 16'hA047);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 385 || ccount != 129) begin
$display("Monitor: Test PLL Failed");
$finish;
end
wait(checkbits == 16'hA048);
$display("Monitor: Test 5 PLL (RTL) Started");
@ -112,11 +128,15 @@ module pll_tb;
ccount = 0;
wait(checkbits == 16'hA049);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 513 || ccount != 129) begin
$display("Monitor: Test PLL Failed");
$finish;
end
wait(checkbits == 16'hA090);
$display("Monitor: Test PLL (RTL) Passed");
$finish;
$display("Monitor: Test PLL (RTL) Passed");
$finish;
end
initial begin

View File

@ -20,39 +20,23 @@
// --------------------------------------------------------
/*
* 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 mprj_io
* System control test
* - Sets GPIO to monitor the core and user clocks
*
* This test is basically just the first part of the
* PLL test, with the PLL bypassed. Unlike the PLL
* test, it can be run on a gate-level netlist.
*
*/
void main()
{
int i;
uint32_t value;
// Force housekeeping SPI into a disabled state so that the CSB
// pin can be used as an output without the system failing
reg_hkspi_disable = 1;
reg_mprj_datal = 0;
// Configure upper 6 bits of user GPIO for generating testbench
// Configure upper 16 bits of user GPIO for generating testbench
// checkpoints.
reg_mprj_io_37 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_36 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_35 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_34 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_33 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_32 = GPIO_MODE_MGMT_STD_OUTPUT;
// Configure all lower 32 bits for writing the SPI value read on GPIO
// NOTE: Converting reg_mprj_io_3 (CSB) to output will disable the
// SPI. But that should not disable the back-door access to the SPI
// register values!
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;
@ -70,71 +54,48 @@ void main()
reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT;
/* Monitor pins must be set to output */
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;
reg_mprj_io_7 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_5 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_4 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_3 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_2 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_1 = GPIO_MODE_MGMT_STD_OUTPUT;
reg_mprj_io_0 = GPIO_MODE_MGMT_STD_OUTPUT;
/* Apply configuration */
reg_mprj_xfer = 1;
while (reg_mprj_xfer == 1);
// Start test
reg_mprj_datah = 0x04;
// Read manufacturer and product ID
value = reg_hkspi_chip_id;
reg_mprj_datal = value; // Mfgr + product ID
reg_mprj_datah = 0x05;
/*
*-------------------------------------------------------------
* Register 2620_0004 reg_clk_out_dest
* SPI address 0x1b = Output redirect
* bit 0 = trap to mprj_io[13]
* bit 1 = clk to mprj_io[14]
* bit 2 = clk2 to mprj_io[15]
*-------------------------------------------------------------
*/
// Read user ID
value = reg_hkspi_user_id;
reg_mprj_datal = value; // User ID
reg_mprj_datah = 0x06;
// Monitor the core clock and user clock on mprj_io[14] and mprj_io[15]
// reg_clk_out_dest = 0x6 to turn on, 0x0 to turn off
// Read PLL enables
value = reg_hkspi_pll_ena;
reg_mprj_datal = value; // DLL enables
reg_mprj_datah = 0x07;
// Write checkpoint for making sure nothing is counted when monitoring is off
reg_mprj_datal = 0xA0400000;
reg_clk_out_dest = 0x0;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0410000;
// Read PLL bypass state
value = reg_hkspi_pll_bypass;
reg_mprj_datal = value; // DLL bypass state
reg_mprj_datah = 0x08;
// Write checkpoint for core clock counting (PLL bypassed)
reg_mprj_datal = 0xA0420000;
reg_clk_out_dest = 0x2;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0430000;
// Read PLL trim
value = reg_hkspi_pll_trim;
reg_mprj_datal = value; // DLL trim
reg_mprj_datah = 0x09;
// Read PLL source
value = reg_hkspi_pll_source;
reg_mprj_datal = value; // DLL source
reg_mprj_datah = 0x0a;
// Read PLL divider
value = reg_hkspi_pll_divider;
reg_mprj_datal = value; // DLL divider
reg_mprj_datah = 0x0b;
// Read a GPIO configuration word
value = reg_mprj_io_6;
reg_mprj_datal = value; // DLL divider
reg_mprj_datah = 0x0c;
// Write checkpoint for user clock counting (PLL bypassed)
reg_mprj_datal = 0xA0440000;
reg_clk_out_dest = 0x4;
reg_clk_out_dest = 0x0;
reg_mprj_datal = 0xA0450000;
// End test
reg_mprj_datah = 0x0d;
reg_mprj_datal = 0xA0900000;
}

View File

@ -23,13 +23,13 @@
module sysctrl_tb;
reg clock;
reg power1;
reg power2;
reg RSTB;
reg csb_set;
reg power1, power2;
wire gpio;
wire [5:0] checkbits;
wire [31:0] spivalue;
wire [15:0] checkbits;
wire [7:0] spivalue;
wire [37:0] mprj_io;
wire flash_csb;
wire flash_clk;
@ -37,11 +37,11 @@ module sysctrl_tb;
wire flash_io1;
wire SDO;
assign checkbits = mprj_io[37:32];
assign spivalue = mprj_io[31:0];
integer ccount;
integer ucount;
// mrpj_io[3] = CSB needs to be set until the program disables the SPI.
assign mprj_io[3] = (csb_set) ? 1'b1 : 1'bz;
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
@ -49,6 +49,16 @@ module sysctrl_tb;
always #10 clock <= (clock === 1'b0);
// User clock monitoring
always @(posedge mprj_io[15]) begin
ucount = ucount + 1;
end
// Core clock monitoring
always @(posedge mprj_io[14]) begin
ccount = ccount + 1;
end
initial begin
clock = 0;
end
@ -61,80 +71,50 @@ module sysctrl_tb;
$display("+1000 cycles");
end
$display("%c[1;31m",27);
`ifdef GL
$display ("Monitor: Timeout, Test Sysctrl (GL) Failed");
`else
$display ("Monitor: Timeout, Test Sysctrl (RTL) Failed");
`endif
$display("%c[0m",27);
$display ("Monitor: Timeout, Test Sysctrl (RTL) Failed");
$display("%c[0m",27);
$finish;
end
// Monitor
initial begin
wait(checkbits == 6'h04);
`ifdef GL
$display("Monitor: Test Sysctrl (GL) Started");
`else
$display("Monitor: Test Sysctrl (RTL) Started");
`endif
wait(checkbits == 6'h05);
$display(" Chip ID value = 0x%x (should be 0x00045611)", spivalue);
if(spivalue !== 32'h00045611) begin
wait(checkbits == 16'hA040);
$display("Monitor: Test 1 Sysctrl (RTL) Started");
ucount = 0;
ccount = 0;
wait(checkbits == 16'hA041);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 0 || ccount != 0) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 6'h06);
$display(" User ID value = 0x%x (should be 0x00000000)", spivalue);
if(spivalue !== 32'h00000000) begin
wait(checkbits == 16'hA042);
$display("Monitor: Test 1 Sysctrl (RTL) Started");
ucount = 0;
ccount = 0;
wait(checkbits == 16'hA043);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 129 || ccount != 0) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 6'h07);
$display(" PLL enables value = 0x%x (should be 0x00000002)", spivalue);
if(spivalue !== 32'h00000002) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 6'h08);
$display(" PLL bypass value = 0x%x (should be 0x00000001)", spivalue);
if(spivalue !== 32'h00000001) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 6'h09);
$display(" PLL trim value = 0x%x (should be 0x03ffefff)", spivalue);
if(spivalue !== 32'h03ffefff) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 6'h0a);
$display(" PLL divider value = 0x%x (should be 0x00000012)", spivalue);
if(spivalue !== 32'h00000012) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 6'h0b);
$display(" PLL source value = 0x%x (should be 0x00000004)", spivalue);
if(spivalue !== 32'h00000004) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 6'h0c);
$display(" GPIO config value = 0x%x (should be 0x00001809)", spivalue);
if(spivalue !== 32'h00001809) begin
wait(checkbits == 16'hA044);
$display("Monitor: Test 2 Sysctrl (RTL) Started");
ucount = 0;
ccount = 0;
wait(checkbits == 16'hA045);
$display("Monitor: ucount = %d ccount = %d", ucount, ccount);
if (ucount !== 0 || ccount != 129) begin
$display("Monitor: Test Sysctrl Failed");
$finish;
end
wait(checkbits == 16'hA090);
wait(checkbits == 6'h0d);
`ifdef GL
$display("Monitor: Test Sysctrl (GL) Passed");
`else
$display("Monitor: Test Sysctrl (RTL) Passed");
`endif
$finish;
$display("Monitor: Test Sysctrl (RTL) Passed");
$finish;
end
initial begin
@ -144,16 +124,13 @@ module sysctrl_tb;
#2000;
end
initial begin // Power-up sequence
initial begin
power1 <= 1'b0;
power2 <= 1'b0;
csb_set <= 1'b1;
#200;
power1 <= 1'b1;
#200;
power2 <= 1'b1;
#200000;
csb_set <= 1'b0; // Release CSB after SPI is disabled
end
always @(checkbits) begin
@ -168,21 +145,18 @@ module sysctrl_tb;
assign VDD1V8 = power2;
assign VSS = 1'b0;
assign mprj_io[3] = 1'b1; // Force CSB high.
caravel uut (
.vddio (VDD3V3),
.vddio_2 (VDD3V3),
.vssio (VSS),
.vssio_2 (VSS),
.vdda (VDD3V3),
.vssa (VSS),
.vccd (VDD1V8),
.vssd (VSS),
.vdda1 (VDD3V3),
.vdda1_2 (VDD3V3),
.vdda2 (VDD3V3),
.vssa1 (VSS),
.vssa1_2 (VSS),
.vssa2 (VSS),
.vccd1 (VDD1V8),
.vccd2 (VDD1V8),

View File

@ -102,9 +102,10 @@ module odd #(
end
reg [SIZE-1:0] initial_begin; // this is used to offset the negative edge counter
// wire [SIZE:0] interm_3; // from the positive edge counter in order to
// assign interm_3 = {1'b0,N} + 2'b11; // guarante 50% duty cycle.
localparam [SIZE:0] interm_3 = {1'b0,`CLK_DIV} + 2'b11;
wire [SIZE:0] interm_3; // from the positive edge counter in order to
assign interm_3 = {1'b0, N} + 2'b11; // guarantee 50% duty cycle.
localparam [SIZE:0] interm_init = {1'b0,`CLK_DIV} + 2'b11;
// Counter driven by negative edge of clock.
@ -112,7 +113,7 @@ module odd #(
if (resetb == 1'b0) begin
// reset the counter at system reset
counter2 <= `CLK_DIV;
initial_begin <= interm_3[SIZE:1];
initial_begin <= interm_init[SIZE:1];
out_counter2 <= 1;
end else if (rst_pulse) begin
// reset the counter at change of N.