Corrected the last testbenches, added a new testbench for the spi_master

since the original one was folded into the sysctrl testbench, but that
testbench no longer uses the SPI master.  Moved the SPI master from being
an overlay of the housekeeping SPI to occupying GPIO pins 32 to 35.
Made GPIO 35 a bidirectional pin like 36 and 37 so that the output enable
from the SPI master can be used.
This commit is contained in:
Tim Edwards 2021-10-21 19:48:24 -04:00
parent 43ced83bd8
commit e474dbbc99
7 changed files with 621 additions and 99 deletions

View File

@ -0,0 +1,86 @@
# SPDX-FileCopyrightText: 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
PDK_PATH = $(PDK_ROOT)/sky130A
VERILOG_PATH = ../../../..
RTL_PATH = $(VERILOG_PATH)/rtl
BEHAVIOURAL_MODELS = ../../
# Temporary: Path to management SoC wrapper repository
MGMT_WRAPPER_PATH = ~/gits/caravel_pico/verilog/rtl
FIRMWARE_PATH = ../..
GCC_PATH?=/ef/apps/bin
GCC_PREFIX?=riscv32-unknown-elf
SIM_DEFINES = -DFUNCTIONAL -DSIM
SIM?=RTL
.SUFFIXES:
PATTERN = spi_master
all: ${PATTERN:=.vcd}
hex: ${PATTERN:=.hex}
%.vvp: %_tb.v %.hex
ifeq ($(SIM),RTL)
iverilog -Ttyp $(SIM_DEFINES) -I $(BEHAVIOURAL_MODELS) \
-I $(PDK_PATH) -I $(RTL_PATH) -I $(MGMT_WRAPPER_PATH) \
$< -o $@
else
iverilog -Ttyp $(SIM_DEFINES) -DGL -I $(BEHAVIOURAL_MODELS) \
-I $(PDK_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \
$< -o $@
endif
%.vcd: %.vvp
vvp $<
%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s check-env
${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
%.hex: %.elf
${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@
# to fix flash base address
sed -i 's/@10000000/@00000000/g' $@
%.bin: %.elf
${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
check-env:
ifndef PDK_ROOT
$(error PDK_ROOT is undefined, please export it before running make)
endif
ifeq (,$(wildcard $(PDK_ROOT)/sky130A))
$(error $(PDK_ROOT)/sky130A not found, please install pdk before running make)
endif
ifeq (,$(wildcard $(GCC_PATH)/$(GCC_PREFIX)-gcc ))
$(error $(GCC_PATH)/$(GCC_PREFIX)-gcc is not found, please export GCC_PATH and GCC_PREFIX before running make)
endif
# check for efabless style installation
ifeq (,$(wildcard $(PDK_ROOT)/sky130A/libs.ref/*/verilog))
SIM_DEFINES := ${SIM_DEFINES} -DEF_STYLE
endif
# ---- Clean ----
clean:
rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
.PHONY: clean hex all

View File

@ -0,0 +1,184 @@
/*
* SPDX-FileCopyrightText: 2020 Efabless Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* SPDX-License-Identifier: Apache-2.0
*/
#include "../../defs.h"
// --------------------------------------------------------
/*
* SPI master Test
* - Enables SPI master
* - Uses SPI master to talk to external SPI module
*/
void main()
{
int i;
uint32_t value;
reg_mprj_datal = 0;
// For SPI operation, GPIO 1 should be an input, and GPIOs 2 to 4
// should be outputs.
reg_mprj_io_34 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; // SDI
reg_mprj_io_35 = GPIO_MODE_MGMT_STD_BIDIRECTIONAL; // SDO
reg_mprj_io_33 = GPIO_MODE_MGMT_STD_OUTPUT; // CSB
reg_mprj_io_32 = GPIO_MODE_MGMT_STD_OUTPUT; // SCK
// Configure upper 16 bits of user GPIO for generating testbench
// checkpoints.
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;
// 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;
/* Apply configuration */
reg_mprj_xfer = 1;
while (reg_mprj_xfer == 1);
// Start test
reg_mprj_datal = 0xA0400000;
// 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: (unused)
reg_spimaster_config = 0x2002; // Enable, prescaler = 2,
// Apply stream read (0x40 + 0x03) and read back one byte
reg_spimaster_config = 0x3002; // Apply stream mode
reg_spimaster_data = 0xff; // Write 0xff (reset)
reg_spimaster_config = 0x2102; // Release CSB (ends stream mode)
reg_spimaster_config = 0x3002; // Apply stream mode
reg_spimaster_data = 0xab; // Write 0xab (wakeup)
reg_spimaster_config = 0x2102; // Release CSB (ends stream mode)
reg_spimaster_config = 0x3002; // Apply stream mode
reg_spimaster_data = 0x03; // Write 0x03 (read mode)
reg_spimaster_data = 0x00; // Write 0x00 (start address high byte)
reg_spimaster_data = 0x00; // Write 0x00 (start address middle byte)
reg_spimaster_data = 0x04; // Write 0x00 (start address low byte)
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0410000 | (value << 8); // 0x93
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0420000 | (value << 8); // 0x01
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0430000 | (value << 8); // 0x00
reg_spimaster_config = 0x2102; // Release CSB (ends stream mode)
reg_spimaster_config = 0x3002; // Apply stream mode
reg_spimaster_data = 0x03; // Write 0x03 (read mode)
reg_spimaster_data = 0x00; // Write 0x00 (start address low byte)
reg_spimaster_data = 0x00; // Write 0x00 (start address middle byte)
reg_spimaster_data = 0x08; // Write 0x08 (start address high byte)
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0440000 | (value << 8); // 0x13
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0450000 | (value << 8); // 0x02
reg_spimaster_config = 0x2102; // Release CSB (ends stream mode)
reg_spimaster_config = 0x3002; // Apply stream mode
reg_spimaster_data = 0x03; // Write 0x03 (read mode)
reg_spimaster_data = 0x00; // Write 0x00 (start address high byte)
reg_spimaster_data = 0x00; // Write 0x00 (start address middle byte)
reg_spimaster_data = 0xa0; // Write 0xa0 (start address low byte)
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0460000 | (value << 8); // 0x63
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0470000 | (value << 8); // 0x57
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0480000 | (value << 8); // 0xb5
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA0490000 | (value << 8); // 0x00
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA04a0000 | (value << 8); // 0x23
reg_spimaster_data = 0x00; // Write 0x00 for read
value = reg_spimaster_data; // Read back byte
// Write checkpoint
reg_mprj_datal = 0xA04b0000 | (value << 8); // 0x20
reg_spimaster_config = 0x2102; // Release CSB (ends stream mode)
reg_spimaster_config = 0x0002; // Disable the SPI master
// End test
reg_mprj_datal = 0xA0900000;
}

View File

@ -0,0 +1,236 @@
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
`timescale 1 ns / 1 ps
`include "__uprj_netlists.v"
`include "caravel_netlists.v"
`include "spiflash.v"
module spi_master_tb;
reg clock;
reg RSTB;
reg power1, power2;
wire gpio;
wire [15:0] checkbits;
wire [7:0] spivalue;
wire [37:0] mprj_io;
wire flash_csb;
wire flash_clk;
wire flash_io0;
wire flash_io1;
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
// would be the fast clock.
always #10 clock <= (clock === 1'b0);
initial begin
clock <= 0;
end
initial begin
$dumpfile("spi_master.vcd");
$dumpvars(0, spi_master_tb);
repeat (25) begin
repeat (1000) @(posedge clock);
$display("+1000 cycles");
end
$display("%c[1;31m",27);
`ifdef GL
$display ("Monitor: Timeout, Test SPI Master (GL) Failed");
`else
$display ("Monitor: Timeout, Test SPI Master (RTL) Failed");
`endif
$display("%c[0m",27);
$finish;
end
// Monitor
initial begin
wait(checkbits == 16'hA040);
`ifdef GL
$display("Monitor: Test SPI Master (GL) Started");
`else
$display("Monitor: Test SPI Master (RTL) Started");
`endif
wait(checkbits == 16'hA041);
$display(" SPI value = 0x%x (should be 0x93)", spivalue);
if(spivalue !== 32'h93) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA042);
$display(" SPI value = 0x%x (should be 0x01)", spivalue);
if(spivalue !== 32'h01) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA043);
$display(" SPI value = 0x%x (should be 0x00)", spivalue);
if(spivalue !== 32'h00) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA044);
$display(" SPI value = 0x%x (should be 0x13)", spivalue);
if(spivalue !== 32'h13) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA045);
$display(" SPI value = 0x%x (should be 0x02)", spivalue);
if(spivalue !== 32'h02) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA046);
$display(" SPI value = 0x%x (should be 0x63)", spivalue);
if(spivalue !== 32'h63) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA047);
$display(" SPI value = 0x%x (should be 0x57)", spivalue);
if(spivalue !== 32'h57) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA048);
$display(" SPI value = 0x%x (should be 0xb5)", spivalue);
if(spivalue !== 32'hb5) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA049);
$display(" SPI value = 0x%x (should be 0x00)", spivalue);
if(spivalue !== 32'h00) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA04a);
$display(" SPI value = 0x%x (should be 0x23)", spivalue);
if(spivalue !== 32'h23) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA04b);
$display(" SPI value = 0x%x (should be 0x20)", spivalue);
if(spivalue !== 32'h20) begin
$display("Monitor: Test SPI Master Failed");
$finish;
end
wait(checkbits == 16'hA090);
`ifdef GL
$display("Monitor: Test SPI Master (GL) Passed");
`else
$display("Monitor: Test SPI Master (RTL) Passed");
`endif
$finish;
end
initial begin
RSTB <= 1'b0;
#1000;
RSTB <= 1'b1; // Release reset
#2000;
end
initial begin // Power-up sequence
power1 <= 1'b0;
power2 <= 1'b0;
#200;
power1 <= 1'b1;
#200;
power2 <= 1'b1;
end
always @(checkbits) begin
#1 $display("GPIO state = %b ", checkbits);
end
wire VDD3V3;
wire VDD1V8;
wire VSS;
assign VDD3V3 = power1;
assign VDD1V8 = power2;
assign VSS = 1'b0;
assign mprj_io[3] = 1'b1; // Keep 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),
.vssd1 (VSS),
.vssd2 (VSS),
.clock (clock),
.gpio (gpio),
.mprj_io (mprj_io),
.flash_csb(flash_csb),
.flash_clk(flash_clk),
.flash_io0(flash_io0),
.flash_io1(flash_io1),
.resetb (RSTB)
);
spiflash #(
.FILENAME("spi_master.hex")
) spiflash (
.csb(flash_csb),
.clk(flash_clk),
.io0(flash_io0),
.io1(flash_io1),
.io2(), // not used
.io3() // not used
);
/* Instantiate a 2nd SPI flash so the SPI master can talk to it */
spiflash #(
.FILENAME("spi_master.hex")
) test_spi (
.csb(mprj_io[33]),
.clk(mprj_io[32]),
.io0(mprj_io[35]),
.io1(mprj_io[34]),
.io2(), // not used
.io3() // not used
);
endmodule
`default_nettype wire

View File

@ -84,8 +84,8 @@ module timer_tb;
`endif
/* Add checks here */
wait(checkbits == 6'h01);
$display(" countbits = 0x%x (should be 0xdcba7cf9)", countbits);
if(countbits !== 32'hdcba7cf9) begin
$display(" countbits = 0x%x (should be 0xdcba7cfb)", countbits);
if(countbits !== 32'hdcba7cfb) begin
$display("Monitor: Test Timer Failed");
$finish;
end
@ -96,14 +96,14 @@ module timer_tb;
$finish;
end
wait(checkbits == 6'h03);
$display(" countbits = %x (should be 0x0d)", countbits);
if(countbits !== ((32'h0d) | (3'b100))) begin
$display(" countbits = %x (should be 0x0f)", countbits);
if(countbits !== ((32'h0f) | (3'b100))) begin
$display("Monitor: Test Timer Failed");
$finish;
end
wait(checkbits == 6'h04);
$display(" countbits = %x (should be 0x0d)", countbits);
if(countbits !== ((32'h0d) | (3'b100))) begin
$display(" countbits = %x (should be 0x0f)", countbits);
if(countbits !== ((32'h0f) | (3'b100))) begin
$display("Monitor: Test Timer Failed");
$finish;
end

View File

@ -82,8 +82,8 @@ module timer2_tb;
`endif
/* Add checks here */
wait(checkbits == 6'h01);
$display(" countbits = 0x%x (should be 0xdcba7cf9)", countbits);
if(countbits !== 32'hdcba7cf9) begin
$display(" countbits = 0x%x (should be 0xdcba7cfb)", countbits);
if(countbits !== 32'hdcba7cfb) begin
$display("Monitor: Test Timer2 (RTL) Failed");
$finish;
end
@ -94,14 +94,14 @@ module timer2_tb;
$finish;
end
wait(checkbits == 6'h03);
$display(" countbits = %x (should be 0x0d)", countbits);
if(countbits !== 32'h0d) begin
$display(" countbits = %x (should be 0x0f)", countbits);
if(countbits !== 32'h0f) begin
$display("Monitor: Test Timer (RTL) Failed");
$finish;
end
wait(checkbits == 6'h04);
$display(" countbits = %x (should be 0x0d)", countbits);
if(countbits !== 32'h0d) begin
$display(" countbits = %x (should be 0x0f)", countbits);
if(countbits !== 32'h0f) begin
$display("Monitor: Test Timer2 (RTL) Failed");
$finish;
end
@ -134,8 +134,8 @@ module timer2_tb;
end
wait(checkbits == 6'h10);
$display(" countbits = %x (should be 0x0008)", countbits);
if(countbits !== 32'h0008) begin
$display(" countbits = %x (should be 0x000a)", countbits);
if(countbits !== 32'h000a) begin
$display("Monitor: Test Timer2 (RTL) Failed");
$finish;
end

View File

@ -87,17 +87,21 @@ module caravel (
* FTDI chip sets these lines to high impedence (input function) at
* all times except when holding the chip in reset.
*
* JTAG = mprj_io[0] (inout)
* SDO = mprj_io[1] (output)
* SDI = mprj_io[2] (input)
* CSB = mprj_io[3] (input)
* SCK = mprj_io[4] (input)
* ser_rx = mprj_io[5] (input)
* ser_tx = mprj_io[6] (output)
* irq = mprj_io[7] (input)
* JTAG = mprj_io[0] (inout)
* SDO = mprj_io[1] (output)
* SDI = mprj_io[2] (input)
* CSB = mprj_io[3] (input)
* SCK = mprj_io[4] (input)
* ser_rx = mprj_io[5] (input)
* ser_tx = mprj_io[6] (output)
* irq = mprj_io[7] (input)
*
* flash_io2 = mprj_io[36] (inout)
* flash_io3 = mprj_io[37] (inout)
* spi_sck = mprj_io[32] (output)
* spi_csb = mprj_io[33] (output)
* spi_sdi = mprj_io[34] (input)
* spi_sdo = mprj_io[35] (output)
* flash_io2 = mprj_io[36] (inout)
* flash_io3 = mprj_io[37] (inout)
*
* These pins are reserved for any project that wants to incorporate
* its own processor and flash controller. While a user project can
@ -168,8 +172,8 @@ module caravel (
wire [`MPRJ_IO_PADS-1:0] mgmt_io_in; /* one- and three-pin data */
wire [`MPRJ_IO_PADS-5:0] mgmt_io_nc; /* no-connects */
wire [3:0] mgmt_io_out; /* three-pin interface out */
wire [3:0] mgmt_io_oeb; /* three-pin output enable */
wire [4:0] mgmt_io_out; /* three-pin interface out */
wire [4:0] mgmt_io_oeb; /* three-pin output enable */
wire clock_core;
@ -422,6 +426,7 @@ module caravel (
.spi_csb(spi_csb),
.spi_sck(spi_sck),
.spi_sdo(spi_sdo),
.spi_sdoenb(spi_sdoenb),
// Debug
.debug_in(debug_in),
.debug_out(debug_out),
@ -656,6 +661,7 @@ module caravel (
.spi_csb(spi_csb),
.spi_sck(spi_sck),
.spi_sdo(spi_sdo),
.spi_sdoenb(spi_sdoenb),
.debug_in(debug_in),
.debug_out(debug_out),
@ -670,9 +676,9 @@ module caravel (
.serial_data_2(mprj_io_loader_data_2),
.mgmt_gpio_in(mgmt_io_in),
.mgmt_gpio_out({mgmt_io_out[3:2], mgmt_io_in[`MPRJ_IO_PADS-3:2],
.mgmt_gpio_out({mgmt_io_out[4:2], mgmt_io_in[`MPRJ_IO_PADS-4:2],
mgmt_io_out[1:0]}),
.mgmt_gpio_oeb({mgmt_io_oeb[3:2], mgmt_io_nc[`MPRJ_IO_PADS-5:0],
.mgmt_gpio_oeb({mgmt_io_oeb[4:2], mgmt_io_nc[`MPRJ_IO_PADS-6:0],
mgmt_io_oeb[1:0]}),
.pwr_ctrl_out(), /* Not used in this version */
@ -739,7 +745,8 @@ module caravel (
/* First two GPIOs (JTAG and SDO) */
gpio_control_block #(
.MGMT_INIT(1'b1), // Management-controlled
.OENB_INIT(1'b1) // Output controlled from bidirectional pin
.OENB_INIT(1'b1), // Output controlled from bidirectional pin
.DM_INIT(3'b110) // Mode is set to ouput, no pullup/pulldown
) gpio_control_bidir_1 [1:0] (
`ifdef USE_POWER_PINS
.vccd(vccd_core),
@ -793,7 +800,6 @@ module caravel (
/* Section 1 GPIOs (GPIO 3 to 7) that start up under management control */
gpio_control_block #(
.DM_INIT(3'b001), // Configured as inputs
.MGMT_INIT(1'b1), // Management-controlled
.OENB_INIT(1'b1) // Output disabled
) gpio_control_in_1a [5:0] (
@ -893,11 +899,11 @@ module caravel (
);
/* Last two GPIOs (flash_io2 and flash_io3) */
/* Last three GPIOs (spi_sdo, flash_io2, and flash_io3) */
gpio_control_block #(
.MGMT_INIT(1'b1), // Management-controlled
.OENB_INIT(1'b1) // Output controlled from bidirectional pin
) gpio_control_bidir_2 [1:0] (
.OENB_INIT(1'b1) // Output controlled from bidirectional pin
) gpio_control_bidir_2 [2:0] (
`ifdef USE_POWER_PINS
.vccd(vccd_core),
.vssd(vssd_core),
@ -907,46 +913,46 @@ module caravel (
// Management Soc-facing signals
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-3)]),
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-3)]),
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-3)]),
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-3)]),
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.mgmt_gpio_out(mgmt_io_out[3:2]),
.mgmt_gpio_oeb(mgmt_io_oeb[3:2]),
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.mgmt_gpio_out(mgmt_io_out[4:2]),
.mgmt_gpio_oeb(mgmt_io_oeb[4:2]),
.one(),
.zero(),
// Serial data chain for pad configuration
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-3)]),
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-3)]),
// User-facing signals
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
// Pad-facing signals (Pad GPIOv2)
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-1):(`MPRJ_IO_PADS*3-6)]),
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)])
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-1):(`MPRJ_IO_PADS*3-9)]),
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)]),
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-3)])
);
/* Section 2 GPIOs (GPIO 19 to 37) */
wire [`MPRJ_IO_PADS_2-3:0] one_loop2;
gpio_control_block gpio_control_in_2 [`MPRJ_IO_PADS_2-3:0] (
/* Section 2 GPIOs (GPIO 19 to 34) */
wire [`MPRJ_IO_PADS_2-4:0] one_loop2;
gpio_control_block gpio_control_in_2 [`MPRJ_IO_PADS_2-4:0] (
`ifdef USE_POWER_PINS
.vccd(vccd_core),
.vssd(vssd_core),
@ -956,41 +962,41 @@ module caravel (
// Management Soc-facing signals
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-3):0]),
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-3):0]),
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-4):0]),
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-4):0]),
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-3):0]),
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-3):0]),
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-4):0]),
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-4):0]),
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.mgmt_gpio_out(mgmt_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.mgmt_gpio_out(mgmt_io_in[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.mgmt_gpio_oeb(one_loop2),
.one(one_loop2),
.zero(),
// Serial data chain for pad configuration
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-3):0]),
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-3):0]),
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-4):0]),
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-4):0]),
// User-facing signals
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
// Pad-facing signals (Pad GPIOv2)
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-7):(`MPRJ_IO_PADS_1*3)]),
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)])
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-10):(`MPRJ_IO_PADS_1*3)]),
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)]),
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-4):(`MPRJ_IO_PADS_1)])
);
user_id_programming #(

View File

@ -104,6 +104,7 @@ module housekeeping #(
input spi_csb,
input spi_sck,
input spi_sdo,
input spi_sdoenb,
// External (originating from SPI and pad) IRQ and reset
output [2:0] irq,
@ -258,12 +259,12 @@ module housekeeping #(
assign reset = (pass_thru_mgmt_reset) ? 1'b1 : reset_reg;
// Handle the management-side control of the GPIO pins. All but the
// first and last two GPIOs (0, 1 and 36, 37) are one-pin interfaces with
// first and last three GPIOs (0, 1 and 35 to 37) are one-pin interfaces with
// a single I/O pin whose direction is determined by the local OEB signal.
// The other four are straight-through connections of the 3-wire interface.
// The other five are straight-through connections of the 3-wire interface.
assign mgmt_gpio_out[`MPRJ_IO_PADS-1:`MPRJ_IO_PADS-2] =
mgmt_gpio_out_pre[`MPRJ_IO_PADS-1:`MPRJ_IO_PADS-2];
assign mgmt_gpio_out[`MPRJ_IO_PADS-1:`MPRJ_IO_PADS-3] =
mgmt_gpio_out_pre[`MPRJ_IO_PADS-1:`MPRJ_IO_PADS-3];
assign mgmt_gpio_out[1:0] = mgmt_gpio_out_pre[1:0];
genvar i;
@ -272,7 +273,7 @@ module housekeeping #(
// the first and last two GPIOs so that these pins can be tied together
// at the top level to create the single-wire interface on those GPIOs.
generate
for (i = 2; i < `MPRJ_IO_PADS-2; i = i + 1) begin
for (i = 2; i < `MPRJ_IO_PADS-3; i = i + 1) begin
assign mgmt_gpio_out[i] = mgmt_gpio_oeb[i] ? 1'bz : mgmt_gpio_out_pre[i];
end
endgenerate
@ -718,7 +719,7 @@ module housekeeping #(
.reset(~porb),
.SCK(mgmt_gpio_in[4]),
.SDI(mgmt_gpio_in[2]),
.CSB((hkspi_disable) ? 1'b1 : mgmt_gpio_in[3]),
.CSB((spi_is_active) ? mgmt_gpio_in[3] : 1'b1),
.SDO(sdo),
.sdoenb(sdo_enb),
.idata(odata),
@ -750,8 +751,21 @@ module housekeeping #(
~gpio_configure[37][INP_DIS];
assign mgmt_gpio_oeb[36] = (qspi_enabled) ? spimemio_flash_io2_oeb :
~gpio_configure[36][INP_DIS];
assign mgmt_gpio_oeb[35] = (spi_enabled) ? spi_sdoenb :
~gpio_configure[35][INP_DIS];
assign mgmt_gpio_out_pre[35:16] = mgmt_gpio_data[35:16];
// NOTE: Ignored by spimemio module when QSPI disabled, so they do not
// need any exception when qspi_enabled == 1.
assign spimemio_flash_io3_di = mgmt_gpio_in[37];
assign spimemio_flash_io2_di = mgmt_gpio_in[36];
// SPI master is assigned to the other 4 bits of the data high word.
assign mgmt_gpio_out_pre[32] = (spi_enabled) ? spi_sck : mgmt_gpio_data[32];
assign mgmt_gpio_out_pre[33] = (spi_enabled) ? spi_csb : mgmt_gpio_data[33];
assign mgmt_gpio_out_pre[34] = mgmt_gpio_data[34];
assign mgmt_gpio_out_pre[35] = (spi_enabled) ? spi_sdo : mgmt_gpio_data[35];
assign mgmt_gpio_out_pre[31:16] = mgmt_gpio_data[31:16];
assign mgmt_gpio_out_pre[12:11] = mgmt_gpio_data[12:11];
assign mgmt_gpio_out_pre[10] = (pass_thru_user) ? mgmt_gpio_in[2]
@ -763,30 +777,26 @@ module housekeeping #(
assign mgmt_gpio_out_pre[7] = mgmt_gpio_data[7];
assign mgmt_gpio_out_pre[6] = (uart_enabled) ? ser_tx : mgmt_gpio_data[6];
assign mgmt_gpio_out_pre[5] = mgmt_gpio_data[5];
assign mgmt_gpio_out_pre[4] = (spi_enabled) ? spi_sck : mgmt_gpio_data[4];
assign mgmt_gpio_out_pre[3] = (spi_enabled) ? spi_csb : mgmt_gpio_data[3];
assign mgmt_gpio_out_pre[2] = (spi_enabled) ? spi_sdo : mgmt_gpio_data[2];
assign mgmt_gpio_out_pre[5:2] = mgmt_gpio_data[5:2];
// In pass-through modes, route SDO from the respective flash (user or
// management SoC) to the dedicated SDO pin (GPIO[1])
assign mgmt_gpio_out_pre[1] = (pass_thru_mgmt) ? pad_flash_io1_di :
(pass_thru_user) ? mgmt_gpio_in[11] :
(spi_enabled) ? sdo : mgmt_gpio_data[1];
(spi_is_active) ? sdo : mgmt_gpio_data[1];
assign mgmt_gpio_out_pre[0] = (debug_mode) ? debug_out : mgmt_gpio_data[0];
assign mgmt_gpio_oeb[1] = (spi_enabled) ? sdo_enb : ~gpio_configure[0][INP_DIS];
assign mgmt_gpio_oeb[1] = (spi_is_active) ? sdo_enb : ~gpio_configure[0][INP_DIS];
assign mgmt_gpio_oeb[0] = (debug_mode) ? debug_oeb : ~gpio_configure[0][INP_DIS];
assign ser_rx = (uart_enabled) ? mgmt_gpio_in[5] : 1'b0;
assign spi_sdi = (spi_enabled) ? mgmt_gpio_in[1] : 1'b0;
assign spi_sdi = (spi_enabled) ? mgmt_gpio_in[34] : 1'b0;
assign debug_in = (debug_mode) ? mgmt_gpio_in[0] : 1'b0;
/* These are disconnected, but apply a meaningful signal anyway */
generate
for (i = 2; i < `MPRJ_IO_PADS-2; i = i + 1) begin
for (i = 2; i < `MPRJ_IO_PADS-3; i = i + 1) begin
assign mgmt_gpio_oeb[i] = ~gpio_configure[i][INP_DIS];
end
endgenerate