mirror of https://github.com/efabless/caravel.git
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:
parent
a9bb8bcd0a
commit
d4b4b7abb8
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue