From 34e89e842cc0cda695542b376e8bbcfd72e53eb0 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 19 Jul 2024 11:35:12 -0500 Subject: [PATCH 01/39] Added initial spi code to fpga/zsbl --- fpga/zsbl/spi.c | 24 ++++++++++++++++++++++++ fpga/zsbl/spi.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 fpga/zsbl/spi.c create mode 100644 fpga/zsbl/spi.h diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c new file mode 100644 index 000000000..4c3885fd0 --- /dev/null +++ b/fpga/zsbl/spi.c @@ -0,0 +1,24 @@ +#include "spi.h" + +void write_reg(uintptr_t addr, uint32_t value) { + volatile uint32_t * loc = (volatile uint32_t *) addr; + *loc = value; +} + +// Initialize Sifive FU540 based SPI Controller +void spi_init() { + // Disable interrupts by default + // write_reg(SPI_IE, 0); + + write_reg(SPI_TXMARK, 1); + write_reg(SPI_RXMARK, 0); + + write_reg(SPI_DELAY0, + SIFIVE_SPI_DELAY0_CSSCK(1) | + SIFIVE_SPI_DELAY0_SCKCS(1)); + + write_reg(SPI_DELAY1, + SIFIVE_SPI_DELAY1_INTERCS(1) | + SIFIVE_SPI_DELAY1_INTERXFR(0)); +} + diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h new file mode 100644 index 000000000..97f3d58c3 --- /dev/null +++ b/fpga/zsbl/spi.h @@ -0,0 +1,45 @@ +#pragma once +#ifndef SPI_HEADER +#define SPI_HEADER + +#include + +/* register offsets */ +#define SPI_SCKDIV 0x00 /* Serial clock divisor */ +#define SPI_SCKMODE 0x04 /* Serial clock mode */ +#define SPI_CSID 0x10 /* Chip select ID */ +#define SPI_CSDEF 0x14 /* Chip select default */ +#define SPI_CSMODE 0x18 /* Chip select mode */ +#define SPI_DELAY0 0x28 /* Delay control 0 */ +#define SPI_DELAY1 0x2c /* Delay control 1 */ +#define SPI_FMT 0x40 /* Frame format */ +#define SPI_TXDATA 0x48 /* Tx FIFO data */ +#define SPI_RXDATA 0x4c /* Rx FIFO data */ +#define SPI_TXMARK 0x50 /* Tx FIFO [<35;39;29Mwatermark */ +#define SPI_RXMARK 0x54 /* Rx FIFO watermark */ + +/* Non-implemented +#define SPI_FCTRL 0x60 // SPI flash interface control +#define SPI_FFMT 0x64 // SPI flash instruction format +*/ +#define SPI_IE 0x70 /* Interrupt Enable Register */ +#define SPI_IP 0x74 /* Interrupt Pendings Register */ + +/* delay0 bits */ +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) + +/* delay1 bits */ +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) + +void write_reg(uintptr_t addr, uint32_t value); +uint32_t read_reg(uintptr_t addr); +void spi_send_byte(uint8_t byte); +void spi_init(); + +#endif From 53b2a51c8967d29a84d83f66a90c72a3b262d590 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 19 Jul 2024 12:30:32 -0500 Subject: [PATCH 02/39] Added tentative spi_send_byte function. --- fpga/zsbl/spi.c | 27 +++++++++++++++++++++++++++ fpga/zsbl/spi.h | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 4c3885fd0..1400b8881 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -5,6 +5,10 @@ void write_reg(uintptr_t addr, uint32_t value) { *loc = value; } +void read_red(uintptr_t addr) { + return *(volatile uint32_t *) addr; +} + // Initialize Sifive FU540 based SPI Controller void spi_init() { // Disable interrupts by default @@ -22,3 +26,26 @@ void spi_init() { SIFIVE_SPI_DELAY1_INTERXFR(0)); } +// Sends and receives a single byte +uint8_t spi_send_byte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); + + /* Not sure how necessary this is. Will keep commented for now. + // Wait a decent amount of time for data to send + for (int i = 0; i < 100; i++) { + __asm__ volatile("nop"); + } + */ + + // Wait for data to come into receive fifo + while (read_reg(SPI_IP) != 2) {} + + // Read received data + result = read_reg(SPI_RXDATA); + + // Return result + return result; +} + + diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index 97f3d58c3..2bd2003c5 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -39,7 +39,7 @@ void write_reg(uintptr_t addr, uint32_t value); uint32_t read_reg(uintptr_t addr); -void spi_send_byte(uint8_t byte); +uint8_t spi_send_byte(uint8_t byte); void spi_init(); #endif From c7d869bc96022e4731fa305ec94c9e6e881f4dce Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Sat, 20 Jul 2024 14:00:43 -0500 Subject: [PATCH 03/39] Added inital spi based sd card code. Working on CRC7 code that works. --- fpga/zsbl/sd.c | 31 +++++++++++++++++++++++++++++++ fpga/zsbl/sd.h | 9 +++++++++ fpga/zsbl/spi.c | 1 - fpga/zsbl/spi.h | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 fpga/zsbl/sd.c create mode 100644 fpga/zsbl/sd.h diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c new file mode 100644 index 000000000..4ffb53d67 --- /dev/null +++ b/fpga/zsbl/sd.c @@ -0,0 +1,31 @@ +#include "sd.h" +#include "spi.h" + +uint8_t crc7(uint8_t prev, uint8_t in) { + // CRC polynomial 0x89 + uint8_t remainder = prev & in; + remainder ^= (remainder >> 4) ^ (remainder >> 7); + remainder ^= remainder << 4; + return remainder & 0x7f; +} + +uint16_t crc16(uint16_t crc, uint8_t data) { + // CRC polynomial 0x11021 + crc = (uint8_t)(crc >> 8) | (crc << 8); + crc ^= data; + crc ^= (uint8_t)(crc >> 4) & 0xf; + crc ^= crc << 12; + crc ^= (crc & 0xff) << 5; + return crc; +} + +uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { + spi_send_byte +} + +void init_sd(){ + init_spi(); + + +} + diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h new file mode 100644 index 000000000..b1b27db14 --- /dev/null +++ b/fpga/zsbl/sd.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +uint8_t crc7(uint8_t prev, uint8_t in); +uint16_t crc16(uint16_t crc, uint8_t data); +uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); +void init_sd(); + diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 1400b8881..bf6d629b4 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -48,4 +48,3 @@ uint8_t spi_send_byte(uint8_t byte) { return result; } - diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index 2bd2003c5..6bae450ae 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -40,6 +40,7 @@ void write_reg(uintptr_t addr, uint32_t value); uint32_t read_reg(uintptr_t addr); uint8_t spi_send_byte(uint8_t byte); + void spi_init(); #endif From e91d2c8b1457efbcceb0efd769a850b9b5422ba0 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 22 Jul 2024 01:19:10 -0500 Subject: [PATCH 04/39] Corrected the CRC7 code with the right sequence of instructions. --- fpga/zsbl/sd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 4ffb53d67..8781dd5c3 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,12 +1,15 @@ #include "sd.h" #include "spi.h" +// Parallel byte update CRC7-CCITT algorithm. +// The result is the CRC7 result, left shifted over by 1 +// which is perfect, since we append a 1 at the end anyway uint8_t crc7(uint8_t prev, uint8_t in) { // CRC polynomial 0x89 - uint8_t remainder = prev & in; + uint8_t remainder = prev ^ in; remainder ^= (remainder >> 4) ^ (remainder >> 7); - remainder ^= remainder << 4; - return remainder & 0x7f; + remainder = (remainder << 1) ^ (remainder << 4); + return remainder & 0xff; } uint16_t crc16(uint16_t crc, uint8_t data) { From a506d76149f83faeb96acb52efd10c4fe6265ea1 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 22 Jul 2024 12:36:39 -0500 Subject: [PATCH 05/39] Removed the old SDC. Added a second SPI peripheral that now will be used to control the SD card. SPI peripheral now outputs SPICLK. Removed references to the now non-existent external SDC in uncore. Removed all of the AXI Xilinx IP. --- fpga/src/fpgaTopArtyA7.sv | 828 ++++----------------------------- src/uncore/spi_apb.sv | 17 +- src/uncore/uncore.sv | 47 +- src/wally/wallypipelinedsoc.sv | 10 +- 4 files changed, 144 insertions(+), 758 deletions(-) diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 9ddf958a7..6a2f055ba 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -29,38 +29,43 @@ import cvw::*; module fpgaTop - (input default_100mhz_clk, -(* mark_debug = "true" *) input resetn, - input south_reset, + (input default_100mhz_clk, + input resetn, + input south_reset, - input [3:0] GPI, - output [4:0] GPO, + // GPIO signals + input [3:0] GPI, + output [4:0] GPO, - input UARTSin, - output UARTSout, + // UART Signals + input UARTSin, + output UARTSout, - inout [3:0] SDCDat, - output SDCCLK, - inout SDCCmd, - input SDCCD, + // SDC Signals connecting to an SPI peripheral + input [3:0] SDCDat, + output SDCCLK, + output SDCCmd, + output SDCCD, - inout [15:0] ddr3_dq, - inout [1:0] ddr3_dqs_n, - inout [1:0] ddr3_dqs_p, - output [13:0] ddr3_addr, - output [2:0] ddr3_ba, - output ddr3_ras_n, - output ddr3_cas_n, - output ddr3_we_n, - output ddr3_reset_n, - output [0:0] ddr3_ck_p, - output [0:0] ddr3_ck_n, - output [0:0] ddr3_cke, - output [0:0] ddr3_cs_n, - output [1:0] ddr3_dm, - output [0:0] ddr3_odt + // Memory signals + inout [15:0] ddr3_dq, + inout [1:0] ddr3_dqs_n, + inout [1:0] ddr3_dqs_p, + output [13:0] ddr3_addr, + output [2:0] ddr3_ba, + output ddr3_ras_n, + output ddr3_cas_n, + output ddr3_we_n, + output ddr3_reset_n, + output [0:0] ddr3_ck_p, + output [0:0] ddr3_ck_n, + output [0:0] ddr3_cke, + output [0:0] ddr3_cs_n, + output [1:0] ddr3_dm, + output [0:0] ddr3_odt ); + // MMCM Signals wire CPUCLK; wire c0_ddr4_ui_clk_sync_rst; wire bus_struct_reset; @@ -69,6 +74,7 @@ module fpgaTop wire peripheral_aresetn; wire mb_reset; + // AHB Signals from Wally wire HCLKOpen; wire HRESETnOpen; wire [63:0] HRDATAEXT; @@ -87,12 +93,10 @@ module fpgaTop wire [3:0] HPROT; wire HMASTLOCK; + // GPIO Signals wire [31:0] GPIOIN, GPIOOUT, GPIOEN; - wire SDCCmdIn; - wire SDCCmdOE; - wire SDCCmdOut; - + // AHB to AXI Bridge Signals wire [3:0] m_axi_awid; wire [7:0] m_axi_awlen; wire [2:0] m_axi_awsize; @@ -100,40 +104,40 @@ module fpgaTop wire [3:0] m_axi_awcache; wire [31:0] m_axi_awaddr; wire [2:0] m_axi_awprot; - wire m_axi_awvalid; - wire m_axi_awready; - wire m_axi_awlock; + wire m_axi_awvalid; + wire m_axi_awready; + wire m_axi_awlock; wire [63:0] m_axi_wdata; wire [7:0] m_axi_wstrb; - wire m_axi_wlast; - wire m_axi_wvalid; - wire m_axi_wready; + wire m_axi_wlast; + wire m_axi_wvalid; + wire m_axi_wready; wire [3:0] m_axi_bid; wire [1:0] m_axi_bresp; - wire m_axi_bvalid; - wire m_axi_bready; + wire m_axi_bvalid; + wire m_axi_bready; wire [3:0] m_axi_arid; wire [7:0] m_axi_arlen; wire [2:0] m_axi_arsize; wire [1:0] m_axi_arburst; wire [2:0] m_axi_arprot; wire [3:0] m_axi_arcache; - wire m_axi_arvalid; + wire m_axi_arvalid; wire [31:0] m_axi_araddr; wire m_axi_arlock; - wire m_axi_arready; + wire m_axi_arready; wire [3:0] m_axi_rid; wire [63:0] m_axi_rdata; wire [1:0] m_axi_rresp; - wire m_axi_rvalid; - wire m_axi_rlast; - wire m_axi_rready; + wire m_axi_rvalid; + wire m_axi_rlast; + wire m_axi_rready; + // AXI Signals going out of Clock Converter wire [3:0] BUS_axi_arregion; wire [3:0] BUS_axi_arqos; wire [3:0] BUS_axi_awregion; wire [3:0] BUS_axi_awqos; - wire [3:0] BUS_axi_awid; wire [7:0] BUS_axi_awlen; wire [2:0] BUS_axi_awsize; @@ -173,250 +177,10 @@ module fpgaTop wire BUSCLK; wire sdio_reset_open; - // Crossbar to Bus ------------------------------------------------ - - wire s00_axi_aclk; - wire s00_axi_aresetn; - wire [3:0] s00_axi_awid; - wire [31:0]s00_axi_awaddr; - wire [7:0]s00_axi_awlen; - wire [2:0]s00_axi_awsize; - wire [1:0]s00_axi_awburst; - wire [0:0]s00_axi_awlock; - wire [3:0]s00_axi_awcache; - wire [2:0]s00_axi_awprot; - wire [3:0]s00_axi_awregion; - wire [3:0]s00_axi_awqos; - wire s00_axi_awvalid; - wire s00_axi_awready; - wire [63:0]s00_axi_wdata; - wire [7:0]s00_axi_wstrb; - wire s00_axi_wlast; - wire s00_axi_wvalid; - wire s00_axi_wready; - wire [1:0]s00_axi_bresp; - wire s00_axi_bvalid; - wire s00_axi_bready; - wire [3:0] s00_axi_arid; - wire [31:0]s00_axi_araddr; - wire [7:0]s00_axi_arlen; - wire [2:0]s00_axi_arsize; - wire [1:0]s00_axi_arburst; - wire [0:0]s00_axi_arlock; - wire [3:0]s00_axi_arcache; - wire [2:0]s00_axi_arprot; - wire [3:0]s00_axi_arregion; - wire [3:0]s00_axi_arqos; - wire s00_axi_arvalid; - wire s00_axi_arready; - wire [63:0]s00_axi_rdata; - wire [1:0]s00_axi_rresp; - wire s00_axi_rlast; - wire s00_axi_rvalid; - wire s00_axi_rready; - - wire [3:0] s00_axi_bid; - wire [3:0] s00_axi_rid; - - // 64to32 dwidth converter input interface------------------------- - wire s01_axi_aclk; - wire s01_axi_aresetn; - wire [3:0]s01_axi_awid; - wire [31:0]s01_axi_awaddr; - wire [7:0]s01_axi_awlen; - wire [2:0]s01_axi_awsize; - wire [1:0]s01_axi_awburst; - wire [0:0]s01_axi_awlock; - wire [3:0]s01_axi_awcache; - wire [2:0]s01_axi_awprot; - wire [3:0]s01_axi_awregion; - wire [3:0]s01_axi_awqos; // qos signals need to be 0 for SDC - wire s01_axi_awvalid; - wire s01_axi_awready; - wire [63:0]s01_axi_wdata; - wire [7:0]s01_axi_wstrb; - wire s01_axi_wlast; - wire s01_axi_wvalid; - wire s01_axi_wready; - wire [1:0]s01_axi_bresp; - wire s01_axi_bvalid; - wire s01_axi_bready; - wire [31:0]s01_axi_araddr; - wire [7:0]s01_axi_arlen; - wire [3:0] s01_axi_arid; - wire [2:0]s01_axi_arsize; - wire [1:0]s01_axi_arburst; - wire [0:0]s01_axi_arlock; - wire [3:0]s01_axi_arcache; - wire [2:0]s01_axi_arprot; - wire [3:0]s01_axi_arregion; - wire [3:0]s01_axi_arqos; // - wire s01_axi_arvalid; - wire s01_axi_arready; - wire [63:0]s01_axi_rdata; - wire [1:0]s01_axi_rresp; - wire s01_axi_rlast; - wire s01_axi_rvalid; - wire s01_axi_rready; - - // Output Interface - wire [31:0]axi4in_axi_awaddr; - wire [7:0]axi4in_axi_awlen; - wire [2:0]axi4in_axi_awsize; - wire [1:0]axi4in_axi_awburst; - wire [0:0]axi4in_axi_awlock; - wire [3:0]axi4in_axi_awcache; - wire [2:0]axi4in_axi_awprot; - wire [3:0]axi4in_axi_awregion; - wire [3:0]axi4in_axi_awqos; - wire axi4in_axi_awvalid; - wire axi4in_axi_awready; - wire [31:0]axi4in_axi_wdata; - wire [3:0]axi4in_axi_wstrb; - wire axi4in_axi_wlast; - wire axi4in_axi_wvalid; - wire axi4in_axi_wready; - wire [1:0]axi4in_axi_bresp; - wire axi4in_axi_bvalid; - wire axi4in_axi_bready; - wire [31:0]axi4in_axi_araddr; - wire [7:0]axi4in_axi_arlen; - wire [2:0]axi4in_axi_arsize; - wire [1:0]axi4in_axi_arburst; - wire [0:0]axi4in_axi_arlock; - wire [3:0]axi4in_axi_arcache; - wire [2:0]axi4in_axi_arprot; - wire [3:0]axi4in_axi_arregion; - wire [3:0]axi4in_axi_arqos; - wire axi4in_axi_arvalid; - wire axi4in_axi_arready; - wire [31:0]axi4in_axi_rdata; - wire [1:0]axi4in_axi_rresp; - wire axi4in_axi_rlast; - wire axi4in_axi_rvalid; - wire axi4in_axi_rready; - - // AXI4 to AXI4-Lite Protocol converter output - wire [31:0]SDCin_axi_awaddr; - wire [2:0]SDCin_axi_awprot; - wire SDCin_axi_awvalid; - wire SDCin_axi_awready; - wire [31:0]SDCin_axi_wdata; - wire [3:0]SDCin_axi_wstrb; - wire SDCin_axi_wvalid; - wire SDCin_axi_wready; - wire [1:0]SDCin_axi_bresp; - wire SDCin_axi_bvalid; - wire SDCin_axi_bready; - wire [31:0]SDCin_axi_araddr; - wire [2:0]SDCin_axi_arprot; - wire SDCin_axi_arvalid; - wire SDCin_axi_arready; - wire [31:0]SDCin_axi_rdata; - wire [1:0]SDCin_axi_rresp; - wire SDCin_axi_rvalid; - wire SDCin_axi_rready; - // ---------------------------------------------------------------- - - // 32to64 dwidth converter input interface ----------------------- - wire [31:0]SDCout_axi_awaddr; - wire [7:0]SDCout_axi_awlen; - wire [2:0]SDCout_axi_awsize; - wire [1:0]SDCout_axi_awburst; - wire [0:0]SDCout_axi_awlock; - wire [3:0]SDCout_axi_awcache; - wire [2:0]SDCout_axi_awprot; - wire [3:0]SDCout_axi_awregion; - wire [3:0]SDCout_axi_awqos; - wire SDCout_axi_awvalid; - wire SDCout_axi_awready; - wire [31:0]SDCout_axi_wdata; - wire [3:0]SDCout_axi_wstrb; - wire SDCout_axi_wlast; - wire SDCout_axi_wvalid; - wire SDCout_axi_wready; - wire [1:0]SDCout_axi_bresp; - wire SDCout_axi_bvalid; - wire SDCout_axi_bready; - wire [31:0]SDCout_axi_araddr; - wire [7:0]SDCout_axi_arlen; - wire [2:0]SDCout_axi_arsize; - wire [1:0]SDCout_axi_arburst; - wire [0:0]SDCout_axi_arlock; - wire [3:0]SDCout_axi_arcache; - wire [2:0]SDCout_axi_arprot; - wire [3:0]SDCout_axi_arregion; - wire [3:0]SDCout_axi_arqos; - wire SDCout_axi_arvalid; - wire SDCout_axi_arready; - wire [31:0]SDCout_axi_rdata; - wire [1:0]SDCout_axi_rresp; - wire SDCout_axi_rlast; - wire SDCout_axi_rvalid; - wire SDCout_axi_rready; - - // Output Interface - wire [3:0]m01_axi_awid; - wire [31:0]m01_axi_awaddr; - wire [7:0]m01_axi_awlen; - wire [2:0]m01_axi_awsize; - wire [1:0]m01_axi_awburst; - wire [0:0]m01_axi_awlock; - wire [3:0]m01_axi_awcache; - wire [2:0]m01_axi_awprot; - wire [3:0]m01_axi_awregion; - wire [3:0]m01_axi_awqos; - wire m01_axi_awvalid; - wire m01_axi_awready; - wire [63:0]m01_axi_wdata; - wire [7:0]m01_axi_wstrb; - wire m01_axi_wlast; - wire m01_axi_wvalid; - wire m01_axi_wready; - wire [3:0] m01_axi_bid; - wire [1:0]m01_axi_bresp; - wire m01_axi_bvalid; - wire m01_axi_bready; - wire [3:0] m01_axi_arid; - wire [31:0]m01_axi_araddr; - wire [7:0]m01_axi_arlen; - wire [2:0]m01_axi_arsize; - wire [1:0]m01_axi_arburst; - wire [0:0]m01_axi_arlock; - wire [3:0]m01_axi_arcache; - wire [2:0]m01_axi_arprot; - wire [3:0]m01_axi_arregion; - wire [3:0]m01_axi_arqos; - wire m01_axi_arvalid; - wire m01_axi_arready; - wire [3:0] m01_axi_rid; - wire [63:0]m01_axi_rdata; - wire [1:0]m01_axi_rresp; - wire m01_axi_rlast; - wire m01_axi_rvalid; - wire m01_axi_rready; - - // Old SDC input - // wire [3:0] SDCDatIn; - - // New SDC Command IOBUF connections - wire sd_cmd_i; - wire sd_cmd_reg_o; - wire sd_cmd_reg_t; - - // SD Card Interrupt signal - wire SDCIntr; - - // New SDC Data IOBUF connections - wire [3:0] sd_dat_i; - wire [3:0] sd_dat_reg_o; - wire sd_dat_reg_t; - - - wire c0_init_calib_complete; + wire c0_init_calib_complete; wire dbg_clk; wire [511 : 0] dbg_bus; - wire ui_clk_sync_rst; + wire ui_clk_sync_rst; wire CLK208; wire clk167; @@ -425,9 +189,9 @@ module fpgaTop wire app_sr_active; wire app_ref_ack; wire app_zq_ack; - wire mmcm_locked; + wire mmcm_locked; wire [11:0] device_temp; - wire mmcm1_locked; + wire mmcm1_locked; assign GPIOIN = {28'b0, GPI}; @@ -436,6 +200,11 @@ module fpgaTop assign cpu_reset = bus_struct_reset; assign calib = c0_init_calib_complete; + logic [3:0] SDCCS; + assign SDCCD = SDCCS[0]; + logic SDCIn; + assign SDCIn = SDCDat[0]; + // mmcm // the ddr3 mig7 requires 2 input clocks @@ -449,26 +218,7 @@ module fpgaTop .reset(1'b0), .locked(mmcm1_locked), .clk_in1(default_100mhz_clk)); - -/* -----\/----- EXCLUDED -----\/----- - // SD Card Tristate - IOBUF iobufSDCMD(.T(~SDCCmdOE), // iobuf's T is active low - .I(SDCCmdOut), - .O(SDCCmdIn), - .IO(SDCCmd)); - -----/\----- EXCLUDED -----/\----- */ - // IOBUFS for new SDC peripheral - IOBUF IOBUF_cmd (.O(sd_cmd_i), .IO(SDCCmd), .I(sd_cmd_reg_o), .T(sd_cmd_reg_t)); - genvar i; - generate - for (i = 0; i < 4; i = i + 1) begin - IOBUF iobufSDCDat(.T(sd_dat_reg_t), - .I(sd_dat_reg_o[i]), - .O(sd_dat_i[i]), - .IO(SDCDat[i]) ); - end - endgenerate // reset controller XILINX IP @@ -484,11 +234,9 @@ module fpgaTop .interconnect_aresetn(interconnect_aresetn), //open .peripheral_aresetn(peripheral_aresetn)); - // wally - // RT and JP: FIXME add sdc interrupt and HSELEXTSDC, remove old sdc after the new sdc ahb version is implemented - `include "parameter-defs.vh" - + + // Wally wallypipelinedsoc #(P) wallypipelinedsoc(.clk(CPUCLK), .reset_ext(bus_struct_reset), .reset(), .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, @@ -496,7 +244,7 @@ module fpgaTop .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr); + .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); // ahb lite to axi bridge @@ -551,432 +299,49 @@ module fpgaTop .m_axi_rlast(m_axi_rlast), .m_axi_rready(m_axi_rready)); - // AXI Crossbar for arbitrating the SDC and CPU -------------- - xlnx_axi_crossbar xlnx_axi_crossbar_0 - (.aclk(CPUCLK), - .aresetn(peripheral_aresetn), - - // Connect Masters - .s_axi_awid({4'b1000, m_axi_awid}), - .s_axi_awaddr({m01_axi_awaddr, m_axi_awaddr}), - .s_axi_awlen({m01_axi_awlen, m_axi_awlen}), - .s_axi_awsize({m01_axi_awsize, m_axi_awsize}), - .s_axi_awburst({m01_axi_awburst, m_axi_awburst}), - .s_axi_awlock({m01_axi_awlock, m_axi_awlock}), - .s_axi_awcache({m01_axi_awcache, m_axi_awcache}), - .s_axi_awprot({m01_axi_awprot, m_axi_awprot}), - .s_axi_awqos(8'b0), - .s_axi_awvalid({m01_axi_awvalid, m_axi_awvalid}), - .s_axi_awready({m01_axi_awready, m_axi_awready}), - .s_axi_wdata({m01_axi_wdata, m_axi_wdata}), - .s_axi_wstrb({m01_axi_wstrb, m_axi_wstrb}), - .s_axi_wlast({m01_axi_wlast, m_axi_wlast}), - .s_axi_wvalid({m01_axi_wvalid, m_axi_wvalid}), - .s_axi_wready({m01_axi_wready, m_axi_wready}), - .s_axi_bid({m01_axi_bid, m_axi_bid}), - .s_axi_bresp({m01_axi_bresp, m_axi_bresp}), - .s_axi_bvalid({m01_axi_bvalid, m_axi_bvalid}), - .s_axi_bready({m01_axi_bready, m_axi_bready}), - .s_axi_arid({4'b1000, m_axi_arid}), - .s_axi_araddr({m01_axi_araddr, m_axi_araddr}), - .s_axi_arlen({m01_axi_arlen, m_axi_arlen}), - .s_axi_arsize({m01_axi_arsize, m_axi_arsize}), - .s_axi_arburst({m01_axi_arburst, m_axi_arburst}), - .s_axi_arlock({m01_axi_arlock, m_axi_arlock}), - .s_axi_arcache({m01_axi_arcache, m_axi_arcache}), - .s_axi_arprot({m01_axi_arprot, m_axi_arprot}), - .s_axi_arqos(8'b0), - .s_axi_arvalid({m01_axi_arvalid, m_axi_arvalid}), - .s_axi_arready({m01_axi_arready, m_axi_arready}), - .s_axi_rid({m01_axi_rid, m_axi_rid}), - .s_axi_rdata({m01_axi_rdata, m_axi_rdata}), - .s_axi_rresp({m01_axi_rresp, m_axi_rresp}), - .s_axi_rlast({m01_axi_rlast, m_axi_rlast}), - .s_axi_rvalid({m01_axi_rvalid, m_axi_rvalid}), - .s_axi_rready({m01_axi_rready, m_axi_rready}), - - // Connect Slaves - .m_axi_awid({s01_axi_awid, s00_axi_awid}), - .m_axi_awlen({s01_axi_awlen, s00_axi_awlen}), - .m_axi_awsize({s01_axi_awsize, s00_axi_awsize}), - .m_axi_awburst({s01_axi_awburst, s00_axi_awburst}), - .m_axi_awcache({s01_axi_awcache, s00_axi_awcache}), - .m_axi_awaddr({s01_axi_awaddr, s00_axi_awaddr}), - .m_axi_awprot({s01_axi_awprot, s00_axi_awprot}), - .m_axi_awregion({s01_axi_awregion, s00_axi_awregion}), - .m_axi_awqos({s01_axi_awqos, s00_axi_awqos}), - .m_axi_awvalid({s01_axi_awvalid, s00_axi_awvalid}), - .m_axi_awready({s01_axi_awready, s00_axi_awready}), - .m_axi_awlock({s01_axi_awlock, s00_axi_awlock}), - .m_axi_wdata({s01_axi_wdata, s00_axi_wdata}), - .m_axi_wstrb({s01_axi_wstrb, s00_axi_wstrb}), - .m_axi_wlast({s01_axi_wlast, s00_axi_wlast}), - .m_axi_wvalid({s01_axi_wvalid, s00_axi_wvalid}), - .m_axi_wready({s01_axi_wready, s00_axi_wready}), - .m_axi_bid({4'b1000, s00_axi_bid}), - .m_axi_bresp({s01_axi_bresp, s00_axi_bresp}), - .m_axi_bvalid({s01_axi_bvalid, s00_axi_bvalid}), - .m_axi_bready({s01_axi_bready, s00_axi_bready}), - .m_axi_arid({s01_axi_arid, s00_axi_arid}), - .m_axi_arlen({s01_axi_arlen, s00_axi_arlen}), - .m_axi_arsize({s01_axi_arsize, s00_axi_arsize}), - .m_axi_arburst({s01_axi_arburst, s00_axi_arburst}), - .m_axi_arprot({s01_axi_arprot, s00_axi_arprot}), - .m_axi_arregion({s01_axi_arregion, s00_axi_arregion}), - .m_axi_arqos({s01_axi_arqos, s00_axi_arqos}), - .m_axi_arcache({s01_axi_arcache, s00_axi_arcache}), - .m_axi_arvalid({s01_axi_arvalid, s00_axi_arvalid}), - .m_axi_araddr({s01_axi_araddr, s00_axi_araddr}), - .m_axi_arlock({s01_axi_arlock, s00_axi_arlock}), - .m_axi_arready({s01_axi_arready, s00_axi_arready}), - .m_axi_rid({4'b1000, s00_axi_rid}), - .m_axi_rdata({s01_axi_rdata, s00_axi_rdata}), - .m_axi_rresp({s01_axi_rresp, s00_axi_rresp}), - .m_axi_rvalid({s01_axi_rvalid, s00_axi_rvalid}), - .m_axi_rlast({s01_axi_rlast, s00_axi_rlast}), - .m_axi_rready({s01_axi_rready, s00_axi_rready}) - ); - - // ----------------------------------------------------- - - // SDC Implementation ---------------------------------- - // - // The SDC peripheral from Eugene Tarassov takes in an AXI4Lite - // interface and outputs an AXI4 interface. In order to convert from - // one to the other, we use these dwidth converters to make sure the - // bit widths match the rest of the bus. - - xlnx_axi_dwidth_conv_64to32 axi_conv_down - (.s_axi_aclk(CPUCLK), - .s_axi_aresetn(peripheral_aresetn), - - // Slave interface - .s_axi_awaddr(s01_axi_awaddr), - .s_axi_awlen(s01_axi_awlen), - .s_axi_awsize(s01_axi_awsize), - .s_axi_awburst(s01_axi_awburst), - .s_axi_awlock(s01_axi_awlock), - .s_axi_awcache(s01_axi_awcache), - .s_axi_awprot(s01_axi_awprot), - .s_axi_awregion(s01_axi_awregion), - .s_axi_awqos(4'b0), - .s_axi_awvalid(s01_axi_awvalid), - .s_axi_awready(s01_axi_awready), - .s_axi_wdata(s01_axi_wdata), - .s_axi_wstrb(s01_axi_wstrb), - .s_axi_wlast(s01_axi_wlast), - .s_axi_wvalid(s01_axi_wvalid), - .s_axi_wready(s01_axi_wready), - .s_axi_bresp(s01_axi_bresp), - .s_axi_bvalid(s01_axi_bvalid), - .s_axi_bready(s01_axi_bready), - .s_axi_araddr(s01_axi_araddr), - .s_axi_arlen(s01_axi_arlen), - .s_axi_arsize(s01_axi_arsize), - .s_axi_arburst(s01_axi_arburst), - .s_axi_arlock(s01_axi_arlock), - .s_axi_arcache(s01_axi_arcache), - .s_axi_arprot(s01_axi_arprot), - .s_axi_arregion(s01_axi_arregion), - .s_axi_arqos(4'b0), - .s_axi_arvalid(s01_axi_arvalid), - .s_axi_arready(s01_axi_arready), - .s_axi_rdata(s01_axi_rdata), - .s_axi_rresp(s01_axi_rresp), - .s_axi_rlast(s01_axi_rlast), - .s_axi_rvalid(s01_axi_rvalid), - .s_axi_rready(s01_axi_rready), - - // Master interface - .m_axi_awaddr(axi4in_axi_awaddr), - .m_axi_awlen(axi4in_axi_awlen), - .m_axi_awsize(axi4in_axi_awsize), - .m_axi_awburst(axi4in_axi_awburst), - .m_axi_awlock(axi4in_axi_awlock), - .m_axi_awcache(axi4in_axi_awcache), - .m_axi_awprot(axi4in_axi_awprot), - .m_axi_awregion(axi4in_axi_awregion), - .m_axi_awqos(axi4in_axi_awqos), - .m_axi_awvalid(axi4in_axi_awvalid), - .m_axi_awready(axi4in_axi_awready), - .m_axi_wdata(axi4in_axi_wdata), - .m_axi_wstrb(axi4in_axi_wstrb), - .m_axi_wlast(axi4in_axi_wlast), - .m_axi_wvalid(axi4in_axi_wvalid), - .m_axi_wready(axi4in_axi_wready), - .m_axi_bresp(axi4in_axi_bresp), - .m_axi_bvalid(axi4in_axi_bvalid), - .m_axi_bready(axi4in_axi_bready), - .m_axi_araddr(axi4in_axi_araddr), - .m_axi_arlen(axi4in_axi_arlen), - .m_axi_arsize(axi4in_axi_arsize), - .m_axi_arburst(axi4in_axi_arburst), - .m_axi_arlock(axi4in_axi_arlock), - .m_axi_arcache(axi4in_axi_arcache), - .m_axi_arprot(axi4in_axi_arprot), - .m_axi_arregion(axi4in_axi_arregion), - .m_axi_arqos(axi4in_axi_arqos), - .m_axi_arvalid(axi4in_axi_arvalid), - .m_axi_arready(axi4in_axi_arready), - .m_axi_rdata(axi4in_axi_rdata), - .m_axi_rresp(axi4in_axi_rresp), - .m_axi_rlast(axi4in_axi_rlast), - .m_axi_rvalid(axi4in_axi_rvalid), - .m_axi_rready(axi4in_axi_rready) - ); - - xlnx_axi_prtcl_conv axi4tolite - (.aclk(CPUCLK), - .aresetn(peripheral_aresetn), - - // AXI4 In - .s_axi_awaddr(axi4in_axi_awaddr), - .s_axi_awlen(axi4in_axi_awlen), - .s_axi_awsize(axi4in_axi_awsize), - .s_axi_awburst(axi4in_axi_awburst), - .s_axi_awlock(axi4in_axi_awlock), - .s_axi_awcache(axi4in_axi_awcache), - .s_axi_awprot(axi4in_axi_awprot), - .s_axi_awregion(axi4in_axi_awregion), - .s_axi_awqos(axi4in_axi_awqos), - .s_axi_awvalid(axi4in_axi_awvalid), - .s_axi_awready(axi4in_axi_awready), - .s_axi_wdata(axi4in_axi_wdata), - .s_axi_wstrb(axi4in_axi_wstrb), - .s_axi_wlast(axi4in_axi_wlast), - .s_axi_wvalid(axi4in_axi_wvalid), - .s_axi_wready(axi4in_axi_wready), - .s_axi_bresp(axi4in_axi_bresp), - .s_axi_bvalid(axi4in_axi_bvalid), - .s_axi_bready(axi4in_axi_bready), - .s_axi_araddr(axi4in_axi_araddr), - .s_axi_arlen(axi4in_axi_arlen), - .s_axi_arsize(axi4in_axi_arsize), - .s_axi_arburst(axi4in_axi_arburst), - .s_axi_arlock(axi4in_axi_arlock), - .s_axi_arcache(axi4in_axi_arcache), - .s_axi_arprot(axi4in_axi_arprot), - .s_axi_arregion(axi4in_axi_arregion), - .s_axi_arqos(axi4in_axi_arqos), - .s_axi_arvalid(axi4in_axi_arvalid), - .s_axi_arready(axi4in_axi_arready), - .s_axi_rdata(axi4in_axi_rdata), - .s_axi_rresp(axi4in_axi_rresp), - .s_axi_rlast(axi4in_axi_rlast), - .s_axi_rvalid(axi4in_axi_rvalid), - .s_axi_rready(axi4in_axi_rready), - - // AXI4Lite Out - .m_axi_awaddr(SDCin_axi_awaddr), - .m_axi_awprot(SDCin_axi_awprot), - .m_axi_awvalid(SDCin_axi_awvalid), - .m_axi_awready(SDCin_axi_awready), - .m_axi_wdata(SDCin_axi_wdata), - .m_axi_wstrb(SDCin_axi_wstrb), - .m_axi_wvalid(SDCin_axi_wvalid), - .m_axi_wready(SDCin_axi_wready), - .m_axi_bresp(SDCin_axi_bresp), - .m_axi_bvalid(SDCin_axi_bvalid), - .m_axi_bready(SDCin_axi_bready), - .m_axi_araddr(SDCin_axi_araddr), - .m_axi_arprot(SDCin_axi_arprot), - .m_axi_arvalid(SDCin_axi_arvalid), - .m_axi_arready(SDCin_axi_arready), - .m_axi_rdata(SDCin_axi_rdata), - .m_axi_rresp(SDCin_axi_rresp), - .m_axi_rvalid(SDCin_axi_rvalid), - .m_axi_rready(SDCin_axi_rready) - - ); - - - sdc_controller axiSDC - (.clock(CPUCLK), - .async_resetn(peripheral_aresetn), - - // Slave Interface - .s_axi_awaddr({8'b0, SDCin_axi_awaddr[7:0]}), - .s_axi_awvalid(SDCin_axi_awvalid), - .s_axi_awready(SDCin_axi_awready), - .s_axi_wdata(SDCin_axi_wdata), - .s_axi_wvalid(SDCin_axi_wvalid), - .s_axi_wready(SDCin_axi_wready), - .s_axi_bresp(SDCin_axi_bresp), - .s_axi_bvalid(SDCin_axi_bvalid), - .s_axi_bready(SDCin_axi_bready), - .s_axi_araddr({8'b0, SDCin_axi_araddr[7:0]}), - .s_axi_arvalid(SDCin_axi_arvalid), - .s_axi_arready(SDCin_axi_arready), - .s_axi_rdata(SDCin_axi_rdata), - .s_axi_rresp(SDCin_axi_rresp), - .s_axi_rvalid(SDCin_axi_rvalid), - .s_axi_rready(SDCin_axi_rready), - .sdio_reset(sdio_reset_open), - - // Master Interface - .m_axi_awaddr(SDCout_axi_awaddr), - .m_axi_awlen(SDCout_axi_awlen), - .m_axi_awvalid(SDCout_axi_awvalid), - .m_axi_awready(SDCout_axi_awready), - .m_axi_wdata(SDCout_axi_wdata), - .m_axi_wlast(SDCout_axi_wlast), - .m_axi_wvalid(SDCout_axi_wvalid), - .m_axi_wready(SDCout_axi_wready), - .m_axi_bresp(SDCout_axi_bresp), - .m_axi_bvalid(SDCout_axi_bvalid), - .m_axi_bready(SDCout_axi_bready), - .m_axi_araddr(SDCout_axi_araddr), - .m_axi_arlen(SDCout_axi_arlen), - .m_axi_arvalid(SDCout_axi_arvalid), - .m_axi_arready(SDCout_axi_arready), - .m_axi_rdata(SDCout_axi_rdata), - .m_axi_rlast(SDCout_axi_rlast), - .m_axi_rresp(SDCout_axi_rresp), - .m_axi_rvalid(SDCout_axi_rvalid), - .m_axi_rready(SDCout_axi_rready), - - // SDC interface - //.sdio_cmd(1'b0), - //.sdio_dat(4'b0), - //.sdio_cd(1'b0) - - .sd_dat_reg_t(sd_dat_reg_t), - .sd_dat_reg_o(sd_dat_reg_o), - .sd_dat_i(sd_dat_i), - - .sd_cmd_reg_t(sd_cmd_reg_t), - .sd_cmd_reg_o(sd_cmd_reg_o), - .sd_cmd_i(sd_cmd_i), - - .sdio_clk(SDCCLK), - .sdio_cd(SDCCD), - - .interrupt(SDCIntr) - ); - - xlnx_axi_dwidth_conv_32to64 axi_conv_up - (.s_axi_aclk(CPUCLK), - .s_axi_aresetn(peripheral_aresetn), - - // Slave interface - .s_axi_awaddr(SDCout_axi_awaddr), - .s_axi_awlen(SDCout_axi_awlen), - .s_axi_awsize(3'b010), - .s_axi_awburst(2'b01), - .s_axi_awlock(1'b0), - .s_axi_awcache(4'b0), - .s_axi_awprot(3'b0), - .s_axi_awregion(4'b0), - .s_axi_awqos(4'b0), - .s_axi_awvalid(SDCout_axi_awvalid), - .s_axi_awready(SDCout_axi_awready), - .s_axi_wdata(SDCout_axi_wdata), - .s_axi_wstrb(8'b11111111), - .s_axi_wlast(SDCout_axi_wlast), - .s_axi_wvalid(SDCout_axi_wvalid), - .s_axi_wready(SDCout_axi_wready), - .s_axi_bresp(SDCout_axi_bresp), - .s_axi_bvalid(SDCout_axi_bvalid), - .s_axi_bready(SDCout_axi_bready), - .s_axi_araddr(SDCout_axi_araddr), - .s_axi_arlen(SDCout_axi_arlen), - .s_axi_arsize(3'b010), - .s_axi_arburst(2'b01), - .s_axi_arlock(1'b0), - .s_axi_arcache(4'b0), - .s_axi_arprot(3'b0), - .s_axi_arregion(4'b0), - .s_axi_arqos(4'b0), - .s_axi_arvalid(SDCout_axi_arvalid), - .s_axi_arready(SDCout_axi_arready), - .s_axi_rdata(SDCout_axi_rdata), - .s_axi_rresp(SDCout_axi_rresp), - .s_axi_rlast(SDCout_axi_rlast), - .s_axi_rvalid(SDCout_axi_rvalid), - .s_axi_rready(SDCout_axi_rready), - - // Master interface - .m_axi_awaddr(m01_axi_awaddr), - .m_axi_awlen(m01_axi_awlen), - .m_axi_awsize(m01_axi_awsize), - .m_axi_awburst(m01_axi_awburst), - .m_axi_awlock(m01_axi_awlock), - .m_axi_awcache(m01_axi_awcache), - .m_axi_awprot(m01_axi_awprot), - .m_axi_awregion(m01_axi_awregion), - .m_axi_awqos(m01_axi_awqos), - .m_axi_awvalid(m01_axi_awvalid), - .m_axi_awready(m01_axi_awready), - .m_axi_wdata(m01_axi_wdata), - .m_axi_wstrb(m01_axi_wstrb), - .m_axi_wlast(m01_axi_wlast), - .m_axi_wvalid(m01_axi_wvalid), - .m_axi_wready(m01_axi_wready), - .m_axi_bresp(m01_axi_bresp), - .m_axi_bvalid(m01_axi_bvalid), - .m_axi_bready(m01_axi_bready), - .m_axi_araddr(m01_axi_araddr), - .m_axi_arlen(m01_axi_arlen), - .m_axi_arsize(m01_axi_arsize), - .m_axi_arburst(m01_axi_arburst), - .m_axi_arlock(m01_axi_arlock), - .m_axi_arcache(m01_axi_arcache), - .m_axi_arprot(m01_axi_arprot), - .m_axi_arregion(m01_axi_arregion), - .m_axi_arqos(m01_axi_arqos), - .m_axi_arvalid(m01_axi_arvalid), - .m_axi_arready(m01_axi_arready), - .m_axi_rdata(m01_axi_rdata), - .m_axi_rresp(m01_axi_rresp), - .m_axi_rlast(m01_axi_rlast), - .m_axi_rvalid(m01_axi_rvalid), - .m_axi_rready(m01_axi_rready) - ); - - // End SDC signals -------------------------------------------- - + // AXI Clock Converter xlnx_axi_clock_converter xlnx_axi_clock_converter_0 (.s_axi_aclk(CPUCLK), .s_axi_aresetn(peripheral_aresetn), - .s_axi_awid(s00_axi_awid), - .s_axi_awlen(s00_axi_awlen), - .s_axi_awsize(s00_axi_awsize), - .s_axi_awburst(s00_axi_awburst), - .s_axi_awcache(s00_axi_awcache), - .s_axi_awaddr(s00_axi_awaddr[30:0] ), - .s_axi_awprot(s00_axi_awprot), + .s_axi_awid(m_axi_awid), + .s_axi_awlen(m_axi_awlen), + .s_axi_awsize(m_axi_awsize), + .s_axi_awburst(m_axi_awburst), + .s_axi_awcache(m_axi_awcache), + .s_axi_awaddr(m_axi_awaddr[30:0] ), + .s_axi_awprot(m_axi_awprot), .s_axi_awregion(4'b0), // this could be a bug. bridge does not have these outputs .s_axi_awqos(4'b0), // this could be a bug. bridge does not have these outputs - .s_axi_awvalid(s00_axi_awvalid), - .s_axi_awready(s00_axi_awready), - .s_axi_awlock(s00_axi_awlock), - .s_axi_wdata(s00_axi_wdata), - .s_axi_wstrb(s00_axi_wstrb), - .s_axi_wlast(s00_axi_wlast), - .s_axi_wvalid(s00_axi_wvalid), - .s_axi_wready(s00_axi_wready), - .s_axi_bid(s00_axi_bid), - .s_axi_bresp(s00_axi_bresp), - .s_axi_bvalid(s00_axi_bvalid), - .s_axi_bready(s00_axi_bready), - .s_axi_arid(s00_axi_arid), - .s_axi_arlen(s00_axi_arlen), - .s_axi_arsize(s00_axi_arsize), - .s_axi_arburst(s00_axi_arburst), - .s_axi_arprot(s00_axi_arprot), + .s_axi_awvalid(m_axi_awvalid), + .s_axi_awready(m_axi_awready), + .s_axi_awlock(m_axi_awlock), + .s_axi_wdata(m_axi_wdata), + .s_axi_wstrb(m_axi_wstrb), + .s_axi_wlast(m_axi_wlast), + .s_axi_wvalid(m_axi_wvalid), + .s_axi_wready(m_axi_wready), + .s_axi_bid(m_axi_bid), + .s_axi_bresp(m_axi_bresp), + .s_axi_bvalid(m_axi_bvalid), + .s_axi_bready(m_axi_bready), + .s_axi_arid(m_axi_arid), + .s_axi_arlen(m_axi_arlen), + .s_axi_arsize(m_axi_arsize), + .s_axi_arburst(m_axi_arburst), + .s_axi_arprot(m_axi_arprot), .s_axi_arregion(4'b0), // this could be a bug. bridge does not have these outputs .s_axi_arqos(4'b0), // this could be a bug. bridge does not have these outputs - .s_axi_arcache(s00_axi_arcache), - .s_axi_arvalid(s00_axi_arvalid), - .s_axi_araddr(s00_axi_araddr[30:0]), - .s_axi_arlock(s00_axi_arlock), - .s_axi_arready(s00_axi_arready), - .s_axi_rid(s00_axi_rid), - .s_axi_rdata(s00_axi_rdata), - .s_axi_rresp(s00_axi_rresp), - .s_axi_rvalid(s00_axi_rvalid), - .s_axi_rlast(s00_axi_rlast), - .s_axi_rready(s00_axi_rready), + .s_axi_arcache(m_axi_arcache), + .s_axi_arvalid(m_axi_arvalid), + .s_axi_araddr(m_axi_araddr[30:0]), + .s_axi_arlock(m_axi_arlock), + .s_axi_arready(m_axi_arready), + .s_axi_rid(m_axi_rid), + .s_axi_rdata(m_axi_rdata), + .s_axi_rresp(m_axi_rresp), + .s_axi_rvalid(m_axi_rvalid), + .s_axi_rlast(m_axi_rlast), + .s_axi_rready(m_axi_rready), .m_axi_aclk(BUSCLK), .m_axi_aresetn(resetn), @@ -1020,6 +385,7 @@ module fpgaTop .m_axi_rlast(BUS_axi_rlast), .m_axi_rready(BUS_axi_rready)); + // DDR3 Controller xlnx_ddr3 xlnx_ddr3_c0 ( // ddr3 I/O diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 94f188120..e9c04bca8 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -42,7 +42,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( output logic SPIOut, input logic SPIIn, output logic [3:0] SPICS, - output logic SPIIntr + output logic SPIIntr, + output logic SPICLK ); // register map @@ -99,7 +100,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( rsrstatetype ReceiveState; // Transmission signals - logic sck; + // logic sck; logic [11:0] DivCounter; // Counter for sck logic SCLKenable; // Flip flop enable high every sclk edge @@ -358,7 +359,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull); assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef; - assign sck = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1]; + assign SPICLK = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1]; assign Active = (state == ACTIVE_0 | state == ACTIVE_1); assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0); assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4]))); @@ -368,11 +369,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Signal tracks which edge of sck to shift data always_comb case(SckMode[1:0]) - 2'b00: ShiftEdge = ~sck & SCLKenable; - 2'b01: ShiftEdge = (sck & |(FrameCount) & SCLKenable); - 2'b10: ShiftEdge = sck & SCLKenable; - 2'b11: ShiftEdge = (~sck & |(FrameCount) & SCLKenable); - default: ShiftEdge = sck & SCLKenable; + 2'b00: ShiftEdge = ~SPICLK & SCLKenable; + 2'b01: ShiftEdge = (SPICLK & |(FrameCount) & SCLKenable); + 2'b10: ShiftEdge = SPICLK & SCLKenable; + 2'b11: ShiftEdge = (~SPICLK & |(FrameCount) & SCLKenable); + default: ShiftEdge = SPICLK & SCLKenable; endcase // Transmit shift register diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 39a2be09a..dad558c19 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -46,7 +46,6 @@ module uncore import cvw::*; #(parameter cvw_t P)( output logic [P.AHBW-1:0] HRDATA, output logic HREADY, HRESP, output logic HSELEXT, - output logic HSELEXTSDC, // peripheral pins output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT output logic MExtInt, SExtInt, // External interrupts from PLIC @@ -55,16 +54,20 @@ module uncore import cvw::*; #(parameter cvw_t P)( output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable input logic UARTSin, // UART serial input output logic UARTSout, // UART serial output - input logic SDCIntr, input logic SPIIn, output logic SPIOut, - output logic [3:0] SPICS + output logic [3:0] SPICS, + output logic SPICLK, + input logic SDCIn, + output logic SDCCmd, + output logic [3:0] SDCCS, + output logic SDCCLK ); logic [P.XLEN-1:0] HREADRam, HREADSDC; logic [11:0] HSELRegions; - logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSPI; + logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART,HSELSDC, HSELSPI; logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID; logic HRESPRam, HRESPSDC; logic HREADYRam, HRESPSDCD; @@ -85,8 +88,8 @@ module uncore import cvw::*; #(parameter cvw_t P)( /* verilator lint_on UNDRIVEN */ logic [P.XLEN-1:0] HREADBRIDGE; logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED; - - (* mark_debug = "true" *) logic HSELEXTSDCD; + /* SDC Interrupt (SPI Controller) */ + logic SDCIntr; // Determine which region of physical memory (if any) is being accessed @@ -95,14 +98,14 @@ module uncore import cvw::*; #(parameter cvw_t P)( adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals - assign {HSELSPI, HSELEXTSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1]; + assign {HSELSPI, HSELSDC, HSELPLIC, HSELUART, HSELGPIO, HSELCLINT, HSELRam, HSELBootRom, HSELEXT, HSELIROM, HSELDTIM} = HSELRegions[11:1]; // AHB -> APB bridge - ahbapbbridge #(P, 5) ahbapbbridge ( - .HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, + ahbapbbridge #(P, 6) ahbapbbridge ( + .HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO, HSELSDC}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, .HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE), .PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA); - assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI; // if any of the bridge signals are selected + assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI | HSELSDC; // if any of the bridge signals are selected // on-chip RAM if (P.UNCORE_RAM_SUPPORTED) begin : ram @@ -142,6 +145,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( end else begin : gpio assign GPIOOUT = '0; assign GPIOEN = '0; assign GPIOIntr = 1'b0; end + if (P.UART_SUPPORTED == 1) begin : uartgen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 uart_apb #(P) uart( .PCLK, .PRESETn, .PSEL(PSEL[3]), .PADDR(PADDR[2:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, @@ -152,28 +156,39 @@ module uncore import cvw::*; #(parameter cvw_t P)( end else begin : uart assign UARTSout = 1'b0; assign UARTIntr = 1'b0; end + if (P.SPI_SUPPORTED == 1) begin : spi spi_apb #(P) spi ( .PCLK, .PRESETn, .PSEL(PSEL[4]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, .PREADY(PREADY[4]), .PRDATA(PRDATA[4]), - .SPIOut, .SPIIn, .SPICS, .SPIIntr); + .SPIOut, .SPIIn, .SPICS, .SPICLK, .SPIIntr); end else begin : spi - assign SPIOut = 1'b0; assign SPICS = '0; assign SPIIntr = 1'b0; + assign SPIOut = 1'b0; assign SPICS = '0; assign SPIIntr = 1'b0; assign SPICLK = 1'b0; end + if (P.SDC_SUPPORTED == 1) begin : sdc + spi_apb #(P) sdc( + .PCLK, .PRESETN, .PSEL(.PSEL[5]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, + .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), + .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(.SDCIntr)); + end else begin : sdc + assign SDCCmd = '0; assign SDCCD = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; + end + + // AHB Read Multiplexer assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) | - ({P.XLEN{HSELEXTD | HSELEXTSDCD}} & HRDATAEXT) | + ({P.XLEN{HSELEXTD}} & HRDATAEXT) | ({P.XLEN{HSELBRIDGED}} & HREADBRIDGE) | ({P.XLEN{HSELBootRomD}} & HREADBootRom); assign HRESP = HSELRamD & HRESPRam | - (HSELEXTD | HSELEXTSDCD) & HRESPEXT | + HSELEXTD & HRESPEXT | HSELBRIDGE & HRESPBRIDGE | HSELBootRomD & HRESPBootRom; assign HREADY = HSELRamD & HREADYRam | - (HSELEXTD | HSELEXTSDCD) & HREADYEXT | + HSELEXTD & HREADYEXT | HSELBRIDGED & HREADYBRIDGE | HSELBootRomD & HREADYBootRom | HSELNoneD; // don't lock up the bus if no region is being accessed @@ -184,7 +199,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( // device is ready. Hense this register must be selectively enabled by HREADY. // However on reset None must be seleted. flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1, - {HSELSPID, HSELEXTSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD, + {HSELSPID, HSELSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD, HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD}); flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED); endmodule diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 9f5e5ee00..af9f0ff26 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -55,10 +55,14 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( output logic [31:0] GPIOEN, // output enables for GPIO input logic UARTSin, // UART serial data input output logic UARTSout, // UART serial data output - input logic SDCIntr, input logic SPIIn, // SPI pins in output logic SPIOut, // SPI pins out - output logic [3:0] SPICS // SPI chip select pins + output logic [3:0] SPICS, // SPI chip select pins + output logic SPICLK, // SPI clock + input logic SDCIn, // SDC DATA[0] to SPI DI + output logic SDCCmd, // SDC CMD from SPI DO + output logic [3:0] SDCCS, // SDC Card Detect from SPI CS + output logic SDCCLK // SDC Clock from SPI Clock ); // Uncore signals @@ -84,7 +88,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC, .MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, - .UARTSout, .MTIME_CLINT, .SDCIntr, .SPIIn, .SPIOut, .SPICS); + .UARTSout, .MTIME_CLINT, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); end else begin assign {HRDATA, HREADY, HRESP, HSELEXT, HSELEXTSDC, MTimerInt, MSwInt, MExtInt, SExtInt, MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; From cec39fd3aa66a8ccc8fee528287134f3ccdfd643 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 22 Jul 2024 13:05:16 -0500 Subject: [PATCH 06/39] Added new SDC clock constraint. --- fpga/constraints/constraints-ArtyA7.xdc | 63 +++++++++++++------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 6fc660e8d..f466b0c30 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -4,6 +4,7 @@ # This clock is not used by wally or the AHB Bus. However it is used by the AXI BUS on the DD3 IP. #create_generated_clock -name CLKDiv64_Gen -source [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/I0] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/O] +create_generated_clock -name SPISDCClock -source [get_pins clk_out3_xlnx_mmcm] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncore.uncore/sdc.sdc/SPICLK] ##### clock ##### set_property PACKAGE_PIN E3 [get_ports {default_100mhz_clk}] @@ -74,41 +75,43 @@ set_property IOSTANDARD LVCMOS33 [get_ports {south_reset}] ##### SD Card I/O ##### #***** may have to switch to Pmod JB or JC. -set_property PACKAGE_PIN D4 [get_ports {SDCDat[3]}] -set_property PACKAGE_PIN D2 [get_ports {SDCDat[2]}] -set_property PACKAGE_PIN E2 [get_ports {SDCDat[1]}] -set_property PACKAGE_PIN F4 [get_ports {SDCDat[0]}] -set_property PACKAGE_PIN F3 [get_ports SDCCLK] -set_property PACKAGE_PIN D3 [get_ports {SDCCmd}] -set_property PACKAGE_PIN H2 [get_ports {SDCCD}] +#set_property PACKAGE_PIN D4 [get_ports {SDCDat[3]}] +#set_property PACKAGE_PIN D2 [get_ports {SDCDat[2]}] +#set_property PACKAGE_PIN E2 [get_ports {SDCDat[1]}] +#set_property PACKAGE_PIN F4 [get_ports {SDCDat[0]}] +#set_property PACKAGE_PIN F3 [get_ports SDCCLK] +#set_property PACKAGE_PIN D3 [get_ports {SDCCmd}] +#set_property PACKAGE_PIN H2 [get_ports {SDCCD}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[3]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[2]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[1]}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[0]}] +#set_property IOSTANDARD LVCMOS33 [get_ports SDCCLK] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCCmd}] +#set_property IOSTANDARD LVCMOS33 [get_ports {SDCCD}] +#set_property PULLUP true [get_ports {SDCDat[3]}] +#set_property PULLUP true [get_ports {SDCDat[2]}] +#set_property PULLUP true [get_ports {SDCDat[1]}] +#set_property PULLUP true [get_ports {SDCDat[0]}] +#set_property PULLUP true [get_ports {SDCCmd}] +#set_property PULLUP true [get_ports {SDCCD}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[3]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[2]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[1]}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[0]}] -set_property IOSTANDARD LVCMOS33 [get_ports SDCCLK] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCCmd}] -set_property IOSTANDARD LVCMOS33 [get_ports {SDCCD}] -set_property PULLUP true [get_ports {SDCDat[3]}] -set_property PULLUP true [get_ports {SDCDat[2]}] -set_property PULLUP true [get_ports {SDCDat[1]}] -set_property PULLUP true [get_ports {SDCDat[0]}] -set_property PULLUP true [get_ports {SDCCmd}] -set_property PULLUP true [get_ports {SDCCD}] +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[3]}] +set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] +set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] +set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[0]}] +set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCClk}] +set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] +set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] +set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCDat[*]}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCDat[*]}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.500 [get_ports {SDCDat[*]}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 21.000 [get_ports {SDCDat[*]}] +set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.000 [get_ports {SDCCmd}] +set_output_delay -clock [get_clocks SPISDCClock] -max -add_delay 6.000 [get_ports {SDCCmd}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.500 [get_ports {SDCCmd}] -set_input_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 14.000 [get_ports {SDCCmd}] - - -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 2.000 [get_ports {SDCCmd}] -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 6.000 [get_ports {SDCCmd}] - -set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] 0.000 [get_ports SDCCLK] +set_output_delay -clock [get_clocks SPISDCClock] 0.000 [get_ports SDCCLK] #set_multicycle_path -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 10 From b05052311f095a7e7021a3d1d5dd391dfcd1e5b0 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Mon, 22 Jul 2024 16:57:04 -0500 Subject: [PATCH 07/39] Added sd_cmd and utility SPI functions. --- fpga/zsbl/sd.c | 68 ++++++++++++++++++++++++++++++++++-- fpga/zsbl/sd.h | 3 +- fpga/zsbl/spi.c | 91 ++++++++++++++++++++++++++++++++++--------------- fpga/zsbl/spi.h | 53 +++++++++++++++++----------- 4 files changed, 164 insertions(+), 51 deletions(-) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 8781dd5c3..aacea0db9 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -12,6 +12,7 @@ uint8_t crc7(uint8_t prev, uint8_t in) { return remainder & 0xff; } +// Need to check this. This could be wrong as well. uint16_t crc16(uint16_t crc, uint8_t data) { // CRC polynomial 0x11021 crc = (uint8_t)(crc >> 8) | (crc << 8); @@ -22,13 +23,74 @@ uint16_t crc16(uint16_t crc, uint8_t data) { return crc; } -uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { - spi_send_byte +uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { + uint8_t response_len; + uint8_t i; + uint64_t r; + uint8_t rbyte; + + switch (cmd) { + case 0: + response_len = 1; + break; + case 8: + response_len = 7 + break; + default: + response_len = 1; + break; + } + + // Make interrupt pending after response fifo receives the correct + // response length. + write_reg(SPI_RXMARK, response_len); + + // Write all 6 bytes into transfer fifo + spi_sendbyte(0x40 | cmd); + spi_sendbyte(arg >> 24); + spi_sendbyte(arg >> 16); + spi_sendbyte(arg >> 8); + spi_sendbyte(arg); + spi_sendbyte(crc); + + // Wait for command to send + // The Transfer IP bit should go high when the txFIFO is empty + // while(!(read_reg(SPI_IP) & 1)) {} + waittx(); + + // Read the dummy rxFIFO entries to move the head back to the tail + for (i = 0; i < 6; i++) { + spi_readbyte(); + } + + // Send "dummy signals". Since SPI is duplex, + // useless bytes must be transferred + for (i = 0; i < response_len; i++) { + spi_sendbyte(0xFF); + } + + // Wait for transfer fifo again + waittx(); + + // Read rxfifo response + for (i = 0; i < response_len; i++) { + rbyte = spi_readbyte(); + r = r | (rbyte << ((response_len - 1 - i)*8)); + } + + return r; } +#define cmd0() sd_cmd( 0, 0x00000000, 0x95) +#define cmd8() sd_cmd( 8, 0x000001aa, 0x87) +// CMD55 has to be sent before ACMD41 (it means the next command is +// application specific) +#define cmd55() sd_cmd(55, 0x00000000, 0x65) +#defube acmd41() sd_cmd(41, 0x40000000, 0x77) + void init_sd(){ init_spi(); - + cmd0() } diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index b1b27db14..f08941364 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -4,6 +4,5 @@ uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); -uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); +uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); void init_sd(); - diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index bf6d629b4..c812327f4 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -1,50 +1,87 @@ +/////////////////////////////////////////////////////////////////////// +// spi.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: SPI Controller API for bootloader +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #include "spi.h" -void write_reg(uintptr_t addr, uint32_t value) { +// Write to a register +inline void write_reg(uintptr_t addr, uint32_t value) { volatile uint32_t * loc = (volatile uint32_t *) addr; *loc = value; } -void read_red(uintptr_t addr) { +// Read a register +inline void read_reg(uintptr_t addr) { return *(volatile uint32_t *) addr; } +// Queues a single byte in the transfer fifo +inline void spi_sendbyte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); +} + +inline uint8_t spi_readbyte() { + return read_reg(SPI_RXDATA); +} + +inline void waittx() { + while(!(read_reg(SPI_IP) & 1)) {} +} + +inline void waitrx() { + while(read_reg(SPI_IP) & 2)) {} +} + + // Initialize Sifive FU540 based SPI Controller void spi_init() { - // Disable interrupts by default - // write_reg(SPI_IE, 0); + // Enable interrupts + write_reg(SPI_IE, 0x3); + // Set TXMARK to 1. If the number of entries is < 1 + // IP's txwm field will go high. + // Set RXMARK to 0. If the number of entries is > 0 + // IP's rwxm field will go high. write_reg(SPI_TXMARK, 1); write_reg(SPI_RXMARK, 0); + // Set Delay 0 to default write_reg(SPI_DELAY0, SIFIVE_SPI_DELAY0_CSSCK(1) | SIFIVE_SPI_DELAY0_SCKCS(1)); + // Set Delay 1 to default write_reg(SPI_DELAY1, SIFIVE_SPI_DELAY1_INTERCS(1) | SIFIVE_SPI_DELAY1_INTERXFR(0)); + + // Initialize the SPI controller clock to + // div = (20MHz/(2*400kHz)) - 1 = 24 = 0x18 + write_reg(SPI_SCKDIV, 0x18); } - -// Sends and receives a single byte -uint8_t spi_send_byte(uint8_t byte) { - // Write byte to transfer fifo - write_reg(SPI_TXDATA, byte); - - /* Not sure how necessary this is. Will keep commented for now. - // Wait a decent amount of time for data to send - for (int i = 0; i < 100; i++) { - __asm__ volatile("nop"); - } - */ - - // Wait for data to come into receive fifo - while (read_reg(SPI_IP) != 2) {} - - // Read received data - result = read_reg(SPI_RXDATA); - - // Return result - return result; -} - diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index 6bae450ae..a035f0ab5 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -4,26 +4,28 @@ #include +#define SPI_BASE 0x13000 /* Base address of SPI device used for SDC */ + /* register offsets */ -#define SPI_SCKDIV 0x00 /* Serial clock divisor */ -#define SPI_SCKMODE 0x04 /* Serial clock mode */ -#define SPI_CSID 0x10 /* Chip select ID */ -#define SPI_CSDEF 0x14 /* Chip select default */ -#define SPI_CSMODE 0x18 /* Chip select mode */ -#define SPI_DELAY0 0x28 /* Delay control 0 */ -#define SPI_DELAY1 0x2c /* Delay control 1 */ -#define SPI_FMT 0x40 /* Frame format */ -#define SPI_TXDATA 0x48 /* Tx FIFO data */ -#define SPI_RXDATA 0x4c /* Rx FIFO data */ -#define SPI_TXMARK 0x50 /* Tx FIFO [<35;39;29Mwatermark */ -#define SPI_RXMARK 0x54 /* Rx FIFO watermark */ +#define SPI_SCKDIV SPI_BASE + 0x00 /* Serial clock divisor */ +#define SPI_SCKMODE SPI_BASE + 0x04 /* Serial clock mode */ +#define SPI_CSID SPI_BASE + 0x10 /* Chip select ID */ +#define SPI_CSDEF SPI_BASE + 0x14 /* Chip select default */ +#define SPI_CSMODE SPI_BASE + 0x18 /* Chip select mode */ +#define SPI_DELAY0 SPI_BASE + 0x28 /* Delay control 0 */ +#define SPI_DELAY1 SPI_BASE + 0x2c /* Delay control 1 */ +#define SPI_FMT SPI_BASE + 0x40 /* Frame format */ +#define SPI_TXDATA SPI_BASE + 0x48 /* Tx FIFO data */ +#define SPI_RXDATA SPI_BASE + 0x4c /* Rx FIFO data */ +#define SPI_TXMARK SPI_BASE + 0x50 /* Tx FIFO [<35;39;29Mwatermark */ +#define SPI_RXMARK SPI_BASE + 0x54 /* Rx FIFO watermark */ /* Non-implemented -#define SPI_FCTRL 0x60 // SPI flash interface control -#define SPI_FFMT 0x64 // SPI flash instruction format +#define SPI_FCTRL SPI_BASE + 0x60 // SPI flash interface control +#define SPI_FFMT SPI_BASE + 0x64 // SPI flash instruction format */ -#define SPI_IE 0x70 /* Interrupt Enable Register */ -#define SPI_IP 0x74 /* Interrupt Pendings Register */ +#define SPI_IE SPI_BASE + 0x70 /* Interrupt Enable Register */ +#define SPI_IP SPI_BASE + 0x74 /* Interrupt Pendings Register */ /* delay0 bits */ #define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) @@ -37,9 +39,22 @@ #define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) #define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) -void write_reg(uintptr_t addr, uint32_t value); -uint32_t read_reg(uintptr_t addr); -uint8_t spi_send_byte(uint8_t byte); +/* csmode bits */ +#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U +#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U +#define SIFIVE_SPI_CSMODE_MODE_OFF 3U + + +#define WAITTX while(!(read_reg(SPI_IP) & 1) {} +#define WAITRX while(read_reg(SPI_IP) & 2) {} + +inline void write_reg(uintptr_t addr, uint32_t value); +inline uint32_t read_reg(uintptr_t addr); +inline void spi_sendbyte(uint8_t byte); +inline void waittx(); +inline void waitrx(); +uint8_t spi_txrx(uint8_t byte); +inline uint8_t spi_readbyte(); void spi_init(); From bf65cd2817b7a49a1dfb0bf16b2362f253da4fd9 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 14:18:42 -0500 Subject: [PATCH 08/39] Added uart print functions and the Wally banner. SD card can now be initialized. Removed old code from boot.c --- fpga/zsbl/boot.c | 441 ++++------------------------------------------- fpga/zsbl/boot.h | 10 ++ fpga/zsbl/sd.c | 76 ++++++-- fpga/zsbl/sd.h | 10 ++ fpga/zsbl/uart.c | 96 +++++++++++ fpga/zsbl/uart.h | 26 +++ 6 files changed, 239 insertions(+), 420 deletions(-) create mode 100644 fpga/zsbl/uart.c create mode 100644 fpga/zsbl/uart.h diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 6e4780f55..484bddaac 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -2,421 +2,54 @@ #include "boot.h" #include "gpt.h" -/* Card type flags (card_type) */ -#define CT_MMC 0x01 /* MMC ver 3 */ -#define CT_SD1 0x02 /* SD ver 1 */ -#define CT_SD2 0x04 /* SD ver 2 */ -#define CT_SDC (CT_SD1|CT_SD2) /* SD */ -#define CT_BLOCK 0x08 /* Block addressing */ +/* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ -#define CMD0 (0) /* GO_IDLE_STATE */ -#define CMD1 (1) /* SEND_OP_COND */ -#define CMD2 (2) /* SEND_CID */ -#define CMD3 (3) /* RELATIVE_ADDR */ -#define CMD4 (4) -#define CMD5 (5) /* SLEEP_WAKE (SDC) */ -#define CMD6 (6) /* SWITCH_FUNC */ -#define CMD7 (7) /* SELECT */ -#define CMD8 (8) /* SEND_IF_COND */ -#define CMD9 (9) /* SEND_CSD */ -#define CMD10 (10) /* SEND_CID */ -#define CMD11 (11) -#define CMD12 (12) /* STOP_TRANSMISSION */ -#define CMD13 (13) -#define CMD15 (15) -#define CMD16 (16) /* SET_BLOCKLEN */ -#define CMD17 (17) /* READ_SINGLE_BLOCK */ -#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ -#define CMD19 (19) -#define CMD20 (20) -#define CMD23 (23) -#define CMD24 (24) -#define CMD25 (25) -#define CMD27 (27) -#define CMD28 (28) -#define CMD29 (29) -#define CMD30 (30) -#define CMD32 (32) -#define CMD33 (33) -#define CMD38 (38) -#define CMD42 (42) -#define CMD55 (55) /* APP_CMD */ -#define CMD56 (56) -#define ACMD6 (0x80+6) /* define the data bus width */ -#define ACMD41 (0x80+41) /* SEND_OP_COND (ACMD) */ +/* /\* This is not needed. This has everything to do with the FAT */ +/* filesystem stuff that I'm not including. All I need to do is */ +/* initialize the SD card and read from it. Anything in here that is */ +/* checking for potential errors, I'm going to have to temporarily */ +/* do without. */ +/* *\/ */ +/* // if (!count) return RES_PARERR; */ +/* /\* if (drv_status & STA_NOINIT) return RES_NOTRDY; *\/ */ -// Capability bits -#define SDC_CAPABILITY_SD_4BIT 0x0001 -#define SDC_CAPABILITY_SD_RESET 0x0002 -#define SDC_CAPABILITY_ADDR 0xff00 - -// Control bits -#define SDC_CONTROL_SD_4BIT 0x0001 -#define SDC_CONTROL_SD_RESET 0x0002 - -// Card detect bits -#define SDC_CARD_INSERT_INT_EN 0x0001 -#define SDC_CARD_INSERT_INT_REQ 0x0002 -#define SDC_CARD_REMOVE_INT_EN 0x0004 -#define SDC_CARD_REMOVE_INT_REQ 0x0008 - -// Command status bits -#define SDC_CMD_INT_STATUS_CC 0x0001 // Command complete -#define SDC_CMD_INT_STATUS_EI 0x0002 // Any error -#define SDC_CMD_INT_STATUS_CTE 0x0004 // Timeout -#define SDC_CMD_INT_STATUS_CCRC 0x0008 // CRC error -#define SDC_CMD_INT_STATUS_CIE 0x0010 // Command code check error - -// Data status bits -#define SDC_DAT_INT_STATUS_TRS 0x0001 // Transfer complete -#define SDC_DAT_INT_STATUS_ERR 0x0002 // Any error -#define SDC_DAT_INT_STATUS_CTE 0x0004 // Timeout -#define SDC_DAT_INT_STATUS_CRC 0x0008 // CRC error -#define SDC_DAT_INT_STATUS_CFE 0x0010 // Data FIFO underrun or overrun - - -#define ERR_EOF 30 -#define ERR_NOT_ELF 31 -#define ERR_ELF_BITS 32 -#define ERR_ELF_ENDIANNESS 33 -#define ERR_CMD_CRC 34 -#define ERR_CMD_CHECK 35 -#define ERR_DATA_CRC 36 -#define ERR_DATA_FIFO 37 -#define ERR_BUF_ALIGNMENT 38 -#define FR_DISK_ERR 39 -#define FR_TIMEOUT 40 - -struct sdc_regs { - volatile uint32_t argument; - volatile uint32_t command; - volatile uint32_t response1; - volatile uint32_t response2; - volatile uint32_t response3; - volatile uint32_t response4; - volatile uint32_t data_timeout; - volatile uint32_t control; - volatile uint32_t cmd_timeout; - volatile uint32_t clock_divider; - volatile uint32_t software_reset; - volatile uint32_t power_control; - volatile uint32_t capability; - volatile uint32_t cmd_int_status; - volatile uint32_t cmd_int_enable; - volatile uint32_t dat_int_status; - volatile uint32_t dat_int_enable; - volatile uint32_t block_size; - volatile uint32_t block_count; - volatile uint32_t card_detect; - volatile uint32_t res_50; - volatile uint32_t res_54; - volatile uint32_t res_58; - volatile uint32_t res_5c; - volatile uint64_t dma_addres; -}; - -#define MAX_BLOCK_CNT 0x1000 - -#define SDC 0x00013000; - -// static struct sdc_regs * const regs __attribute__((section(".rodata"))) = (struct sdc_regs *)0x00013000; - -// static int errno __attribute__((section(".bss"))); -// static DSTATUS drv_status __attribute__((section(".bss"))); -// static BYTE card_type __attribute__((section(".bss"))); -// static uint32_t response[4] __attribute__((section(".bss"))); -// static int alt_mem __attribute__((section(".bss"))); - -/*static const char * errno_to_str(void) { - switch (errno) { - case ERR_EOF: return "Unexpected EOF"; - case ERR_NOT_ELF: return "Not an ELF file"; - case ERR_ELF_BITS: return "Wrong ELF word size"; - case ERR_ELF_ENDIANNESS: return "Wrong ELF endianness"; - case ERR_CMD_CRC: return "Command CRC error"; - case ERR_CMD_CHECK: return "Command code check error"; - case ERR_DATA_CRC: return "Data CRC error"; - case ERR_DATA_FIFO: return "Data FIFO error"; - case ERR_BUF_ALIGNMENT: return "Bad buffer alignment"; - case FR_DISK_ERR: return "Disk error"; - case FR_TIMEOUT: return "Timeout"; - } - return "Unknown error code"; - }*/ - -static void usleep(unsigned us) { - uintptr_t cycles0; - uintptr_t cycles1; - asm volatile ("csrr %0, 0xB00" : "=r" (cycles0)); - for (;;) { - asm volatile ("csrr %0, 0xB00" : "=r" (cycles1)); - if (cycles1 - cycles0 >= us * 100) break; - } -} - -static int sdc_cmd_finish(unsigned cmd, uint32_t * response) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; +/* uint32_t response[4]; */ +/* struct sdc_regs * regs = (struct sdc_regs *)SDC; */ - while (1) { - unsigned status = regs->cmd_int_status; - if (status) { - // clear interrupts - regs->cmd_int_status = 0; - while (regs->software_reset != 0) {} - if (status == SDC_CMD_INT_STATUS_CC) { - // get response - response[0] = regs->response1; - response[1] = regs->response2; - response[2] = regs->response3; - response[3] = regs->response4; - return 0; - } - /* errno = FR_DISK_ERR; - if (status & SDC_CMD_INT_STATUS_CTE) errno = FR_TIMEOUT; - if (status & SDC_CMD_INT_STATUS_CCRC) errno = ERR_CMD_CRC; - if (status & SDC_CMD_INT_STATUS_CIE) errno = ERR_CMD_CHECK;*/ - break; - } - } - return -1; -} +/* /\* Convert LBA to byte address if needed *\/ */ +/* if (!(card_type & CT_BLOCK)) sector *= 512; */ +/* while (count > 0) { */ +/* UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; */ +/* unsigned bytes = bcnt * 512; */ +/* if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; */ +/* if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; */ +/* sector += (card_type & CT_BLOCK) ? bcnt : bytes; */ +/* count -= bcnt; */ +/* buf += bytes; */ +/* } */ -static int sdc_data_finish(void) { - int status; - struct sdc_regs * regs = (struct sdc_regs *)SDC; - - while ((status = regs->dat_int_status) == 0) {} - regs->dat_int_status = 0; - while (regs->software_reset != 0) {} +/* return 0;; */ +/* } */ - if (status == SDC_DAT_INT_STATUS_TRS) return 0; - /* errno = FR_DISK_ERR; - if (status & SDC_DAT_INT_STATUS_CTE) errno = FR_TIMEOUT; - if (status & SDC_DAT_INT_STATUS_CRC) errno = ERR_DATA_CRC; - if (status & SDC_DAT_INT_STATUS_CFE) errno = ERR_DATA_FIFO;*/ - return -1; -} - -static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks, uint32_t * response) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; +int disk_read(BYTE * buf, LBA_t sector, UINT count) { - unsigned command = (cmd & 0x3f) << 8; - switch (cmd) { - case CMD0: - case CMD4: - case CMD15: - // No responce - break; - case CMD11: - case CMD13: - case CMD16: - case CMD17: - case CMD18: - case CMD19: - case CMD23: - case CMD24: - case CMD25: - case CMD27: - case CMD30: - case CMD32: - case CMD33: - case CMD42: - case CMD55: - case CMD56: - case ACMD6: - // R1 - command |= 1; // 48 bits - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD7: - case CMD12: - case CMD20: - case CMD28: - case CMD29: - case CMD38: - // R1b - command |= 1; // 48 bits - command |= 1 << 2; // busy - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD2: - case CMD9: - case CMD10: - // R2 - command |= 2; // 136 bits - command |= 1 << 3; // resp CRC - break; - case ACMD41: - // R3 - command |= 1; // 48 bits - break; - case CMD3: - // R6 - command |= 1; // 48 bits - command |= 1 << 2; // busy - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - case CMD8: - // R7 - command |= 1; // 48 bits - command |= 1 << 3; // resp CRC - command |= 1 << 4; // resp OPCODE - break; - } - - if (blocks) { - command |= 1 << 5; - if ((intptr_t)buf & 3) { - // errno = ERR_BUF_ALIGNMENT; - return -1; - } - regs->dma_addres = (uint64_t)(intptr_t)buf; - regs->block_size = 511; - regs->block_count = blocks - 1; - regs->data_timeout = 0x1FFFFFF; - } - - regs->command = command; - regs->cmd_timeout = 0xFFFFF; - regs->argument = arg; - - if (sdc_cmd_finish(cmd, response) < 0) return -1; - if (blocks) return sdc_data_finish(); - - return 0; -} - -#define send_cmd(cmd, arg, response) send_data_cmd(cmd, arg, NULL, 0, response) - -static BYTE ini_sd(void) { - struct sdc_regs * regs = (struct sdc_regs *)SDC; - unsigned rca; - BYTE card_type; - uint32_t response[4]; - - /* Reset controller */ - regs->software_reset = 1; - while ((regs->software_reset & 1) == 0) {} - - // This clock divider is meant to initialize the card at - // 400kHz - - // 22MHz/400kHz = 55 (base 10) = 0x37 - 0x01 = 0x36 - regs->clock_divider = 0x36; - regs->software_reset = 0; - while (regs->software_reset) {} - usleep(5000); - - card_type = 0; - // drv_status = STA_NOINIT; - - if (regs->capability & SDC_CAPABILITY_SD_RESET) { - /* Power cycle SD card */ - regs->control |= SDC_CONTROL_SD_RESET; - usleep(1000000); - regs->control &= ~SDC_CONTROL_SD_RESET; - usleep(100000); - } - - /* Enter Idle state */ - send_cmd(CMD0, 0, response); - - card_type = CT_SD1; - if (send_cmd(CMD8, 0x1AA, response) == 0) { - if ((response[0] & 0xfff) != 0x1AA) { - // errno = ERR_CMD_CHECK; - return -1; - } - card_type = CT_SD2; - } - - /* Wait for leaving idle state (ACMD41 with HCS bit) */ - while (1) { - /* ACMD41, Set Operating Conditions: Host High Capacity & 3.3V */ - if (send_cmd(CMD55, 0, response) < 0 || send_cmd(ACMD41, 0x40300000, response) < 0) return -1; - if (response[0] & (1 << 31)) { - if (response[0] & (1 << 30)) card_type |= CT_BLOCK; - break; - } - } - - /* Enter Identification state */ - if (send_cmd(CMD2, 0, response) < 0) return -1; - - /* Get RCA (Relative Card Address) */ - rca = 0x1234; - if (send_cmd(CMD3, rca << 16, response) < 0) return -1; - rca = response[0] >> 16; - - /* Select card */ - if (send_cmd(CMD7, rca << 16, response) < 0) return -1; - - /* Clock 25MHz */ - // 22Mhz/2 = 11Mhz - regs->clock_divider = 1; - usleep(10000); - - /* Bus width 1-bit */ - regs->control = 0; - if (send_cmd(CMD55, rca << 16, response) < 0 || send_cmd(ACMD6, 0, response) < 0) return -1; - - /* Set R/W block length to 512 */ - if (send_cmd(CMD16, 512, response) < 0) return -1; - - // drv_status &= ~STA_NOINIT; - return card_type; -} - -int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { - - /* This is not needed. This has everything to do with the FAT - filesystem stuff that I'm not including. All I need to do is - initialize the SD card and read from it. Anything in here that is - checking for potential errors, I'm going to have to temporarily - do without. - */ - // if (!count) return RES_PARERR; - /* if (drv_status & STA_NOINIT) return RES_NOTRDY; */ - - uint32_t response[4]; - struct sdc_regs * regs = (struct sdc_regs *)SDC; - - /* Convert LBA to byte address if needed */ - if (!(card_type & CT_BLOCK)) sector *= 512; - while (count > 0) { - UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; - unsigned bytes = bcnt * 512; - if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; - if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; - sector += (card_type & CT_BLOCK) ? bcnt : bytes; - count -= bcnt; - buf += bytes; - } - - return 0;; } +// copyFlash: -------------------------------------------------------- +// A lot happens in this function: +// * The Wally banner is printed +// * The peripherals are initialized void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { - BYTE card_type; int ret = 0; - - card_type = ini_sd(); - // BYTE * buf = (BYTE *)Dst; - - // if (disk_read(buf, (LBA_t)address, (UINT)numBlocks, card_type) < 0) /* UART Print function?*/; + // Initialize UART for messages + init_uart(); + + // Print the wally banner + print_uart(BANNER); + + + init_sd(); ret = gpt_load_partitions(card_type); } - -/* -int main() { - ini_sd(); - - - return 0; -} -*/ diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 77d403145..cb0f4e7f3 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -19,6 +19,16 @@ typedef QWORD LBA_t; #define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START #define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR +#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\n" \ +" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\n" \ +" █▄█ █▄█ █ █ █▄▄ ▀▄▀\n" \ +" ____ ____ ____ ___ ___ ____ ___\n" \ +" \\ \\ / / / \\ | | | | \\ \\ / /\n" \ +" \\ \\ __ / / / \\ | | | | \\ \\/ /\n" \ +" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\n" \ +" \\ / / ____ \\ | |___ | |___ | |\n" \ +" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\n\n" + // Export disk_read int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type); diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index aacea0db9..4669aeb0b 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,5 +1,6 @@ #include "sd.h" #include "spi.h" +#include "uart.h" // Parallel byte update CRC7-CCITT algorithm. // The result is the CRC7 result, left shifted over by 1 @@ -23,27 +24,44 @@ uint16_t crc16(uint16_t crc, uint8_t data) { return crc; } +// sd_cmd ------------------------------------------------------------ +// Sends SD card command using SPI mode. +// This function: +// * Chooses the response length based on the input command +// * Makes use of SPI's full duplex. For every byte sent, +// a byte is received. Thus for every byte sent as part of +// a command, a useless byte must be read from the receive +// FIFO. +// * Takes advantage of the Sifive SPI peripheral spec's +// watermark and interrupt features to determine when a +// transfer is complete. This should save on cycles since +// no arbitrary delays need to be added. uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t response_len; uint8_t i; uint64_t r; uint8_t rbyte; - + + // Initialize the response with 0's. + r = 0; + + // Choose response length based on cmd input. + // Most commands return an R1 format response. switch (cmd) { - case 0: - response_len = 1; - break; case 8: - response_len = 7 + response_len = R7_RESPONSE; break; + case 12: + response_len = R1B_RESPONSE; default: - response_len = 1; + response_len = R1_RESPONSE; break; } // Make interrupt pending after response fifo receives the correct - // response length. - write_reg(SPI_RXMARK, response_len); + // response length. Probably unecessary so let's wait and see what + // happens. + // write_reg(SPI_RXMARK, response_len); // Write all 6 bytes into transfer fifo spi_sendbyte(0x40 | cmd); @@ -79,18 +97,44 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { } return r; -} +} // sd_cmd -#define cmd0() sd_cmd( 0, 0x00000000, 0x95) -#define cmd8() sd_cmd( 8, 0x000001aa, 0x87) -// CMD55 has to be sent before ACMD41 (it means the next command is -// application specific) -#define cmd55() sd_cmd(55, 0x00000000, 0x65) -#defube acmd41() sd_cmd(41, 0x40000000, 0x77) +// Utility defines for CMD0, CMD8, CMD55, and ACMD41 +#define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state +#define CMD8() sd_cmd( 8, 0x000001aa, 0x87) // +#define CMD55() sd_cmd(55, 0x00000000, 0x65) // +#define ACMD41() sd_cmd(41, 0x40000000, 0x77) // +// init_sd: ---------------------------------------------------------- +// This first initializes the SPI peripheral then initializes the SD +// card itself. We use the uart to display anything that goes wrong. void init_sd(){ init_spi(); - cmd0() + uint64_t r; + + print_uart("Initializing SD Card in SPI mode"); + + // Reset SD Card command + // Initializes SD card into SPI mode if CS is asserted '0' + if (!(( r = CMD0() ) & 0x10) ) { + print_uart("SD ERROR: "); + print_uart_byte(r & 0xff); + print_uart("\r\n"); + } + + // + if (!(( r = CMD8() ) & 0x10 )) { + print_uart("SD ERROR: "); + print_uart_byte(r & 0xff); + print_uart("\r\n"); + } + + do { + CMD55(); + r = ACMD41(); + } while (r == 0x1); + + print_uart("SD card is initialized"); } diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index f08941364..a70d203e7 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -2,6 +2,16 @@ #include +// Command names +#define SD_CMD_STOP_TRANSMISSION 12 +#define SD_CMD_READ_BLOCK_MULTIPLE 18 +#define SD_DATA_TOKEN 0xfe + +// Response lengths in bytes +#define R1_RESPONSE 1 +#define R7_RESPONSE 7 +#define R1B_RESPONSE 2 + uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c new file mode 100644 index 000000000..a08690069 --- /dev/null +++ b/fpga/zsbl/uart.c @@ -0,0 +1,96 @@ +#include "uart.h" + + +void write_reg_u8(uintptr_t addr, uint8_t value) +{ + volatile uint8_t *loc_addr = (volatile uint8_t *)addr; + *loc_addr = value; +} + +uint8_t read_reg_u8(uintptr_t addr) +{ + return *(volatile uint8_t *)addr; +} + +int is_transmit_empty() +{ + return read_reg_u8(UART_LINE_STATUS) & 0x20; +} + +int is_receive_empty() +{ + return !(read_reg_u8(UART_LINE_STATUS) & 0x1); +} + +void write_serial(char a) +{ + while (is_transmit_empty() == 0) {}; + + write_reg_u8(UART_THR, a); +} + +void init_uart(uint32_t freq, uint32_t baud) +{ + uint32_t divisor = freq / (baud << 4); + + write_reg_u8(UART_IER, 0x00); // Disable all interrupts + write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) + write_reg_u8(UART_DLL, divisor); // divisor (lo byte) + write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) + write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit + write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold +} + +void print_uart(const char *str) +{ + const char *cur = &str[0]; + while (*cur != '\0') + { + write_serial((uint8_t)*cur); + ++cur; + } +} + +uint8_t bin_to_hex_table[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + +void bin_to_hex(uint8_t inp, uint8_t res[2]) +{ + res[1] = bin_to_hex_table[inp & 0xf]; + res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; + return; +} + +void print_uart_int(uint32_t addr) +{ + int i; + for (i = 3; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_addr(uint64_t addr) +{ + int i; + for (i = 7; i > -1; i--) + { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } +} + +void print_uart_byte(uint8_t byte) +{ + uint8_t hex[2]; + bin_to_hex(byte, hex); + write_serial(hex[0]); + write_serial(hex[1]); +} diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h new file mode 100644 index 000000000..18710e76b --- /dev/null +++ b/fpga/zsbl/uart.h @@ -0,0 +1,26 @@ +#pragma once +#include + +#define UART_BASE 0x10000000 + +#define UART_RBR UART_BASE + 0x00 +#define UART_THR UART_BASE + 0x00 +#define UART_IER UART_BASE + 0x01 +#define UART_IIR UART_BASE + 0x02 +#define UART_FCR UART_BASE + 0x02 +#define UART_LCR UART_BASE + 0x03 +#define UART_MCR UART_BASE + 0x04 +#define UART_LSR UART_BASE + 0x05 +#define UART_MSR UART_BASE + 0x06 +#define UART_SCR UART_BASE + 0x07 +#define UART_DLL UART_BASE + 0x00 +#define UART_DLM UART_BASE + 0x01 + +void init_uart(); +void write_reg_u8(uintptr_t addr, uint8_t value); +uint8_t read_reg_u8(uintptr_t addr); +int read_serial(uint8_t *res); +void print_uart(const char* str); +void print_uart_int(uint32_t addr); +void print_uart_addr(uint64_t addr); +void print_uart_byte(uint8_t byte); From 9ccb0eb027679351e81d9cf41d0cfd494fe05e24 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 15:46:18 -0500 Subject: [PATCH 09/39] Removed references to card_type. --- fpga/zsbl/gpt.c | 12 ++++++------ fpga/zsbl/gpt.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 97e3e4e46..65f56924b 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -10,7 +10,7 @@ */ -int gpt_load_partitions(BYTE card_type) { +int gpt_load_partitions() { // In this version of the GPT partition code // I'm going to assume that the SD card is already initialized. @@ -21,7 +21,7 @@ int gpt_load_partitions(BYTE card_type) { int ret = 0; //ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */); - ret = disk_read(lba1_buf, 1, 1, card_type); + ret = disk_read(lba1_buf, 1, 1); /* Possible error handling with UART message if ( ret != 0 ) { @@ -31,16 +31,16 @@ int gpt_load_partitions(BYTE card_type) { gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf; BYTE lba2_buf[512]; - ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1, card_type); + ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1); // Load parition entries for the relevant boot partitions. partition_entries_t *fdt = (partition_entries_t *)(lba2_buf); partition_entries_t *opensbi = (partition_entries_t *)(lba2_buf + 128); partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); - ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1, card_type); - ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1, card_type); - ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1, card_type); + ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); + ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); + ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); return 0; } diff --git a/fpga/zsbl/gpt.h b/fpga/zsbl/gpt.h index 4aefae229..5ce5e1d4b 100644 --- a/fpga/zsbl/gpt.h +++ b/fpga/zsbl/gpt.h @@ -37,4 +37,4 @@ typedef struct partition_entries } partition_entries_t; // Find boot partition and load it to the destination -int gpt_load_partitions(BYTE card_type); +int gpt_load_partitions(); From 57eeba5c8ca7efa6f202ab915259b2c8ddb7720e Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 15:47:23 -0500 Subject: [PATCH 10/39] Progress made on implementing new disk read function. --- fpga/zsbl/boot.c | 25 ++++++++++++++++++++++++- fpga/zsbl/sd.c | 1 + fpga/zsbl/spi.c | 18 ++++++++++++++++++ fpga/zsbl/spi.h | 2 +- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 484bddaac..16f7c0430 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -1,6 +1,9 @@ #include #include "boot.h" #include "gpt.h" +#include "uart.h" +#include "spi.h" +#include "sd.h" /* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ @@ -32,7 +35,27 @@ /* } */ int disk_read(BYTE * buf, LBA_t sector, UINT count) { + uint64_t r; + UINT i; + uint8_t crc = 0; + crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE); + crc = crc7(crc, (sector >> 24) & 0xff); + crc = crc7(crc, (sector >> 16) & 0xff); + crc = crc7(crc, (sector >> 8) & 0xff); + crc = crc7(crc, sector & 0xff); + crc = crc | 1; + + if (sd_cmd(18, sector &, crc) != 0x00) { + print_uart("disk_read: CMD18 failed. r = "); + print_byte(r & 0xff); + return -1; + } + + // Begin reading + for (i = 0; i < count; i++) { + + } } // copyFlash: -------------------------------------------------------- @@ -48,7 +71,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Print the wally banner print_uart(BANNER); - + // Intialize the SD card init_sd(); ret = gpt_load_partitions(card_type); diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 4669aeb0b..c2a6eed54 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -99,6 +99,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { return r; } // sd_cmd + // Utility defines for CMD0, CMD8, CMD55, and ACMD41 #define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state #define CMD8() sd_cmd( 8, 0x000001aa, 0x87) // diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index c812327f4..687a98ceb 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -58,6 +58,24 @@ inline void waitrx() { while(read_reg(SPI_IP) & 2)) {} } +uint64_t spi_read64() { + uint64_t r; + uint8_t rbyte; + int i; + + for (i = 0; i < 8; i++) { + spi_sendbyte(0xFF); + } + + waittx(); + + for (i = 0; i < 8; i++) { + rbyte = spi_readbyte(); + r = r | (rbyte << ((8 - 1 - i)*8)); + } + + return r; +} // Initialize Sifive FU540 based SPI Controller void spi_init() { diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index a035f0ab5..e91bcc0ea 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -55,7 +55,7 @@ inline void waittx(); inline void waitrx(); uint8_t spi_txrx(uint8_t byte); inline uint8_t spi_readbyte(); - +uint64_t spi_read64(); void spi_init(); #endif From ab00ea5a5cffd862d855e067d57fb4ab3928bb68 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 16:32:29 -0500 Subject: [PATCH 11/39] Added sd_read64 to help with block reads and crc checking. --- fpga/zsbl/sd.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index c2a6eed54..87e78e7fe 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -99,6 +99,25 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { return r; } // sd_cmd +uint64_t sd_read64(uint16_t * crc) { + uint64_t r; + uint8_t rbyte; + int i; + + for (i = 0; i < 8; i++) { + spi_sendbyte(0xFF); + } + + waittx(); + + for (i = 0; i < 8; i++) { + rbyte = spi_readbyte(); + *crc = crc16(*crc, rbyte); + r = r | (rbyte << ((8 - 1 - i)*8)); + } + + return r; +} // Utility defines for CMD0, CMD8, CMD55, and ACMD41 #define CMD0() sd_cmd( 0, 0x00000000, 0x95) // Reset SD card into IDLE state From a8b9e7776b4d2fd029f0a2b6f75566ce45d2d81d Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 16:32:52 -0500 Subject: [PATCH 12/39] Added some minor error checking to gpt.c. --- fpga/zsbl/gpt.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 65f56924b..90948935b 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -38,9 +38,26 @@ int gpt_load_partitions() { partition_entries_t *opensbi = (partition_entries_t *)(lba2_buf + 128); partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); + // Load device tree ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); + if (ret < 0) { + print_uart("Failed to load device tree!"); + return -1; + } + + // Load OpenSBI ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); + if (ret < 0) { + print_uart("Failed to load OpenSBI!"); + return -1; + } + + // Load Linux ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); + if (ret < 0) { + print_uart("Failed to load Linux!"); + return -1; + } return 0; } From 5f0addd69a25a0b1384ea6cd64f0419058f8f311 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 16:33:49 -0500 Subject: [PATCH 13/39] Initial pass on SPI based bootloader code finished. --- fpga/zsbl/boot.c | 32 +++++++++++++++++++++++++++++++- fpga/zsbl/sd.h | 1 + fpga/zsbl/spi.c | 6 ++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 16f7c0430..96bde4205 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -52,10 +52,40 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { return -1; } - // Begin reading + // Begin reading blocks for (i = 0; i < count; i++) { + uint16_t crc, crc_exp; + + // Read the data token + r = spi_readbyte(); + if (r != SD_DATA_TOKEN) { + print_uart("Didn't receive data token first thing. Shoot: "); + print_byte(r & 0xff); + return -1; + } + + // Read block into memory. + for (int j = 0; j < 8; j++) { + *buf = sd_read64(&crc); + buf = buf + 64; + } + + // Read CRC16 and check + crc_exp = ((uint16_t)spi_txrx(0xff) << 8); + crc_exp |= spi_txrx(0xff); + + if (crc != crc_exp) { + print_uart("Stinking CRC16 didn't match on block "); + print_int(i); + print_uart("\r\n"); + return -1; + } } + + sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01); + spi_txrx(0xff); + return 0; } // copyFlash: -------------------------------------------------------- diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index a70d203e7..37e4a2c94 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -15,4 +15,5 @@ uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); +uint64_t sd_read64(uint16_t * crc); void init_sd(); diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 687a98ceb..76985a350 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -58,6 +58,12 @@ inline void waitrx() { while(read_reg(SPI_IP) & 2)) {} } +uint8_t spi_txrx(uint8_t byte) { + spi_sendbyte(0xFF); + waittx(); + return spi_readbyte(); +} + uint64_t spi_read64() { uint64_t r; uint8_t rbyte; From dcb2edf8888175f078d10b80c491a7df264bafac Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 17:00:32 -0500 Subject: [PATCH 14/39] Fixed syntax bugs. inline functions are now static and in the spi.h header. --- fpga/zsbl/boot.c | 10 +++++----- fpga/zsbl/boot.h | 2 +- fpga/zsbl/sd.c | 2 +- fpga/zsbl/spi.c | 46 +++++++++++++++++++++++----------------------- fpga/zsbl/spi.h | 48 ++++++++++++++++++++++++++++++++++++++---------- fpga/zsbl/uart.c | 4 ++-- 6 files changed, 70 insertions(+), 42 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 96bde4205..786879c49 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -46,9 +46,9 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { crc = crc7(crc, sector & 0xff); crc = crc | 1; - if (sd_cmd(18, sector &, crc) != 0x00) { + if (sd_cmd(18, sector & 0xffffffff, crc) != 0x00) { print_uart("disk_read: CMD18 failed. r = "); - print_byte(r & 0xff); + print_uart_byte(r & 0xff); return -1; } @@ -60,7 +60,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { r = spi_readbyte(); if (r != SD_DATA_TOKEN) { print_uart("Didn't receive data token first thing. Shoot: "); - print_byte(r & 0xff); + print_uart_byte(r & 0xff); return -1; } @@ -76,7 +76,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { if (crc != crc_exp) { print_uart("Stinking CRC16 didn't match on block "); - print_int(i); + print_uart_int(i); print_uart("\r\n"); return -1; } @@ -104,5 +104,5 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Intialize the SD card init_sd(); - ret = gpt_load_partitions(card_type); + ret = gpt_load_partitions(); } diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index cb0f4e7f3..2048ca47c 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -30,7 +30,7 @@ typedef QWORD LBA_t; " \\___/\\___/ /___/ \\___\\|_______||_______| |___|\n\n" // Export disk_read -int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type); +int disk_read(BYTE * buf, LBA_t sector, UINT count); #endif // WALLYBOOT diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 87e78e7fe..585b98281 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -129,7 +129,7 @@ uint64_t sd_read64(uint16_t * crc) { // This first initializes the SPI peripheral then initializes the SD // card itself. We use the uart to display anything that goes wrong. void init_sd(){ - init_spi(); + spi_init(); uint64_t r; diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 76985a350..cbb9fa2eb 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -30,33 +30,29 @@ #include "spi.h" // Write to a register -inline void write_reg(uintptr_t addr, uint32_t value) { - volatile uint32_t * loc = (volatile uint32_t *) addr; - *loc = value; -} +/* inline void write_reg(uintptr_t addr, uint32_t value) { */ +/* volatile uint32_t * loc = (volatile uint32_t *) addr; */ +/* *loc = value; */ +/* } */ -// Read a register -inline void read_reg(uintptr_t addr) { - return *(volatile uint32_t *) addr; -} +/* // Read a register */ +/* inline uint32_t read_reg(uintptr_t addr) { */ +/* return *(volatile uint32_t *) addr; */ +/* } */ -// Queues a single byte in the transfer fifo -inline void spi_sendbyte(uint8_t byte) { - // Write byte to transfer fifo - write_reg(SPI_TXDATA, byte); -} +/* // Queues a single byte in the transfer fifo */ +/* inline void spi_sendbyte(uint8_t byte) { */ +/* // Write byte to transfer fifo */ +/* write_reg(SPI_TXDATA, byte); */ +/* } */ -inline uint8_t spi_readbyte() { - return read_reg(SPI_RXDATA); -} +/* inline void waittx() { */ +/* while(!(read_reg(SPI_IP) & 1)) {} */ +/* } */ -inline void waittx() { - while(!(read_reg(SPI_IP) & 1)) {} -} - -inline void waitrx() { - while(read_reg(SPI_IP) & 2)) {} -} +/* inline void waitrx() { */ +/* while(read_reg(SPI_IP) & 2) {} */ +/* } */ uint8_t spi_txrx(uint8_t byte) { spi_sendbyte(0xFF); @@ -64,6 +60,10 @@ uint8_t spi_txrx(uint8_t byte) { return spi_readbyte(); } +/* inline uint8_t spi_readbyte() { */ +/* return read_reg(SPI_RXDATA); */ +/* } */ + uint64_t spi_read64() { uint64_t r; uint8_t rbyte; diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index e91bcc0ea..bc85c768f 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -28,15 +28,15 @@ #define SPI_IP SPI_BASE + 0x74 /* Interrupt Pendings Register */ /* delay0 bits */ -#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((uint32_t)(x)) #define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU -#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((uint32_t)(x) << 16) #define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) /* delay1 bits */ -#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((uint32_t)(x)) #define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU -#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((uint32_t)(x) << 16) #define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) /* csmode bits */ @@ -48,14 +48,42 @@ #define WAITTX while(!(read_reg(SPI_IP) & 1) {} #define WAITRX while(read_reg(SPI_IP) & 2) {} -inline void write_reg(uintptr_t addr, uint32_t value); -inline uint32_t read_reg(uintptr_t addr); -inline void spi_sendbyte(uint8_t byte); -inline void waittx(); -inline void waitrx(); +// inline void write_reg(uintptr_t addr, uint32_t value); +//inline uint32_t read_reg(uintptr_t addr); +//inline void spi_sendbyte(uint8_t byte); +//inline void waittx(); +//inline void waitrx(); uint8_t spi_txrx(uint8_t byte); -inline uint8_t spi_readbyte(); +//inline uint8_t spi_readbyte(); uint64_t spi_read64(); void spi_init(); +static inline void write_reg(uintptr_t addr, uint32_t value) { + volatile uint32_t * loc = (volatile uint32_t *) addr; + *loc = value; +} + +// Read a register +static inline uint32_t read_reg(uintptr_t addr) { + return *(volatile uint32_t *) addr; +} + +// Queues a single byte in the transfer fifo +static inline void spi_sendbyte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); +} + +static inline void waittx() { + while(!(read_reg(SPI_IP) & 1)) {} +} + +static inline void waitrx() { + while(read_reg(SPI_IP) & 2) {} +} + +static inline uint8_t spi_readbyte() { + return read_reg(SPI_RXDATA); +} + #endif diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index a08690069..be3270e28 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -14,12 +14,12 @@ uint8_t read_reg_u8(uintptr_t addr) int is_transmit_empty() { - return read_reg_u8(UART_LINE_STATUS) & 0x20; + return read_reg_u8(UART_LSR) & 0x20; } int is_receive_empty() { - return !(read_reg_u8(UART_LINE_STATUS) & 0x1); + return !(read_reg_u8(UART_LSR) & 0x1); } void write_serial(char a) From f1cc7dd5a378111c05f84f80601bd79fe5589442 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 23 Jul 2024 17:26:39 -0500 Subject: [PATCH 15/39] Fixed verilog bugs. --- fpga/src/fpgaTopArtyA7.sv | 3 +-- src/uncore/uncore.sv | 4 ++-- src/wally/wallypipelinedsoc.sv | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 6a2f055ba..31848f33e 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -80,7 +80,6 @@ module fpgaTop wire [63:0] HRDATAEXT; wire HREADYEXT; wire HRESPEXT; - wire HSELEXTSDC; // TEMP BOOT SIGNAL - JACOB wire HSELEXT; wire [55:0] HADDR; wire [63:0] HWDATA; @@ -240,7 +239,7 @@ module fpgaTop wallypipelinedsoc #(P) wallypipelinedsoc(.clk(CPUCLK), .reset_ext(bus_struct_reset), .reset(), .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, - .HSELEXTSDC, .HCLK(HCLKOpen), .HRESETn(HRESETnOpen), + .HCLK(HCLKOpen), .HRESETn(HRESETnOpen), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index dad558c19..c3414352f 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -168,9 +168,9 @@ module uncore import cvw::*; #(parameter cvw_t P)( if (P.SDC_SUPPORTED == 1) begin : sdc spi_apb #(P) sdc( - .PCLK, .PRESETN, .PSEL(.PSEL[5]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, + .PCLK, .PRESETn, .PSEL(PSEL[5]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE, .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), - .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(.SDCIntr)); + .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(SDCIntr)); end else begin : sdc assign SDCCmd = '0; assign SDCCD = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; end diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index af9f0ff26..7ad173b78 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -35,7 +35,6 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( input logic [P.AHBW-1:0] HRDATAEXT, input logic HREADYEXT, HRESPEXT, output logic HSELEXT, - output logic HSELEXTSDC, // outputs to external memory, shared with uncore memory output logic HCLK, HRESETn, output logic [P.PA_BITS-1:0] HADDR, @@ -86,11 +85,11 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( if (P.BUS_SUPPORTED) begin : uncoregen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 uncore #(P) uncore(.HCLK, .HRESETn, .TIMECLK, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT, - .HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC, + .HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin, .UARTSout, .MTIME_CLINT, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); end else begin - assign {HRDATA, HREADY, HRESP, HSELEXT, HSELEXTSDC, MTimerInt, MSwInt, MExtInt, SExtInt, + assign {HRDATA, HREADY, HRESP, HSELEXT, MTimerInt, MSwInt, MExtInt, SExtInt, MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; end From 0107a400d175a06c653cfd824e83ef2f602d1836 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 24 Jul 2024 22:43:16 -0500 Subject: [PATCH 16/39] Added uart header to gpt.c. --- fpga/zsbl/gpt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 90948935b..c308ea878 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -1,5 +1,6 @@ #include "gpt.h" #include "boot.h" +#include "uart.h" #include /* PSUEDOCODE From 286d80de7e45c6cbb53b4dfacd37c202876e9c84 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 24 Jul 2024 22:43:47 -0500 Subject: [PATCH 17/39] Initialized UART with Arty frequency and baud rate. Will make this dynamic in the future --- fpga/zsbl/boot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 786879c49..e8065f732 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -96,7 +96,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { int ret = 0; // Initialize UART for messages - init_uart(); + init_uart(20000000, 115200); // Print the wally banner print_uart(BANNER); From d15be492cb5cce505f04ef9c450915a8b668fb45 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 24 Jul 2024 22:44:27 -0500 Subject: [PATCH 18/39] Masked lower byte when writing to DLL. --- fpga/zsbl/uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index be3270e28..7ff40e516 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -35,7 +35,7 @@ void init_uart(uint32_t freq, uint32_t baud) write_reg_u8(UART_IER, 0x00); // Disable all interrupts write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) - write_reg_u8(UART_DLL, divisor); // divisor (lo byte) + write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte) write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold From 2caf9e93be6693a0ff45056b97ee003e83ab24c8 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 24 Jul 2024 22:46:24 -0500 Subject: [PATCH 19/39] Removed old axi IP from fpga Makefile. Added sed for data.mem file loaded into uncore ram. --- fpga/generator/Makefile | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/fpga/generator/Makefile b/fpga/generator/Makefile index df4ed0e2a..7865d33ee 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -1,14 +1,14 @@ dst := IP # vcu118 -#export XILINX_PART := xcvu9p-flga2104-2L-e -#export XILINX_BOARD := xilinx.com:vcu118:part0:2.4 -#export board := vcu118 +# export XILINX_PART := xcvu9p-flga2104-2L-e +# export XILINX_BOARD := xilinx.com:vcu118:part0:2.4 +# export board := vcu118 # vcu108 -#export XILINX_PART := xcvu095-ffva2104-2-e -#export XILINX_BOARD := xilinx.com:vcu108:part0:1.2 -#export board := vcu108 +# export XILINX_PART := xcvu095-ffva2104-2-e +# export XILINX_BOARD := xilinx.com:vcu108:part0:1.7 +# export board := vcu108 # Arty A7 export XILINX_PART := xc7a100tcsg324-1 @@ -40,11 +40,11 @@ IP_Arty: $(dst)/xlnx_proc_sys_reset.log \ $(dst)/xlnx_ddr3-$(board).log \ $(dst)/xlnx_mmcm.log \ $(dst)/xlnx_axi_clock_converter.log \ - $(dst)/xlnx_ahblite_axi_bridge.log \ - $(dst)/xlnx_axi_crossbar.log \ - $(dst)/xlnx_axi_dwidth_conv_32to64.log \ - $(dst)/xlnx_axi_dwidth_conv_64to32.log \ - $(dst)/xlnx_axi_prtcl_conv.log + $(dst)/xlnx_ahblite_axi_bridge.log +#$(dst)/xlnx_axi_crossbar.log \ +#$(dst)/xlnx_axi_dwidth_conv_32to64.log \ +#$(dst)/xlnx_axi_dwidth_conv_64to32.log \ +#$(dst)/xlnx_axi_prtcl_conv.log PreProcessFiles: @@ -59,6 +59,7 @@ PreProcessFiles: # This line allows the Bootloader to be loaded in a Block RAM on the FPGA sed -i "s/bit \[DATA_WIDTH-1:0\].*ROM.*/(\* rom_style=\"block\" \*) &/g" ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv + sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/ram1p1rwbe.sv $(dst)/%.log: %.tcl mkdir -p IP From ebdf25a53b0936b04adcd9e17598acaed111e4bd Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 24 Jul 2024 22:47:15 -0500 Subject: [PATCH 20/39] Commented out references to old axi IP from wally.tcl. --- fpga/generator/wally.tcl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index eff0a6cb9..9acdad4b6 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -27,10 +27,10 @@ read_ip IP/xlnx_proc_sys_reset.srcs/sources_1/ip/xlnx_proc_sys_reset/xlnx_proc_s read_ip IP/xlnx_ahblite_axi_bridge.srcs/sources_1/ip/xlnx_ahblite_axi_bridge/xlnx_ahblite_axi_bridge.xci read_ip IP/xlnx_axi_clock_converter.srcs/sources_1/ip/xlnx_axi_clock_converter/xlnx_axi_clock_converter.xci # Added crossbar - Jacob Pease <2023-01-12 Thu> -read_ip IP/xlnx_axi_crossbar.srcs/sources_1/ip/xlnx_axi_crossbar/xlnx_axi_crossbar.xci -read_ip IP/xlnx_axi_dwidth_conv_32to64.srcs/sources_1/ip/xlnx_axi_dwidth_conv_32to64/xlnx_axi_dwidth_conv_32to64.xci -read_ip IP/xlnx_axi_dwidth_conv_64to32.srcs/sources_1/ip/xlnx_axi_dwidth_conv_64to32/xlnx_axi_dwidth_conv_64to32.xci -read_ip IP/xlnx_axi_prtcl_conv.srcs/sources_1/ip/xlnx_axi_prtcl_conv/xlnx_axi_prtcl_conv.xci +#read_ip IP/xlnx_axi_crossbar.srcs/sources_1/ip/xlnx_axi_crossbar/xlnx_axi_crossbar.xci +#read_ip IP/xlnx_axi_dwidth_conv_32to64.srcs/sources_1/ip/xlnx_axi_dwidth_conv_32to64/xlnx_axi_dwidth_conv_32to64.xci +#read_ip IP/xlnx_axi_dwidth_conv_64to32.srcs/sources_1/ip/xlnx_axi_dwidth_conv_64to32/xlnx_axi_dwidth_conv_64to32.xci +#read_ip IP/xlnx_axi_prtcl_conv.srcs/sources_1/ip/xlnx_axi_prtcl_conv/xlnx_axi_prtcl_conv.xci if {$board=="ArtyA7"} { read_ip IP/xlnx_ddr3.srcs/sources_1/ip/xlnx_ddr3/xlnx_ddr3.xci @@ -89,8 +89,8 @@ report_clock_interaction -file re write_verilog -force -mode funcsim sim/syn-funcsim.v if {$board=="ArtyA7"} { - source ../constraints/small-debug.xdc - + #source ../constraints/small-debug.xdc + source ../constraints/medium-debug.xdc } else { # source ../constraints/vcu-small-debug.xdc source ../constraints/debug6.xdc From 0dae881a0dadd83d9bb5a5a139819be9664f618d Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 24 Jul 2024 22:48:31 -0500 Subject: [PATCH 21/39] Fixed SDCCLK name discrepency. --- fpga/constraints/constraints-ArtyA7.xdc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index f466b0c30..4e156601b 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -101,7 +101,7 @@ set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports { set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[0]}] -set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCClk}] +set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCLK}] set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] From 336a413f3185b089223a75d3b1d43e8f12465611 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 25 Jul 2024 11:19:15 -0500 Subject: [PATCH 22/39] Added ability to split boot.memfile into boot.mem and data.mem. --- fpga/zsbl/Makefile | 9 ++++++-- src/generic/mem/ram1p1rwbe.sv | 23 +++++++++++++++++---- src/uncore/uncore.sv | 10 ++++----- testbench/testbench.sv | 39 ++++++++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/fpga/zsbl/Makefile b/fpga/zsbl/Makefile index 37323b813..85bfc67eb 100644 --- a/fpga/zsbl/Makefile +++ b/fpga/zsbl/Makefile @@ -17,6 +17,7 @@ OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS)) TARGETDIR := bin TARGET := $(TARGETDIR)/boot +MEMFILES := $(TARGETDIR/boot.mem $(TARGETDIR)/data.mem ROOT := .. LIBRARY_DIRS := LIBRARY_FILES := @@ -37,7 +38,7 @@ AR=riscv64-unknown-elf-ar #Default Make -all: directories $(TARGET).memfile +all: directories $(TARGET).memfile #Remake remake: clean all @@ -48,7 +49,7 @@ directories: @mkdir -p $(BUILDDIR) clean: - rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump + rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump boot.mem data.mem #Needed for building additional library projects @@ -112,3 +113,7 @@ $(TARGET).memfile: $(TARGET) extractFunctionRadix.sh $<.objdump mkdir -p ../../imperas-riscv-tests/work/rv64BP/ cp -f $(TARGETDIR)/* ../../imperas-riscv-tests/work/rv64BP/ + @echo 'Splitting memfile.' + ./splitfile.sh $@ + mv boot.mem ../src/boot.mem + mv data.mem ../src/data.mem diff --git a/src/generic/mem/ram1p1rwbe.sv b/src/generic/mem/ram1p1rwbe.sv index d333048b7..e2e76288b 100644 --- a/src/generic/mem/ram1p1rwbe.sv +++ b/src/generic/mem/ram1p1rwbe.sv @@ -83,11 +83,26 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE end else begin: ram bit [WIDTH-1:0] RAM[DEPTH-1:0]; - if (PRELOAD_ENABLED) begin - initial begin - RAM[0] = 64'h00600100d2e3ca40; + // if (PRELOAD_ENABLED) begin + // initial begin + // RAM[0] = 64'h00600100d2e3ca40; + // end + // end + + initial + if (PRELOAD_ENABLED) begin + if (WIDTH == 64) begin + `ifdef VERILATOR + // because Verilator doesn't automatically accept $WALLY from shell + string WALLY_DIR = getenvval("WALLY"); + $readmemh({WALLY_DIR,"/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + `else + $readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + `endif + end else begin // put something in the ROM so it is not optimized away + RAM[0] = 'h00002197; + end end - end // Combinational read: register address and read after clock edge logic [$clog2(DEPTH)-1:0] addrd; diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index c3414352f..7de407c63 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -78,13 +78,13 @@ module uncore import cvw::*; #(parameter cvw_t P)( logic SDCIntM; logic PCLK, PRESETn, PWRITE, PENABLE; - logic [4:0] PSEL; + logic [5:0] PSEL; logic [31:0] PADDR; logic [P.XLEN-1:0] PWDATA; logic [P.XLEN/8-1:0] PSTRB; /* verilator lint_off UNDRIVEN */ // undriven in rv32e configuration - logic [4:0] PREADY; - logic [4:0][P.XLEN-1:0] PRDATA; + logic [5:0] PREADY; + logic [5:0][P.XLEN-1:0] PRDATA; /* verilator lint_on UNDRIVEN */ logic [P.XLEN-1:0] HREADBRIDGE; logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED; @@ -102,7 +102,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( // AHB -> APB bridge ahbapbbridge #(P, 6) ahbapbbridge ( - .HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO, HSELSDC}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, + .HCLK, .HRESETn, .HSEL({HSELSDC, HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY, .HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE), .PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA); assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI | HSELSDC; // if any of the bridge signals are selected @@ -172,7 +172,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(SDCIntr)); end else begin : sdc - assign SDCCmd = '0; assign SDCCD = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; + assign SDCCmd = '0; assign SDCCS = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; end diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 3bf8f1a2e..c8e659670 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -76,8 +76,7 @@ module testbench; // DUT signals logic [P.AHBW-1:0] HRDATAEXT; - logic HREADYEXT, HRESPEXT; - logic HSELEXTSDC; + logic HREADYEXT, HRESPEXT; logic [P.PA_BITS-1:0] HADDR; logic [P.AHBW-1:0] HWDATA; logic [P.XLEN/8-1:0] HWSTRB; @@ -93,7 +92,11 @@ module testbench; logic UARTSin, UARTSout; logic SPIIn, SPIOut; logic [3:0] SPICS; - logic SDCIntr; + logic SPICLK; + logic SDCCmd; + logic SDCIn; + logic [3:0] SDCCS; + logic SDCCLK; logic HREADY; logic HSELEXT; @@ -371,6 +374,11 @@ module testbench; uartoutfile = $fopen(uartoutfilename, "w"); // delete UART output file ProgramAddrMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.addr"}; ProgramLabelMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.lab"}; + end else if(TEST == "fpga") begin + bootmemfilename = {WALLY_DIR, "/fpga/src/boot.mem"}; + memfilename = {WALLY_DIR, "/fpga/src/data.mem"}; + ProgramAddrMapFile = {WALLY_DIR, "/fpga/zsbl/bin/boot.objdump.addr"}; + ProgramLabelMapFile = {WALLY_DIR, "/fpga/zsbl/bin/boot.objdump.lab"}; end else if(ElfFile != "none") begin elffilename = ElfFile; memfilename = {ElfFile, ".memfile"}; @@ -505,6 +513,23 @@ module testbench; end readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.ram.RAM, memFile); $fclose(memFile); + end else if (TEST == "fpga") begin + memFile = $fopen(bootmemfilename, "rb"); + if (memFile == 0) begin + $display("Error: Could not open file %s", memfilename); + $finish; + end + if (P.BOOTROM_SUPPORTED) begin + readResult = $fread(dut.uncoregen.uncore.bootrom.bootrom.memory.ROM, memFile); + end + $fclose(memFile); + memFile = $fopen(memfilename, "rb"); + if (memFile == 0) begin + $display("Error: Could not open file %s", memfilename); + $finish; + end + readResult = $fread(dut.uncoregen.uncore.ram.ram.memory.ram.RAM, memFile); + $fclose(memFile); end else begin uncoreMemFile = $fopen(memfilename, "r"); // Is there a better way to test if a file exists? if (uncoreMemFile == 0) begin @@ -584,15 +609,15 @@ module testbench; assign SDCDat = sd_dat_reg_t ? sd_dat_reg_o : sd_dat_i; assign SDCDatIn = SDCDat; -----/\----- EXCLUDED -----/\----- */ - assign SDCIntr = 1'b0; end else begin - assign SDCIntr = 1'b0; + assign SDCIn = 1'b1; + end - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS); + .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); // generate clock to sequence tests always begin From a36e846b0251f533ba2988da6ca2d95ce17b6e17 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 25 Jul 2024 13:04:27 -0500 Subject: [PATCH 23/39] Changed formatting and added new UART divsor calculation from OpenSBI. --- fpga/zsbl/uart.c | 91 ++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index 7ff40e516..1330bc1d9 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -3,94 +3,93 @@ void write_reg_u8(uintptr_t addr, uint8_t value) { - volatile uint8_t *loc_addr = (volatile uint8_t *)addr; - *loc_addr = value; + volatile uint8_t *loc_addr = (volatile uint8_t *)addr; + *loc_addr = value; } uint8_t read_reg_u8(uintptr_t addr) { - return *(volatile uint8_t *)addr; + return *(volatile uint8_t *)addr; } int is_transmit_empty() { - return read_reg_u8(UART_LSR) & 0x20; + return read_reg_u8(UART_LSR) & 0x20; } int is_receive_empty() { - return !(read_reg_u8(UART_LSR) & 0x1); + return !(read_reg_u8(UART_LSR) & 0x1); } void write_serial(char a) { - while (is_transmit_empty() == 0) {}; + while (is_transmit_empty() == 0) {}; - write_reg_u8(UART_THR, a); + write_reg_u8(UART_THR, a); } void init_uart(uint32_t freq, uint32_t baud) { - uint32_t divisor = freq / (baud << 4); + // Alternative divisor calculation. From OpenSBI code. + // Reduces error for every possible frequency. + uint32_t divisor = (freq + 8 * baud) /(baud << 4); - write_reg_u8(UART_IER, 0x00); // Disable all interrupts - write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) - write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte) - write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) - write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit - write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + write_reg_u8(UART_IER, 0x00); // Disable all interrupts + write_reg_u8(UART_LCR, 0x80); // Enable DLAB (set baud rate divisor) + write_reg_u8(UART_DLL, divisor & 0xFF); // divisor (lo byte) + write_reg_u8(UART_DLM, (divisor >> 8) & 0xFF); // divisor (hi byte) + write_reg_u8(UART_LCR, 0x03); // 8 bits, no parity, one stop bit + write_reg_u8(UART_FCR, 0xC7); // Enable FIFO, clear them, with 14-byte threshold } void print_uart(const char *str) { - const char *cur = &str[0]; - while (*cur != '\0') - { - write_serial((uint8_t)*cur); - ++cur; - } + const char *cur = &str[0]; + while (*cur != '\0') { + write_serial((uint8_t)*cur); + ++cur; + } } uint8_t bin_to_hex_table[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; void bin_to_hex(uint8_t inp, uint8_t res[2]) { - res[1] = bin_to_hex_table[inp & 0xf]; - res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; - return; + res[1] = bin_to_hex_table[inp & 0xf]; + res[0] = bin_to_hex_table[(inp >> 4) & 0xf]; + return; } void print_uart_int(uint32_t addr) { - int i; - for (i = 3; i > -1; i--) - { - uint8_t cur = (addr >> (i * 8)) & 0xff; - uint8_t hex[2]; - bin_to_hex(cur, hex); - write_serial(hex[0]); - write_serial(hex[1]); - } + int i; + for (i = 3; i > -1; i--) { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } } void print_uart_addr(uint64_t addr) { - int i; - for (i = 7; i > -1; i--) - { - uint8_t cur = (addr >> (i * 8)) & 0xff; - uint8_t hex[2]; - bin_to_hex(cur, hex); - write_serial(hex[0]); - write_serial(hex[1]); - } + int i; + for (i = 7; i > -1; i--) { + uint8_t cur = (addr >> (i * 8)) & 0xff; + uint8_t hex[2]; + bin_to_hex(cur, hex); + write_serial(hex[0]); + write_serial(hex[1]); + } } void print_uart_byte(uint8_t byte) { - uint8_t hex[2]; - bin_to_hex(byte, hex); - write_serial(hex[0]); - write_serial(hex[1]); + uint8_t hex[2]; + bin_to_hex(byte, hex); + write_serial(hex[0]); + write_serial(hex[1]); } From 3975f60299c18bfb4f5fce2be64d552f3752c3d2 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Thu, 25 Jul 2024 13:05:57 -0500 Subject: [PATCH 24/39] Added carriage returns to line feed characters. UART messages print properly now. --- fpga/zsbl/boot.c | 5 ++++- fpga/zsbl/boot.h | 18 +++++++++--------- fpga/zsbl/gpt.c | 6 +++--- fpga/zsbl/sd.c | 4 ++-- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index e8065f732..5b022cea3 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -49,6 +49,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { if (sd_cmd(18, sector & 0xffffffff, crc) != 0x00) { print_uart("disk_read: CMD18 failed. r = "); print_uart_byte(r & 0xff); + print_uart("\r\n"); return -1; } @@ -61,6 +62,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { if (r != SD_DATA_TOKEN) { print_uart("Didn't receive data token first thing. Shoot: "); print_uart_byte(r & 0xff); + print_uart("\r\n"); return -1; } @@ -97,7 +99,8 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Initialize UART for messages init_uart(20000000, 115200); - + + print_uart("Booting wally.\r\n"); // Print the wally banner print_uart(BANNER); diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 2048ca47c..087550326 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -19,15 +19,15 @@ typedef QWORD LBA_t; #define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START #define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR -#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\n" \ -" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\n" \ -" █▄█ █▄█ █ █ █▄▄ ▀▄▀\n" \ -" ____ ____ ____ ___ ___ ____ ___\n" \ -" \\ \\ / / / \\ | | | | \\ \\ / /\n" \ -" \\ \\ __ / / / \\ | | | | \\ \\/ /\n" \ -" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\n" \ -" \\ / / ____ \\ | |___ | |___ | |\n" \ -" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\n\n" +#define BANNER " █▀█ █▀█ █▀█ █▀▀ █ █\r\n" \ +" █ █ █ █▄▀ █▄▄ ▄▄▄ █ █\r\n" \ +" █▄█ █▄█ █ █ █▄▄ ▀▄▀\r\n" \ +" ____ ____ ____ ___ ___ ____ ___\r\n" \ +" \\ \\ / / / \\ | | | | \\ \\ / /\r\n" \ +" \\ \\ __ / / / \\ | | | | \\ \\/ /\r\n" \ +" \\ \\/ \\/ / / /\\ \\ | | | | \\ /\r\n" \ +" \\ / / ____ \\ | |___ | |___ | |\r\n" \ +" \\___/\\___/ /___/ \\___\\|_______||_______| |___|\r\n\r\n" // Export disk_read int disk_read(BYTE * buf, LBA_t sector, UINT count); diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index c308ea878..a52dc9048 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -42,21 +42,21 @@ int gpt_load_partitions() { // Load device tree ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); if (ret < 0) { - print_uart("Failed to load device tree!"); + print_uart("Failed to load device tree!\r\n"); return -1; } // Load OpenSBI ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); if (ret < 0) { - print_uart("Failed to load OpenSBI!"); + print_uart("Failed to load OpenSBI!\r\n"); return -1; } // Load Linux ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); if (ret < 0) { - print_uart("Failed to load Linux!"); + print_uart("Failed to load Linux!\r\n"); return -1; } diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 585b98281..02ee4d3bf 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -133,7 +133,7 @@ void init_sd(){ uint64_t r; - print_uart("Initializing SD Card in SPI mode"); + print_uart("Initializing SD Card in SPI mode.\r\n"); // Reset SD Card command // Initializes SD card into SPI mode if CS is asserted '0' @@ -155,6 +155,6 @@ void init_sd(){ r = ACMD41(); } while (r == 0x1); - print_uart("SD card is initialized"); + print_uart("SD card is initialized.\n\r"); } From a263f836f2d322c0f4a5db4e1303e282e741c31b Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 31 Jul 2024 10:58:15 -0500 Subject: [PATCH 25/39] Added extra UART macros and functions for code readability and the ability to print decimal numbers. --- fpga/zsbl/uart.c | 68 +++++++++++++++++++++++++++++++++++------------- fpga/zsbl/uart.h | 20 +++++++++++++- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index 1330bc1d9..d7ac9b558 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -62,10 +62,10 @@ void bin_to_hex(uint8_t inp, uint8_t res[2]) return; } -void print_uart_int(uint32_t addr) +void print_uart_hex(uint64_t addr, int n) { int i; - for (i = 3; i > -1; i--) { + for (i = n - 1; i > -1; i--) { uint8_t cur = (addr >> (i * 8)) & 0xff; uint8_t hex[2]; bin_to_hex(cur, hex); @@ -74,22 +74,54 @@ void print_uart_int(uint32_t addr) } } -void print_uart_addr(uint64_t addr) -{ - int i; - for (i = 7; i > -1; i--) { - uint8_t cur = (addr >> (i * 8)) & 0xff; - uint8_t hex[2]; - bin_to_hex(cur, hex); - write_serial(hex[0]); - write_serial(hex[1]); +void print_uart_dec(uint64_t addr) { + + // floor(log(2^64)) = 19 + char str[19] = {'\0'}; + uint8_t length = 0; + + uint64_t cur = addr; + while (cur != 0) { + char digit = bin_to_hex_table[cur % 10]; + // write_serial(digit); + str[length] = digit; + cur = cur/10; + length++; + } + + for (int i = length; i > -1; i--) { + write_serial(str[i]); } } -void print_uart_byte(uint8_t byte) -{ - uint8_t hex[2]; - bin_to_hex(byte, hex); - write_serial(hex[0]); - write_serial(hex[1]); -} +/* void print_uart_int(uint32_t addr) */ +/* { */ +/* int i; */ +/* for (i = 3; i > -1; i--) { */ +/* uint8_t cur = (addr >> (i * 8)) & 0xff; */ +/* uint8_t hex[2]; */ +/* bin_to_hex(cur, hex); */ +/* write_serial(hex[0]); */ +/* write_serial(hex[1]); */ +/* } */ +/* } */ + +/* void print_uart_addr(uint64_t addr) */ +/* { */ +/* int i; */ +/* for (i = 7; i > -1; i--) { */ +/* uint8_t cur = (addr >> (i * 8)) & 0xff; */ +/* uint8_t hex[2]; */ +/* bin_to_hex(cur, hex); */ +/* write_serial(hex[0]); */ +/* write_serial(hex[1]); */ +/* } */ +/* } */ + +/* void print_uart_byte(uint8_t byte) */ +/* { */ +/* uint8_t hex[2]; */ +/* bin_to_hex(byte, hex); */ +/* write_serial(hex[0]); */ +/* write_serial(hex[1]); */ +/* } */ diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index 18710e76b..ee399885f 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -16,11 +16,29 @@ #define UART_DLL UART_BASE + 0x00 #define UART_DLM UART_BASE + 0x01 -void init_uart(); +void init_uart(uint32_t freq, uint32_t baud); void write_reg_u8(uintptr_t addr, uint8_t value); uint8_t read_reg_u8(uintptr_t addr); int read_serial(uint8_t *res); void print_uart(const char* str); void print_uart_int(uint32_t addr); +void print_uart_dec(uint64_t addr); void print_uart_addr(uint64_t addr); +void print_uart_hex(uint64_t addr, int n); void print_uart_byte(uint8_t byte); + +#define print_uart_int(addr) print_uart_hex(addr, 4) +#define print_uart_addr(addr) print_uart_hex(addr, 8) +#define print_uart_byte(addr) print_uart_hex(addr, 1) +#define print_r7(addr) print_uart_hex(addr, 5) +#define print_r1(addr) print_uart_byte(addr) + +// Print line with numbers utility macros +#define println(msg) print_uart(msg "\r\n"); +#define println_with_dec(msg, num) print_uart(msg); print_uart_dec(num); print_uart("\r\n") +#define println_with_byte(msg, num) print_uart(msg); print_uart_byte(num); print_uart("\r\n") +#define println_with_int(msg, num) print_uart(msg); print_uart_int(num); print_uart("\r\n") +#define println_with_addr(msg, num) print_uart(msg); print_uart_addr(num); print_uart("\r\n") +#define println_with_r1(msg, num) print_uart(msg); print_r1(num); print_uart("\r\n") +#define println_with_r7(msg, num) print_uart(msg); print_r7(num); print_uart("\r\n") + From c4ae17c6797ecdb734be059df83634e70922d2ad Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 31 Jul 2024 10:59:41 -0500 Subject: [PATCH 26/39] Cleaned up code formatting a bit and added ability to set the SD card clock speed. --- fpga/zsbl/sd.c | 65 ++++++++++++++++++++++++++++++++++++++------------ fpga/zsbl/sd.h | 4 ++-- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 02ee4d3bf..cacf40438 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -62,8 +62,14 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // response length. Probably unecessary so let's wait and see what // happens. // write_reg(SPI_RXMARK, response_len); + + // Chip select must remain asserted during transaction + if (cmd != SD_CMD_STOP_TRANSMISSION) { + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); + } - // Write all 6 bytes into transfer fifo + // Write all 7 bytes into transfer fifo + // spi_sendbyte(0xff); spi_sendbyte(0x40 | cmd); spi_sendbyte(arg >> 24); spi_sendbyte(arg >> 16); @@ -77,7 +83,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { waittx(); // Read the dummy rxFIFO entries to move the head back to the tail - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { spi_readbyte(); } @@ -90,12 +96,24 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // Wait for transfer fifo again waittx(); + // Wait for actual response from SD card + // All responses start with a 0. Output of SDCIn is high, unless + // a message is being transferred. + do { + rbyte = spi_txrx(0xff); + } while ( (rbyte & 0x80) != 0 ); + + r = r | (rbyte << ((response_len - 1)*8)); + // Read rxfifo response - for (i = 0; i < response_len; i++) { + for (i = 1; i < response_len; i++) { rbyte = spi_readbyte(); r = r | (rbyte << ((response_len - 1 - i)*8)); } + if (cmd != 18) { + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + } return r; } // sd_cmd @@ -128,33 +146,50 @@ uint64_t sd_read64(uint16_t * crc) { // init_sd: ---------------------------------------------------------- // This first initializes the SPI peripheral then initializes the SD // card itself. We use the uart to display anything that goes wrong. -void init_sd(){ +int init_sd(uint32_t freq, uint32_t sdclk){ spi_init(); uint64_t r; + uint32_t newClockDiv; - print_uart("Initializing SD Card in SPI mode.\r\n"); + println("Initializing SD Card in SPI mode."); + // This is necessary. This is the card's pre-init state initialization. + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_OFF); + for (int i = 0; i < 10; i++) { + spi_txrx(0xff); + } + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + // CMD0 -------------------------------------------------------------- // Reset SD Card command // Initializes SD card into SPI mode if CS is asserted '0' - if (!(( r = CMD0() ) & 0x10) ) { - print_uart("SD ERROR: "); - print_uart_byte(r & 0xff); - print_uart("\r\n"); - } + // We expect to get the R1 response 0x01 which means that the + // card has been put into the idle state. + print_uart("CMD0: "); + do { + r = CMD0(); + } while ( r != 0x01 ); + println_with_r1("Success, r = 0x", r & 0xff); + // CMD8 ------------------------------------------------------------- // - if (!(( r = CMD8() ) & 0x10 )) { - print_uart("SD ERROR: "); - print_uart_byte(r & 0xff); - print_uart("\r\n"); + print_uart("CMD8: "); + r = CMD8(); + if ((r & 0x000000ff0000ffff) != 0x01000001aa) { + println_with_r7("Failed, 0x", r); } + println_with_r7("Success, 0x", r); + // ACMD41 ----------------------------------------------------------- + print_uart("ACMD41: "); do { CMD55(); r = ACMD41(); } while (r == 0x1); + println_with_r1("Success, r = 0x", r & 0xff); - print_uart("SD card is initialized.\n\r"); + println_with_dec("New clock frequency: ", (uint64_t)sdclk); + spi_set_clock(freq, sdclk); + println("SD card is initialized."); } diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index 37e4a2c94..f695b83e5 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -9,11 +9,11 @@ // Response lengths in bytes #define R1_RESPONSE 1 -#define R7_RESPONSE 7 +#define R7_RESPONSE 5 #define R1B_RESPONSE 2 uint8_t crc7(uint8_t prev, uint8_t in); uint16_t crc16(uint16_t crc, uint8_t data); uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc); uint64_t sd_read64(uint16_t * crc); -void init_sd(); +int init_sd(uint32_t freq, uint32_t sdclk); From ee980e39f306cebc9eb2ce7af2c3a0acd8352d91 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 31 Jul 2024 11:00:44 -0500 Subject: [PATCH 27/39] Added function to set SPI clock speed. --- fpga/zsbl/spi.c | 7 ++++++- fpga/zsbl/spi.h | 5 +---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index cbb9fa2eb..b8829b12e 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -83,8 +83,13 @@ uint64_t spi_read64() { return r; } +void spi_set_clock(uint32_t clkin, uint32_t clkout) { + uint32_t div = (clkin/(2*clkout)) - 1; + write_reg(SPI_SCKDIV, div); +} + // Initialize Sifive FU540 based SPI Controller -void spi_init() { +void spi_init(uint32_t clkin) { // Enable interrupts write_reg(SPI_IE, 0x3); diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index bc85c768f..a662fce86 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -44,10 +44,6 @@ #define SIFIVE_SPI_CSMODE_MODE_HOLD 2U #define SIFIVE_SPI_CSMODE_MODE_OFF 3U - -#define WAITTX while(!(read_reg(SPI_IP) & 1) {} -#define WAITRX while(read_reg(SPI_IP) & 2) {} - // inline void write_reg(uintptr_t addr, uint32_t value); //inline uint32_t read_reg(uintptr_t addr); //inline void spi_sendbyte(uint8_t byte); @@ -57,6 +53,7 @@ uint8_t spi_txrx(uint8_t byte); //inline uint8_t spi_readbyte(); uint64_t spi_read64(); void spi_init(); +void spi_set_clock(uint32_t clkin, uint32_t clkout); static inline void write_reg(uintptr_t addr, uint32_t value) { volatile uint32_t * loc = (volatile uint32_t *) addr; From 38071d826736f527820b94d8492492898171bf3e Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Wed, 31 Jul 2024 11:12:05 -0500 Subject: [PATCH 28/39] Updated formatting of gpt.c and boot.c. --- fpga/zsbl/boot.c | 40 ++++++++++++++++++++++++++-------------- fpga/zsbl/gpt.c | 21 +++++---------------- fpga/zsbl/uart.h | 3 +++ 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 5b022cea3..7b2e9af7d 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -34,10 +34,12 @@ /* return 0;; */ /* } */ +#define SYSTEMCLOCK 20000000 + int disk_read(BYTE * buf, LBA_t sector, UINT count) { uint64_t r; UINT i; - + uint8_t crc = 0; crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE); crc = crc7(crc, (sector >> 24) & 0xff); @@ -46,25 +48,29 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { crc = crc7(crc, sector & 0xff); crc = crc | 1; - if (sd_cmd(18, sector & 0xffffffff, crc) != 0x00) { - print_uart("disk_read: CMD18 failed. r = "); - print_uart_byte(r & 0xff); + if ((r = sd_cmd(18, sector & 0xffffffff, crc) & 0xff) != 0x00) { + print_uart("disk_read: CMD18 failed. r = 0x"); + print_uart_byte(r); print_uart("\r\n"); return -1; } + // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); // Begin reading blocks for (i = 0; i < count; i++) { uint16_t crc, crc_exp; // Read the data token r = spi_readbyte(); - if (r != SD_DATA_TOKEN) { - print_uart("Didn't receive data token first thing. Shoot: "); - print_uart_byte(r & 0xff); - print_uart("\r\n"); - return -1; - } + /* if (r != SD_DATA_TOKEN) { */ + /* print_uart("Didn't receive data token first thing. Shoot: "); */ + /* print_uart_byte(r & 0xff); */ + /* print_uart("\r\n"); */ + /* return -1; */ + /* } */ + + // Wait for data token + while((r & 0xff) != SD_DATA_TOKEN); // Read block into memory. for (int j = 0; j < 8; j++) { @@ -77,7 +83,7 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { crc_exp |= spi_txrx(0xff); if (crc != crc_exp) { - print_uart("Stinking CRC16 didn't match on block "); + print_uart("Stinking CRC16 didn't match on block read.\r\n"); print_uart_int(i); print_uart("\r\n"); return -1; @@ -86,7 +92,8 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { } sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01); - spi_txrx(0xff); + // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + //spi_txrx(0xff); return 0; } @@ -100,12 +107,17 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Initialize UART for messages init_uart(20000000, 115200); - print_uart("Booting wally.\r\n"); // Print the wally banner print_uart(BANNER); + /* print_uart("System clock speed: "); */ + /* print_uart_dec(SYSTEMCLOCK); */ + /* print_uart("\r\n"); */ + + println_with_dec("Hello, does this work? Here's the clock: ", SYSTEMCLOCK); + // Intialize the SD card - init_sd(); + init_sd(SYSTEMCLOCK, SYSTEMCLOCK/2); ret = gpt_load_partitions(); } diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index a52dc9048..9af396469 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -3,18 +3,7 @@ #include "uart.h" #include -/* PSUEDOCODE - - Need to load GPT LBA 1 and read through the partition entries. - I need to find each of the relevant partition entries, possibly - by their partition names. - -*/ - int gpt_load_partitions() { - // In this version of the GPT partition code - // I'm going to assume that the SD card is already initialized. - // size_t block_size = 512/8; // long int lba1_buf[block_size]; @@ -22,15 +11,12 @@ int gpt_load_partitions() { int ret = 0; //ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */); + println("Getting GPT information."); ret = disk_read(lba1_buf, 1, 1); - /* Possible error handling with UART message - if ( ret != 0 ) { - - }*/ - gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf; + println("Getting partition entries."); BYTE lba2_buf[512]; ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1); @@ -40,6 +26,7 @@ int gpt_load_partitions() { partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); // Load device tree + println_with_int("Loading device tree at: 0x", FDT_ADDRESS); ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); if (ret < 0) { print_uart("Failed to load device tree!\r\n"); @@ -47,6 +34,7 @@ int gpt_load_partitions() { } // Load OpenSBI + println_with_int("Loading OpenSBI at: 0x", OPENSBI_ADDRESS); ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); if (ret < 0) { print_uart("Failed to load OpenSBI!\r\n"); @@ -54,6 +42,7 @@ int gpt_load_partitions() { } // Load Linux + println_with_int("Loading Linux Kernel at: 0x", KERNEL_ADDRESS); ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); if (ret < 0) { print_uart("Failed to load Linux!\r\n"); diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index ee399885f..515a9dccd 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -1,6 +1,7 @@ #pragma once #include +// UART register addresses #define UART_BASE 0x10000000 #define UART_RBR UART_BASE + 0x00 @@ -16,6 +17,7 @@ #define UART_DLL UART_BASE + 0x00 #define UART_DLM UART_BASE + 0x01 +// Primary function prototypes void init_uart(uint32_t freq, uint32_t baud); void write_reg_u8(uintptr_t addr, uint8_t value); uint8_t read_reg_u8(uintptr_t addr); @@ -27,6 +29,7 @@ void print_uart_addr(uint64_t addr); void print_uart_hex(uint64_t addr, int n); void print_uart_byte(uint8_t byte); +// Print numbers in hex with specified widths #define print_uart_int(addr) print_uart_hex(addr, 4) #define print_uart_addr(addr) print_uart_hex(addr, 8) #define print_uart_byte(addr) print_uart_hex(addr, 1) From fcd88d6e6f4c0a1adc334f2d84eb2a8c82e93ee7 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 2 Aug 2024 15:14:30 -0500 Subject: [PATCH 29/39] Added functions to read registers and print information on failure. Also added a getTime function for a pretty boot display. --- fpga/zsbl/fail.c | 19 +++++++++++++++++++ fpga/zsbl/fail.h | 4 ++++ fpga/zsbl/riscv.S | 29 +++++++++++++++++++++++++++++ fpga/zsbl/riscv.h | 7 +++++++ fpga/zsbl/time.c | 20 ++++++++++++++++++++ fpga/zsbl/time.h | 5 +++++ 6 files changed, 84 insertions(+) create mode 100644 fpga/zsbl/fail.c create mode 100644 fpga/zsbl/fail.h create mode 100644 fpga/zsbl/riscv.S create mode 100644 fpga/zsbl/riscv.h create mode 100644 fpga/zsbl/time.c create mode 100644 fpga/zsbl/time.h diff --git a/fpga/zsbl/fail.c b/fpga/zsbl/fail.c new file mode 100644 index 000000000..4e6cd8db0 --- /dev/null +++ b/fpga/zsbl/fail.c @@ -0,0 +1,19 @@ +#include "fail.h" +#include "uart.h" +#include "riscv.h" +#include "time.h" + +void fail() { + // Get address that led to failure + register uint64_t addr; + asm volatile ("mv %0, ra" : "=r"(addr) : : "memory"); + + // Print message + print_time(); + println_with_addr("Failed at: 0x", addr); + + // Loop forever + while(1) { + + } +} diff --git a/fpga/zsbl/fail.h b/fpga/zsbl/fail.h new file mode 100644 index 000000000..da1a2e405 --- /dev/null +++ b/fpga/zsbl/fail.h @@ -0,0 +1,4 @@ +#pragma once +#include + +void fail(); diff --git a/fpga/zsbl/riscv.S b/fpga/zsbl/riscv.S new file mode 100644 index 000000000..7f400b1b2 --- /dev/null +++ b/fpga/zsbl/riscv.S @@ -0,0 +1,29 @@ +.section .text +.globl read_mcycle +.type read_mcycle, @function +read_mcycle: + csrr a0, mcycle + ret + +.section .text +.globl get_ra +.type get_ra, @function +get_ra: + mv a0, ra + ret + +.section .text +.globl set_status_fs +.type set_status_fs, @function +set_status_fs: + lui t1, 0x6 + csrs mstatus, t1 + ret + +.section .text +.globl clear_status_fs +.type clear_status_fs, @function +clear_status_fs: + lui t1, 0x6 + csrc mstatus, t1 + ret diff --git a/fpga/zsbl/riscv.h b/fpga/zsbl/riscv.h new file mode 100644 index 000000000..a27cd48d6 --- /dev/null +++ b/fpga/zsbl/riscv.h @@ -0,0 +1,7 @@ +#pragma once +#include + +uint64_t read_mcycle(); +uint64_t get_ra(); +void set_status_fs(); +void clear_status_fs(); diff --git a/fpga/zsbl/time.c b/fpga/zsbl/time.c new file mode 100644 index 000000000..43ac085b7 --- /dev/null +++ b/fpga/zsbl/time.c @@ -0,0 +1,20 @@ +#include "time.h" +#include "boot.h" +#include "riscv.h" +#include "uart.h" + +float getTime() { + set_status_fs(); + float numCycles = (float)read_mcycle(); + float ret = numCycles/SYSTEMCLOCK; + // clear_status_fs(); + return ret; +} + +void print_time() { + print_uart("["); + set_status_fs(); + print_uart_float(getTime(),5); + clear_status_fs(); + print_uart("] "); +} diff --git a/fpga/zsbl/time.h b/fpga/zsbl/time.h new file mode 100644 index 000000000..6cd928b88 --- /dev/null +++ b/fpga/zsbl/time.h @@ -0,0 +1,5 @@ +#pragma once +#include + +float getTime(); +void print_time(); From 897f6561cd53fa3875ddd4a14bc4697369f562c7 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 2 Aug 2024 15:19:52 -0500 Subject: [PATCH 30/39] New bootloader now works. Added special print functions and print messages. sdclk is set to 3MHz after initialization currently. --- fpga/zsbl/boot.c | 92 +++++++++++++++++++++++++++++++++++------------- fpga/zsbl/boot.h | 2 ++ fpga/zsbl/gpt.c | 8 +++++ fpga/zsbl/sd.c | 63 ++++++++++++++++++++++++--------- fpga/zsbl/spi.c | 6 +++- fpga/zsbl/spi.h | 1 + fpga/zsbl/uart.c | 40 +++++++++++++++++++-- fpga/zsbl/uart.h | 11 ++++++ 8 files changed, 179 insertions(+), 44 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 7b2e9af7d..e47b34e2f 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -4,6 +4,9 @@ #include "uart.h" #include "spi.h" #include "sd.h" +#include "time.h" +#include "riscv.h" +#include "fail.h" /* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ @@ -34,11 +37,31 @@ /* return 0;; */ /* } */ -#define SYSTEMCLOCK 20000000 +// Need to convert this +/* void print_progress(size_t count, size_t max) { */ +/* const int bar_width = 50; */ + +/* float progress = (float) count / max; */ +/* int bar_length = progress * bar_width; */ + +/* printf("\r["); */ +/* for (int i = 0; i < bar_length; ++i) { */ +/* printf("#"); */ +/* } */ +/* for (int i = bar_length; i < bar_width; ++i) { */ +/* printf("-"); */ +/* } */ +/* printf("] %.2f%%", progress * 100); */ + +/* fflush(stdout); */ +/* } */ int disk_read(BYTE * buf, LBA_t sector, UINT count) { uint64_t r; UINT i; + volatile uint8_t *p = buf; + + UINT modulus = count/50; uint8_t crc = 0; crc = crc7(crc, 0x40 | SD_CMD_READ_BLOCK_MULTIPLE); @@ -52,48 +75,69 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) { print_uart("disk_read: CMD18 failed. r = 0x"); print_uart_byte(r); print_uart("\r\n"); - return -1; + fail(); + // return -1; } + print_uart("\r Blocks loaded: "); + print_uart("0"); + print_uart("/"); + print_uart_dec(count); // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); // Begin reading blocks for (i = 0; i < count; i++) { uint16_t crc, crc_exp; - - // Read the data token - r = spi_readbyte(); - /* if (r != SD_DATA_TOKEN) { */ - /* print_uart("Didn't receive data token first thing. Shoot: "); */ - /* print_uart_byte(r & 0xff); */ - /* print_uart("\r\n"); */ - /* return -1; */ - /* } */ + uint64_t n = 0; // Wait for data token - while((r & 0xff) != SD_DATA_TOKEN); + while((r = spi_dummy()) != SD_DATA_TOKEN); + // println_with_byte("Received data token: 0x", r & 0xff); + // println_with_dec("Block ", i); // Read block into memory. - for (int j = 0; j < 8; j++) { - *buf = sd_read64(&crc); - buf = buf + 64; - } - + /* for (int j = 0; j < 64; j++) { */ + /* *buf = sd_read64(&crc); */ + /* println_with_addr("0x", *buf); */ + /* buf = buf + 64; */ + /* } */ + crc = 0; + n = 512; + do { + uint8_t x = spi_dummy(); + *p++ = x; + crc = crc16(crc, x); + } while (--n > 0); + // Read CRC16 and check - crc_exp = ((uint16_t)spi_txrx(0xff) << 8); - crc_exp |= spi_txrx(0xff); + crc_exp = ((uint16_t)spi_dummy() << 8); + crc_exp |= spi_dummy(); if (crc != crc_exp) { print_uart("Stinking CRC16 didn't match on block read.\r\n"); print_uart_int(i); print_uart("\r\n"); - return -1; + //return -1; + fail(); } - + + if ( (i % modulus) == 0 ) { + print_uart("\r Blocks loaded: "); + print_uart_dec(i); + print_uart("/"); + print_uart_dec(count); + } + } sd_cmd(SD_CMD_STOP_TRANSMISSION, 0, 0x01); + + print_uart("\r Blocks loaded: "); + print_uart_dec(count); + print_uart("/"); + print_uart_dec(count); // write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); //spi_txrx(0xff); + print_uart("\r\n"); return 0; } @@ -106,7 +150,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { // Initialize UART for messages init_uart(20000000, 115200); - + // Print the wally banner print_uart(BANNER); @@ -114,10 +158,8 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { /* print_uart_dec(SYSTEMCLOCK); */ /* print_uart("\r\n"); */ - println_with_dec("Hello, does this work? Here's the clock: ", SYSTEMCLOCK); - // Intialize the SD card - init_sd(SYSTEMCLOCK, SYSTEMCLOCK/2); + init_sd(SYSTEMCLOCK, 3000000); ret = gpt_load_partitions(); } diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 087550326..25b8a5fcc 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -32,5 +32,7 @@ typedef QWORD LBA_t; // Export disk_read int disk_read(BYTE * buf, LBA_t sector, UINT count); +#define SYSTEMCLOCK 20000000 + #endif // WALLYBOOT diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 9af396469..99f74ec3a 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -11,11 +11,13 @@ int gpt_load_partitions() { int ret = 0; //ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */); + print_time(); println("Getting GPT information."); ret = disk_read(lba1_buf, 1, 1); gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf; + print_time(); println("Getting partition entries."); BYTE lba2_buf[512]; ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1); @@ -26,6 +28,7 @@ int gpt_load_partitions() { partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256); // Load device tree + print_time(); println_with_int("Loading device tree at: 0x", FDT_ADDRESS); ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1); if (ret < 0) { @@ -34,6 +37,7 @@ int gpt_load_partitions() { } // Load OpenSBI + print_time(); println_with_int("Loading OpenSBI at: 0x", OPENSBI_ADDRESS); ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1); if (ret < 0) { @@ -42,6 +46,7 @@ int gpt_load_partitions() { } // Load Linux + print_time(); println_with_int("Loading Linux Kernel at: 0x", KERNEL_ADDRESS); ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1); if (ret < 0) { @@ -49,5 +54,8 @@ int gpt_load_partitions() { return -1; } + print_time(); + println("Done! Flashing LEDs and jumping to OpenSBI..."); + return 0; } diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index cacf40438..484fd65c0 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,6 +1,8 @@ #include "sd.h" #include "spi.h" #include "uart.h" +#include "fail.h" +#include "time.h" // Parallel byte update CRC7-CCITT algorithm. // The result is the CRC7 result, left shifted over by 1 @@ -36,9 +38,11 @@ uint16_t crc16(uint16_t crc, uint8_t data) { // watermark and interrupt features to determine when a // transfer is complete. This should save on cycles since // no arbitrary delays need to be added. + uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t response_len; uint8_t i; + uint8_t shiftAmnt; uint64_t r; uint8_t rbyte; @@ -53,6 +57,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { break; case 12: response_len = R1B_RESPONSE; + break; default: response_len = R1_RESPONSE; break; @@ -70,6 +75,7 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // Write all 7 bytes into transfer fifo // spi_sendbyte(0xff); + spi_dummy(); spi_sendbyte(0x40 | cmd); spi_sendbyte(arg >> 24); spi_sendbyte(arg >> 16); @@ -89,30 +95,34 @@ uint64_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) { // Send "dummy signals". Since SPI is duplex, // useless bytes must be transferred - for (i = 0; i < response_len; i++) { - spi_sendbyte(0xFF); - } + /* for (i = 0; i < response_len; i++) { */ + /* spi_sendbyte(0xFF); */ + /* } */ - // Wait for transfer fifo again - waittx(); + /* // Wait for transfer fifo again */ + /* waittx(); */ // Wait for actual response from SD card // All responses start with a 0. Output of SDCIn is high, unless // a message is being transferred. do { - rbyte = spi_txrx(0xff); + rbyte = spi_dummy(); } while ( (rbyte & 0x80) != 0 ); - r = r | (rbyte << ((response_len - 1)*8)); + // Note about the compiler. In order to compile as sll instead of + // sllw, the number to shift has to be a 64 bit number. + r = ((uint64_t)rbyte) << ((response_len - 1)*8); // Read rxfifo response for (i = 1; i < response_len; i++) { - rbyte = spi_readbyte(); - r = r | (rbyte << ((response_len - 1 - i)*8)); + rbyte = spi_dummy(); + r = r | (((uint64_t)rbyte) << ((response_len - 1 - i)*8)); } if (cmd != 18) { write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); + } else { + spi_dummy(); } return r; } // sd_cmd @@ -122,16 +132,16 @@ uint64_t sd_read64(uint16_t * crc) { uint8_t rbyte; int i; - for (i = 0; i < 8; i++) { - spi_sendbyte(0xFF); - } + /* for (i = 0; i < 8; i++) { */ + /* spi_sendbyte(0xFF); */ + /* } */ - waittx(); + /* waittx(); */ for (i = 0; i < 8; i++) { - rbyte = spi_readbyte(); + rbyte = spi_dummy(); *crc = crc16(*crc, rbyte); - r = r | (rbyte << ((8 - 1 - i)*8)); + r = r | ((uint64_t)(rbyte) << ((8 - 1 - i)*8)); } return r; @@ -147,11 +157,15 @@ uint64_t sd_read64(uint16_t * crc) { // This first initializes the SPI peripheral then initializes the SD // card itself. We use the uart to display anything that goes wrong. int init_sd(uint32_t freq, uint32_t sdclk){ + print_time(); + println("Initializing SPI Controller."); spi_init(); uint64_t r; uint32_t newClockDiv; + int n; + print_time(); println("Initializing SD Card in SPI mode."); // This is necessary. This is the card's pre-init state initialization. write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_OFF); @@ -165,31 +179,48 @@ int init_sd(uint32_t freq, uint32_t sdclk){ // Initializes SD card into SPI mode if CS is asserted '0' // We expect to get the R1 response 0x01 which means that the // card has been put into the idle state. + print_time(); print_uart("CMD0: "); + n = 0; do { r = CMD0(); + n++; + if (n == 1000) { + fail(); + } } while ( r != 0x01 ); println_with_r1("Success, r = 0x", r & 0xff); // CMD8 ------------------------------------------------------------- - // + // + print_time(); print_uart("CMD8: "); r = CMD8(); if ((r & 0x000000ff0000ffff) != 0x01000001aa) { println_with_r7("Failed, 0x", r); + fail(); } println_with_r7("Success, 0x", r); // ACMD41 ----------------------------------------------------------- + print_time(); print_uart("ACMD41: "); + n = 0; do { CMD55(); r = ACMD41(); + n++; + if (n == 1000) { + fail(); + } } while (r == 0x1); println_with_r1("Success, r = 0x", r & 0xff); + print_time(); println_with_dec("New clock frequency: ", (uint64_t)sdclk); spi_set_clock(freq, sdclk); + + print_time(); println("SD card is initialized."); } diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index b8829b12e..5b23c85b6 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -55,11 +55,15 @@ /* } */ uint8_t spi_txrx(uint8_t byte) { - spi_sendbyte(0xFF); + spi_sendbyte(byte); waittx(); return spi_readbyte(); } +uint8_t spi_dummy() { + return spi_txrx(0xff); +} + /* inline uint8_t spi_readbyte() { */ /* return read_reg(SPI_RXDATA); */ /* } */ diff --git a/fpga/zsbl/spi.h b/fpga/zsbl/spi.h index a662fce86..d2bf1191c 100644 --- a/fpga/zsbl/spi.h +++ b/fpga/zsbl/spi.h @@ -50,6 +50,7 @@ //inline void waittx(); //inline void waitrx(); uint8_t spi_txrx(uint8_t byte); +uint8_t spi_dummy(); //inline uint8_t spi_readbyte(); uint64_t spi_read64(); void spi_init(); diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index d7ac9b558..8c25f17ca 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -1,6 +1,5 @@ #include "uart.h" - void write_reg_u8(uintptr_t addr, uint8_t value) { volatile uint8_t *loc_addr = (volatile uint8_t *)addr; @@ -78,7 +77,7 @@ void print_uart_dec(uint64_t addr) { // floor(log(2^64)) = 19 char str[19] = {'\0'}; - uint8_t length = 0; + uint8_t length = 1; uint64_t cur = addr; while (cur != 0) { @@ -94,6 +93,43 @@ void print_uart_dec(uint64_t addr) { } } +// Print a floating point number on the UART +void print_uart_float(float num, int precision) { + char str[32] = {'\0'}; + char digit; + uint8_t length = precision + 1; + int i; + uint64_t cur; + + str[precision] = '.'; + + int pow = 1; + + // Calculate power for precision + for (i = 0; i < precision; i++) { + pow = pow * 10; + } + + cur = (uint64_t)(num * pow); + for (i = 0; i < precision; i++) { + digit = bin_to_hex_table[cur % 10]; + str[i] = digit; + cur = cur / 10; + } + + cur = (uint64_t)num; + do { + digit = bin_to_hex_table[cur % 10]; + str[length] = digit; + cur = cur/10; + length++; + } while (cur != 0); + + for (i = length; i > -1; i--) { + write_serial(str[i]); + } +} + /* void print_uart_int(uint32_t addr) */ /* { */ /* int i; */ diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index 515a9dccd..cbdcc5941 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -1,5 +1,7 @@ #pragma once #include +#include "riscv.h" +#include "time.h" // UART register addresses #define UART_BASE 0x10000000 @@ -28,6 +30,8 @@ void print_uart_dec(uint64_t addr); void print_uart_addr(uint64_t addr); void print_uart_hex(uint64_t addr, int n); void print_uart_byte(uint8_t byte); +void print_uart_float(float num, int precision); +// void print_time(); // Print numbers in hex with specified widths #define print_uart_int(addr) print_uart_hex(addr, 4) @@ -44,4 +48,11 @@ void print_uart_byte(uint8_t byte); #define println_with_addr(msg, num) print_uart(msg); print_uart_addr(num); print_uart("\r\n") #define println_with_r1(msg, num) print_uart(msg); print_r1(num); print_uart("\r\n") #define println_with_r7(msg, num) print_uart(msg); print_r7(num); print_uart("\r\n") +#define println_with_float(msg, num) print_uart(msg); set_status_fs(); print_uart_float(num,5); clear_status_fs(); print_uart("\r\n") + +/* #define print_time() print_uart("["); \ */ +/* set_status_fs(); \ */ +/* print_uart_float(getTime(),5); \ */ +/* clear_status_fs(); \ */ +/* print_uart("] ") */ From 1e20d5aea66ff581f0e1b111aa03982a5daa5d95 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 2 Aug 2024 15:21:15 -0500 Subject: [PATCH 31/39] Added preload pointing to data.mem in ram1p1rwbe.sv --- src/generic/mem/ram1p1rwbe.sv | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/generic/mem/ram1p1rwbe.sv b/src/generic/mem/ram1p1rwbe.sv index e2e76288b..287607c9e 100644 --- a/src/generic/mem/ram1p1rwbe.sv +++ b/src/generic/mem/ram1p1rwbe.sv @@ -89,6 +89,10 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE // end // end + `ifdef VERILATOR + import "DPI-C" function string getenvval(input string env_name); + `endif + initial if (PRELOAD_ENABLED) begin if (WIDTH == 64) begin From 11a057b0b35c849c7d184f957c228be957fcbb61 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 2 Aug 2024 15:33:57 -0500 Subject: [PATCH 32/39] Updated wally source files for zsbl testing. --- config/derivlist.txt | 3 ++- fpga/constraints/constraints-ArtyA7.xdc | 17 +++++++++++------ src/uncore/spi_apb.sv | 18 +++++++++++------- src/uncore/uncore.sv | 2 +- src/wally/wallypipelinedsoc.sv | 2 +- testbench/wallywrapper.sv | 16 ++++++++++------ 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/config/derivlist.txt b/config/derivlist.txt index 1edd20b7b..9d864f1f5 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -50,7 +50,8 @@ PLIC_NUM_SRC 32'd53 deriv fpga buildroot BOOTROM_PRELOAD 1 UNCORE_RAM_BASE 64'h2000 -UNCORE_RAM_RANGE 64'hFFF +UNCORE_RAM_RANGE 64'h1FFF +BOOTROM_RANGE 64'hFFF EXT_MEM_SUPPORTED 1 EXT_MEM_BASE 64'h80000000 EXT_MEM_RANGE 64'h0FFFFFFF diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 4e156601b..b8f98d430 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -97,16 +97,21 @@ set_property IOSTANDARD LVCMOS33 [get_ports {south_reset}] #set_property PULLUP true [get_ports {SDCCmd}] #set_property PULLUP true [get_ports {SDCCD}] -set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[3]}] -set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] -set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] -set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[0]}] +# SDCDat[3] +set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCS}] +# set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[2]}] +# set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCDat[1]}] +# SDCDat[0] +set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCIn}] set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCLK}] set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] -set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCDat[*]}] -set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCDat[*]}] +set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCCS}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCCS}] + +set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCIn}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCIn}] set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.000 [get_ports {SDCCmd}] set_output_delay -clock [get_clocks SPISDCClock] -max -add_delay 6.000 [get_ports {SDCCmd}] diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index e9c04bca8..cadb49dfb 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -148,6 +148,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // APB access assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase + // JACOB: This shouldn't behave this way assign PREADY = TransmitInactive; // Tie PREADY to transmission for hardware interlock // Account for subword read/write circuitry @@ -366,22 +367,25 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode)); assign Active0 = (state == ACTIVE_0); - // Signal tracks which edge of sck to shift data + // Signal tracks which edge of sck to shift data + // Jacob: We need to confirm that this represents the actual polarity and phase options for sampling. + // The first option now samples on the leading edge and shifts on the falling edge like it's supposed to. + // We need to confirm the validity of the other options. always_comb case(SckMode[1:0]) - 2'b00: ShiftEdge = ~SPICLK & SCLKenable; - 2'b01: ShiftEdge = (SPICLK & |(FrameCount) & SCLKenable); - 2'b10: ShiftEdge = SPICLK & SCLKenable; - 2'b11: ShiftEdge = (~SPICLK & |(FrameCount) & SCLKenable); + 2'b00: ShiftEdge = SPICLK & SCLKenable; + 2'b01: ShiftEdge = (SPICLK & |(FrameCount) & SCLKenable); // Probably wrong + 2'b10: ShiftEdge = ~SPICLK & SCLKenable; // Probably wrong + 2'b11: ShiftEdge = (~SPICLK & |(FrameCount) & SCLKenable); // Probably wrong default: ShiftEdge = SPICLK & SCLKenable; endcase // Transmit shift register assign TransmitDataEndian = Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0]; always_ff @(posedge PCLK) - if(~PRESETn) TransmitShiftReg <= 8'b0; + if(~PRESETn) TransmitShiftReg <= 8'b0; // Temporarily changing to 1s else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian; - else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0}; + else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], TransmitShiftReg[0]}; // Temporarily changing to 1s assign SPIOut = TransmitShiftReg[7]; diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 7de407c63..21dd956ed 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -172,7 +172,7 @@ module uncore import cvw::*; #(parameter cvw_t P)( .PREADY(PREADY[5]), .PRDATA(PRDATA[5]), .SPIOut(SDCCmd), .SPIIn(SDCIn), .SPICS(SDCCS), .SPICLK(SDCCLK), .SPIIntr(SDCIntr)); end else begin : sdc - assign SDCCmd = '0; assign SDCCS = 1'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; + assign SDCCmd = '0; assign SDCCS = 4'b0; assign SDCIntr = 1'b0; assign SDCCLK = 1'b0; end diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 7ad173b78..77845aff3 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -90,7 +90,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( .UARTSout, .MTIME_CLINT, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); end else begin assign {HRDATA, HREADY, HRESP, HSELEXT, MTimerInt, MSwInt, MExtInt, SExtInt, - MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; + MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS, SPICLK, SDCCmd, SDCCS, SDCCLK} = '0; end endmodule diff --git a/testbench/wallywrapper.sv b/testbench/wallywrapper.sv index 2794240be..b326bb810 100644 --- a/testbench/wallywrapper.sv +++ b/testbench/wallywrapper.sv @@ -32,7 +32,7 @@ module wallywrapper import cvw::*;( input logic clk, input logic reset_ext, input logic SPIIn, - input logic SDCIntr + input logic SDCIn ); `include "parameter-defs.vh" @@ -56,10 +56,14 @@ module wallywrapper import cvw::*;( logic UARTSin, UARTSout; logic SPIOut; logic [3:0] SPICS; + logic SPICLK; + + logic SDCCmd; + logic [3:0] SDCCS; + logic SDCCLK; logic HREADY; logic HSELEXT; - logic HSELEXTSDC; // instantiate device to be tested @@ -71,9 +75,9 @@ module wallywrapper import cvw::*;( assign HRDATAEXT = 0; - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC, - .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, - .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr); + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, + .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, + .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, + .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); endmodule From 83b0a83d5cbe169f3e62b851e00084b9885a3990 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 2 Aug 2024 15:35:18 -0500 Subject: [PATCH 33/39] Removed HSELEXTSDC and fixed SD card pin definitions. --- fpga/src/fpgaTopArtyA7.sv | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 31848f33e..712f67869 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -42,10 +42,11 @@ module fpgaTop output UARTSout, // SDC Signals connecting to an SPI peripheral - input [3:0] SDCDat, + input SDCIn, output SDCCLK, output SDCCmd, - output SDCCD, + output SDCCS, + input SDCCD, // Memory signals inout [15:0] ddr3_dq, @@ -199,10 +200,8 @@ module fpgaTop assign cpu_reset = bus_struct_reset; assign calib = c0_init_calib_complete; - logic [3:0] SDCCS; - assign SDCCD = SDCCS[0]; - logic SDCIn; - assign SDCIn = SDCDat[0]; + logic [3:0] SDCCSin; + assign SDCCS = SDCCSin[0]; // mmcm @@ -243,14 +242,14 @@ module fpgaTop .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); + .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK); // ahb lite to axi bridge xlnx_ahblite_axi_bridge xlnx_ahblite_axi_bridge_0 (.s_ahb_hclk(CPUCLK), .s_ahb_hresetn(peripheral_aresetn), - .s_ahb_hsel(HSELEXT | HSELEXTSDC), + .s_ahb_hsel(HSELEXT), .s_ahb_haddr(HADDR[31:0]), .s_ahb_hprot(HPROT), .s_ahb_htrans(HTRANS), From ad9c98c19cd46a3f05fc26d086f70b1faead83e7 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Fri, 2 Aug 2024 15:36:06 -0500 Subject: [PATCH 34/39] Added file necessary to split boot.mem into boot.mem and data.mem. --- fpga/zsbl/splitfile.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 fpga/zsbl/splitfile.sh diff --git a/fpga/zsbl/splitfile.sh b/fpga/zsbl/splitfile.sh new file mode 100755 index 000000000..1e367c872 --- /dev/null +++ b/fpga/zsbl/splitfile.sh @@ -0,0 +1,18 @@ +# Acquired from here. +# https://stackoverflow.com/questions/3066948/how-to-file-split-at-a-line-number +file_name=$1 + +# set first K lines: +K=512 + +# line count (N): +N=$(wc -l < $file_name) + +# length of the bottom file: +L=$(( $N - $K )) + +# create the top of file: +head -n $K $file_name > boot.mem + +# create bottom of file: +tail -n $L $file_name > data.mem From 665396fdb3f1b8d0435207987c9b04926d1e9db1 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 6 Aug 2024 16:57:57 -0500 Subject: [PATCH 35/39] SD card is now mountable on the fpga. The relevant files have been added. The most important changes are in the buildroot linux configuration and device tree. --- fpga/constraints/constraints-ArtyA7.xdc | 8 ++- fpga/src/fpgaTopArtyA7.sv | 3 +- fpga/zsbl/boot.c | 2 +- linux/Makefile | 2 +- .../buildroot-2023.05.1/linux.config | 13 ++--- linux/devicetree/wally-artya7.dts | 51 ++++++++++++++----- 6 files changed, 55 insertions(+), 24 deletions(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index b8f98d430..394c58dda 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -35,6 +35,7 @@ set_property IOSTANDARD LVCMOS33 [get_ports {GPO[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPO[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {GPO[0]}] set_max_delay -to [get_ports {GPO[*]}] 20.000 + set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -min -add_delay 0.000 [get_ports {GPO[*]}] set_output_delay -clock [get_clocks clk_out3_xlnx_mmcm] -max -add_delay 0.000 [get_ports {GPO[*]}] @@ -106,18 +107,21 @@ set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33 PULLUP true} [get_ports { set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCLK}] set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCmd}] set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCCD}] +set_property -dict {PACKAGE_PIN G2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCWP}] + set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCCS}] -set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCCS}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 10.000 [get_ports {SDCCS}] set_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCIn}] -set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 21.000 [get_ports {SDCIn}] +set_input_delay -clock [get_clocks SPISDCClock] -max -add_delay 10.000 [get_ports {SDCIn}] set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.000 [get_ports {SDCCmd}] set_output_delay -clock [get_clocks SPISDCClock] -max -add_delay 6.000 [get_ports {SDCCmd}] set_output_delay -clock [get_clocks SPISDCClock] 0.000 [get_ports SDCCLK] + #set_multicycle_path -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 10 set_max_delay -datapath_only -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 20.000 diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 712f67869..5d038ad0f 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -47,6 +47,7 @@ module fpgaTop output SDCCmd, output SDCCS, input SDCCD, + input SDCWP, // Memory signals inout [15:0] ddr3_dq, @@ -194,7 +195,7 @@ module fpgaTop wire mmcm1_locked; - assign GPIOIN = {28'b0, GPI}; + assign GPIOIN = {25'b0, SDCCD, SDCWP, 1'b0, GPI}; assign GPO = GPIOOUT[4:0]; assign ahblite_resetn = peripheral_aresetn; assign cpu_reset = bus_struct_reset; diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index e47b34e2f..52473ab46 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -159,7 +159,7 @@ void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) { /* print_uart("\r\n"); */ // Intialize the SD card - init_sd(SYSTEMCLOCK, 3000000); + init_sd(SYSTEMCLOCK, 5000000); ret = gpt_load_partitions(); } diff --git a/linux/Makefile b/linux/Makefile index 6f7b6c7fb..b0b15ce7b 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -102,7 +102,7 @@ $(IMAGES)/busybox: # Generating new Buildroot directories -------------------------------- # This directive should be run as: make install BUILDROOT=path/to/buildroot -download: $(BUILDROOT)/package/fpga-axi-sdc $(WALLYBOARD) +download: $(WALLYBOARD) cp $(WALLYBOARD)/main.config $(BUILDROOT)/.config # CONFIG DEPENDENCIES 2023.05.1 --------------------------------------- diff --git a/linux/buildroot-config-src/buildroot-2023.05.1/linux.config b/linux/buildroot-config-src/buildroot-2023.05.1/linux.config index e348cde78..047be24c2 100644 --- a/linux/buildroot-config-src/buildroot-2023.05.1/linux.config +++ b/linux/buildroot-config-src/buildroot-2023.05.1/linux.config @@ -2,7 +2,7 @@ # Automatically generated file; DO NOT EDIT. # Linux/riscv 6.6.0 Kernel Configuration # -CONFIG_CC_VERSION_TEXT="riscv64-buildroot-linux-gnu-gcc.br_real (Buildroot 2023.05.3-dirty) 12.3.0" +CONFIG_CC_VERSION_TEXT="riscv64-buildroot-linux-gnu-gcc.br_real (Buildroot 2023.05.3) 12.3.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=120300 CONFIG_CLANG_VERSION=0 @@ -1042,7 +1042,7 @@ CONFIG_MMC_BLOCK_MINORS=8 # # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_SPI is not set +CONFIG_MMC_SPI=y # CONFIG_MMC_DW is not set # CONFIG_MMC_USDHI6ROL0 is not set # CONFIG_MMC_CQHCI is not set @@ -1455,7 +1455,7 @@ CONFIG_CRYPTO_HASH2=y # CONFIG_CRYPTO_POLY1305 is not set # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_SHA3 is not set # CONFIG_CRYPTO_SM3_GENERIC is not set @@ -1527,13 +1527,14 @@ CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 # CONFIG_CRYPTO_LIB_POLY1305 is not set # CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y # end of Crypto library routines # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set # CONFIG_CRC64_ROCKSOFT is not set -# CONFIG_CRC_ITU_T is not set +CONFIG_CRC_ITU_T=y CONFIG_CRC32=y # CONFIG_CRC32_SELFTEST is not set CONFIG_CRC32_SLICEBY8=y @@ -1542,7 +1543,7 @@ CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC32_BIT is not set # CONFIG_CRC64 is not set # CONFIG_CRC4 is not set -# CONFIG_CRC7 is not set +CONFIG_CRC7=y # CONFIG_LIBCRC32C is not set # CONFIG_CRC8 is not set # CONFIG_RANDOM32_SELFTEST is not set @@ -1599,7 +1600,7 @@ CONFIG_PRINTK_TIME=y # CONFIG_STACKTRACE_BUILD_ID is not set CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 CONFIG_CONSOLE_LOGLEVEL_QUIET=4 -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_DYNAMIC_DEBUG is not set # CONFIG_DYNAMIC_DEBUG_CORE is not set diff --git a/linux/devicetree/wally-artya7.dts b/linux/devicetree/wally-artya7.dts index 87933bcc0..99b8ff00d 100644 --- a/linux/devicetree/wally-artya7.dts +++ b/linux/devicetree/wally-artya7.dts @@ -5,11 +5,11 @@ #size-cells = <0x02>; compatible = "wally-virt"; model = "wally-virt,qemu"; - + chosen { linux,initrd-end = <0x85c43a00>; linux,initrd-start = <0x84200000>; - bootargs = "root=/dev/vda ro console=ttyS0,115200"; + bootargs = "root=/dev/vda ro console=ttyS0,115200 loglevel=7"; stdout-path = "/soc/uart@10000000"; }; @@ -51,6 +51,25 @@ compatible = "simple-bus"; ranges; + refclk: refclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0x1312D00>; + clock-output-names = "xtal"; + }; + + gpio0: gpio@10060000 { + compatible = "sifive,gpio0"; + interrupt-parent = <0x03>; + interrupts = <3>; + reg = <0x00 0x10060000 0x00 0x1000>; + reg-names = "control"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + uart@10000000 { interrupts = <0x0a>; interrupt-parent = <0x03>; @@ -70,18 +89,24 @@ #address-cells = <0x00>; }; - mmc@13000 { - interrupts = <0x14>; - compatible = "riscv,axi-sd-card-1.0"; - reg = <0x00 0x13000 0x00 0x7F>; - fifo-depth = <256>; - bus-width = <4>; + spi@13000 { + compatible = "sifive,spi0"; interrupt-parent = <0x03>; - clock = <0x1312D00>; - max-frequency = <0x1312D00>; - cap-sd-highspeed; - cap-mmc-highspeed; - no-sdio; + interrupts = <0x14>; + reg = <0x0 0x13000 0x0 0x1000>; + reg-names = "control"; + clocks = <&refclk>; + + #address-cells = <1>; + #size-cells = <0>; + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0>; + spi-max-frequency = <5000000>; + voltage-ranges = <3300 3300>; + disable-wp; + // gpios = <&gpio0 6 1>; + }; }; clint@2000000 { From 954e21148f8aac040f9ed9d8742b1d58754276e2 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 6 Aug 2024 17:11:08 -0500 Subject: [PATCH 36/39] Removed line referring to local file in wally.tcl. --- fpga/generator/wally.tcl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index 465d0c73a..b2e1e359e 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -92,8 +92,7 @@ if {$board=="ArtyA7"} { #source ../constraints/small-debug.xdc source ../constraints/small-debug-rvvi.xdc } else { - # source ../constraints/vcu-small-debug.xdc - source ../constraints/debug6.xdc + source ../constraints/vcu-small-debug.xdc } From 280b5baa59a5fdad57e1cae8eec4ef3f199c5da2 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 6 Aug 2024 17:28:50 -0500 Subject: [PATCH 37/39] Added header to new bootloader files. --- fpga/zsbl/boot.c | 77 ++++++++++++++++++----------------------------- fpga/zsbl/boot.h | 29 ++++++++++++++++++ fpga/zsbl/fail.c | 30 ++++++++++++++++++ fpga/zsbl/fail.h | 29 ++++++++++++++++++ fpga/zsbl/gpt.c | 29 ++++++++++++++++++ fpga/zsbl/gpt.h | 29 ++++++++++++++++++ fpga/zsbl/riscv.S | 29 ++++++++++++++++++ fpga/zsbl/riscv.h | 29 ++++++++++++++++++ fpga/zsbl/sd.c | 29 ++++++++++++++++++ fpga/zsbl/sd.h | 30 ++++++++++++++++++ fpga/zsbl/spi.c | 29 ------------------ fpga/zsbl/time.c | 29 ++++++++++++++++++ fpga/zsbl/time.h | 29 ++++++++++++++++++ fpga/zsbl/uart.c | 30 ++++++++++++++++++ fpga/zsbl/uart.h | 29 ++++++++++++++++++ 15 files changed, 409 insertions(+), 77 deletions(-) diff --git a/fpga/zsbl/boot.c b/fpga/zsbl/boot.c index 52473ab46..566393cb6 100644 --- a/fpga/zsbl/boot.c +++ b/fpga/zsbl/boot.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// boot.c +// +// Written: Jacob Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Main bootloader entry point +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #include #include "boot.h" #include "gpt.h" @@ -8,54 +37,6 @@ #include "riscv.h" #include "fail.h" -/* int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) { */ - -/* /\* This is not needed. This has everything to do with the FAT */ -/* filesystem stuff that I'm not including. All I need to do is */ -/* initialize the SD card and read from it. Anything in here that is */ -/* checking for potential errors, I'm going to have to temporarily */ -/* do without. */ -/* *\/ */ -/* // if (!count) return RES_PARERR; */ -/* /\* if (drv_status & STA_NOINIT) return RES_NOTRDY; *\/ */ - -/* uint32_t response[4]; */ -/* struct sdc_regs * regs = (struct sdc_regs *)SDC; */ - -/* /\* Convert LBA to byte address if needed *\/ */ -/* if (!(card_type & CT_BLOCK)) sector *= 512; */ -/* while (count > 0) { */ -/* UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count; */ -/* unsigned bytes = bcnt * 512; */ -/* if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1; */ -/* if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1; */ -/* sector += (card_type & CT_BLOCK) ? bcnt : bytes; */ -/* count -= bcnt; */ -/* buf += bytes; */ -/* } */ - -/* return 0;; */ -/* } */ - -// Need to convert this -/* void print_progress(size_t count, size_t max) { */ -/* const int bar_width = 50; */ - -/* float progress = (float) count / max; */ -/* int bar_length = progress * bar_width; */ - -/* printf("\r["); */ -/* for (int i = 0; i < bar_length; ++i) { */ -/* printf("#"); */ -/* } */ -/* for (int i = bar_length; i < bar_width; ++i) { */ -/* printf("-"); */ -/* } */ -/* printf("] %.2f%%", progress * 100); */ - -/* fflush(stdout); */ -/* } */ - int disk_read(BYTE * buf, LBA_t sector, UINT count) { uint64_t r; UINT i; diff --git a/fpga/zsbl/boot.h b/fpga/zsbl/boot.h index 25b8a5fcc..0c09a1e52 100644 --- a/fpga/zsbl/boot.h +++ b/fpga/zsbl/boot.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// boot.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header for boot.c, main bootloader entry point +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #ifndef WALLYBOOT #define WALLYBOOT 10000 diff --git a/fpga/zsbl/fail.c b/fpga/zsbl/fail.c index 4e6cd8db0..4430c4a8f 100644 --- a/fpga/zsbl/fail.c +++ b/fpga/zsbl/fail.c @@ -1,3 +1,33 @@ +/////////////////////////////////////////////////////////////////////// +// fail.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Prints information on the uart when a fatal bug is +// encountered. Will expand this later. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #include "fail.h" #include "uart.h" #include "riscv.h" diff --git a/fpga/zsbl/fail.h b/fpga/zsbl/fail.h index da1a2e405..c965265d1 100644 --- a/fpga/zsbl/fail.h +++ b/fpga/zsbl/fail.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// fail.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Function prototype for fail, +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #pragma once #include diff --git a/fpga/zsbl/gpt.c b/fpga/zsbl/gpt.c index 99f74ec3a..e21176f05 100644 --- a/fpga/zsbl/gpt.c +++ b/fpga/zsbl/gpt.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// gpt.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Code to read GPT Partitions off of an SD card. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #include "gpt.h" #include "boot.h" #include "uart.h" diff --git a/fpga/zsbl/gpt.h b/fpga/zsbl/gpt.h index 5ce5e1d4b..8cd3ecc11 100644 --- a/fpga/zsbl/gpt.h +++ b/fpga/zsbl/gpt.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// gpt.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header for gpt.c, contains gpt structs +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #pragma once #include diff --git a/fpga/zsbl/riscv.S b/fpga/zsbl/riscv.S index 7f400b1b2..b2d86599c 100644 --- a/fpga/zsbl/riscv.S +++ b/fpga/zsbl/riscv.S @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// riscv.S +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Basic utility functions for reading registers +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + .section .text .globl read_mcycle .type read_mcycle, @function diff --git a/fpga/zsbl/riscv.h b/fpga/zsbl/riscv.h index a27cd48d6..543fe5cde 100644 --- a/fpga/zsbl/riscv.h +++ b/fpga/zsbl/riscv.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// riscv.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Function prototypes for riscv utility functions +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #pragma once #include diff --git a/fpga/zsbl/sd.c b/fpga/zsbl/sd.c index 484fd65c0..1f95d8477 100644 --- a/fpga/zsbl/sd.c +++ b/fpga/zsbl/sd.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// sd.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: SD Card protocol functions +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #include "sd.h" #include "spi.h" #include "uart.h" diff --git a/fpga/zsbl/sd.h b/fpga/zsbl/sd.h index f695b83e5..f66686560 100644 --- a/fpga/zsbl/sd.h +++ b/fpga/zsbl/sd.h @@ -1,3 +1,33 @@ +/////////////////////////////////////////////////////////////////////// +// sd.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header file for SD card protocol functions. Defines some +// useful macros. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #pragma once #include diff --git a/fpga/zsbl/spi.c b/fpga/zsbl/spi.c index 5b23c85b6..04d609648 100644 --- a/fpga/zsbl/spi.c +++ b/fpga/zsbl/spi.c @@ -29,31 +29,6 @@ #include "spi.h" -// Write to a register -/* inline void write_reg(uintptr_t addr, uint32_t value) { */ -/* volatile uint32_t * loc = (volatile uint32_t *) addr; */ -/* *loc = value; */ -/* } */ - -/* // Read a register */ -/* inline uint32_t read_reg(uintptr_t addr) { */ -/* return *(volatile uint32_t *) addr; */ -/* } */ - -/* // Queues a single byte in the transfer fifo */ -/* inline void spi_sendbyte(uint8_t byte) { */ -/* // Write byte to transfer fifo */ -/* write_reg(SPI_TXDATA, byte); */ -/* } */ - -/* inline void waittx() { */ -/* while(!(read_reg(SPI_IP) & 1)) {} */ -/* } */ - -/* inline void waitrx() { */ -/* while(read_reg(SPI_IP) & 2) {} */ -/* } */ - uint8_t spi_txrx(uint8_t byte) { spi_sendbyte(byte); waittx(); @@ -64,10 +39,6 @@ uint8_t spi_dummy() { return spi_txrx(0xff); } -/* inline uint8_t spi_readbyte() { */ -/* return read_reg(SPI_RXDATA); */ -/* } */ - uint64_t spi_read64() { uint64_t r; uint8_t rbyte; diff --git a/fpga/zsbl/time.c b/fpga/zsbl/time.c index 43ac085b7..c265eea05 100644 --- a/fpga/zsbl/time.c +++ b/fpga/zsbl/time.c @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// time.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Gets and prints the current time. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #include "time.h" #include "boot.h" #include "riscv.h" diff --git a/fpga/zsbl/time.h b/fpga/zsbl/time.h index 6cd928b88..8bf7064af 100644 --- a/fpga/zsbl/time.h +++ b/fpga/zsbl/time.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// spi.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Time function prototypes +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #pragma once #include diff --git a/fpga/zsbl/uart.c b/fpga/zsbl/uart.c index 8c25f17ca..580265d98 100644 --- a/fpga/zsbl/uart.c +++ b/fpga/zsbl/uart.c @@ -1,3 +1,33 @@ +/////////////////////////////////////////////////////////////////////// +// uart.c +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Uart printing functions, as well as functions for printing +// hex, decimal, and floating point numbers. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #include "uart.h" void write_reg_u8(uintptr_t addr, uint8_t value) diff --git a/fpga/zsbl/uart.h b/fpga/zsbl/uart.h index cbdcc5941..96c55ffe8 100644 --- a/fpga/zsbl/uart.h +++ b/fpga/zsbl/uart.h @@ -1,3 +1,32 @@ +/////////////////////////////////////////////////////////////////////// +// uart.h +// +// Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +// +// Purpose: Header for the UART functions. +// +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the +// “License”); you may not use this file except in compliance with the +// License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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. +/////////////////////////////////////////////////////////////////////// + #pragma once #include #include "riscv.h" From 2dc7e0f76fa4cceca5fffc8612244365f7e9c40a Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 6 Aug 2024 17:36:42 -0500 Subject: [PATCH 38/39] Added and extra header and changed the comments to be accurate in ram1p1rwbe.sv --- fpga/zsbl/splitfile.sh | 32 +++++++++++++++++++++++++++++++- src/generic/mem/ram1p1rwbe.sv | 6 +++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/fpga/zsbl/splitfile.sh b/fpga/zsbl/splitfile.sh index 1e367c872..fc943576c 100755 --- a/fpga/zsbl/splitfile.sh +++ b/fpga/zsbl/splitfile.sh @@ -1,5 +1,35 @@ +####################################################################### +# splitfile.sh +# +# Written: Jaocb Pease jacob.pease@okstate.edu 7/22/2024 +# +# Purpose: Used to split boot.mem into two sections for FPGA +# +# +# +# A component of the Wally configurable RISC-V project. +# +# Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +# +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +# +# Licensed under the Solderpad Hardware License v 2.1 (the +# “License”); you may not use this file except in compliance with the +# License, or, at your option, the Apache License version 2.0. You +# may obtain a copy of the License at +# +# https://solderpad.org/licenses/SHL-2.1/ +# +# Unless required by applicable law or agreed to in writing, any work +# 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. +###################################################################### + + # Acquired from here. -# https://stackoverflow.com/questions/3066948/how-to-file-split-at-a-line-number +# https:##stackoverflow.com#questions#3066948#how-to-file-split-at-a-line-number file_name=$1 # set first K lines: diff --git a/src/generic/mem/ram1p1rwbe.sv b/src/generic/mem/ram1p1rwbe.sv index 287607c9e..d17262d22 100644 --- a/src/generic/mem/ram1p1rwbe.sv +++ b/src/generic/mem/ram1p1rwbe.sv @@ -99,11 +99,11 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE `ifdef VERILATOR // because Verilator doesn't automatically accept $WALLY from shell string WALLY_DIR = getenvval("WALLY"); - $readmemh({WALLY_DIR,"/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + $readmemh({WALLY_DIR,"/fpga/src/data.mem"}, RAM, 0); // load boot RAM for FPGA `else - $readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot ROM for FPGA + $readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot RAM for FPGA `endif - end else begin // put something in the ROM so it is not optimized away + end else begin // put something in the RAM so it is not optimized away RAM[0] = 'h00002197; end end From 0303314f4e34c6aee826d17283cc877c22460bf7 Mon Sep 17 00:00:00 2001 From: Huda-10xe Date: Wed, 7 Aug 2024 14:19:05 +0500 Subject: [PATCH 39/39] Adding RVVI Functional Coverage Support --- .gitignore | 3 +++ .gitmodules | 3 +++ bin/regression-wally | 12 ++++++++++++ bin/wsim | 7 +++++-- cvw-arch-verif | 1 + sim/questa/wally.do | 21 ++++++++++++++++++++- testbench/testbench.sv | 12 ++++++++++++ tests/riscof/Makefile | 9 +++++++++ 8 files changed, 65 insertions(+), 3 deletions(-) create mode 160000 cvw-arch-verif diff --git a/.gitignore b/.gitignore index 3a6dad8b0..3d3d875f0 100644 --- a/.gitignore +++ b/.gitignore @@ -193,6 +193,9 @@ config/deriv docs/docker/buildroot-config-src docs/docker/testvector-generation sim/questa/cov +sim/questa/fcovrvvi +sim/questa/fcovrvvi_logs +sim/questa/fcovrvvi_ucdb sim/covhtmlreport/ sim/questa/logs sim/questa/wkdir diff --git a/.gitmodules b/.gitmodules index 69054d830..e2c94791f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,3 +34,6 @@ sparseCheckout = true path = addins/verilog-ethernet url = https://github.com/ross144/verilog-ethernet.git +[submodule "cvw-arch-verif"] + path = cvw-arch-verif + url = https://github.com/openhwgroup/cvw-arch-verif diff --git a/bin/regression-wally b/bin/regression-wally index 3040f584b..e83c3b5fa 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -340,6 +340,7 @@ defaultsim = "verilator" # Default simulator for all other tests parser = argparse.ArgumentParser() parser.add_argument("--ccov", help="Code Coverage", action="store_true") parser.add_argument("--fcov", help="Functional Coverage", action="store_true") +parser.add_argument("--fcovrvvi", help="Functional Coverage RVVI", action="store_true") parser.add_argument("--nightly", help="Run large nightly regression", action="store_true") parser.add_argument("--buildroot", help="Include Buildroot Linux boot test (takes many hours, done along with --nightly)", action="store_true") parser.add_argument("--testfloat", help="Include Testfloat floating-point unit tests", action="store_true") @@ -357,6 +358,8 @@ if (args.ccov): # only run RV64GC tests in coverage mode coverStr = '--ccov' elif (args.fcov): # only run RV64GC tests in lockstep in coverage mode coverStr = '--fcov' +elif (args.fcovrvvi): # only run RV64GC tests in rvvi coverage mode + coverStr = '--fcovrvvi' else: coverStr = '' @@ -392,6 +395,10 @@ elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional c # grepstr="SUCCESS! All tests ran without failures", # grepfile = sim_log) #configs.append(tc) +elif (args.fcovrvvi): # only run RV64GC tests on Questa in rvvi coverage mode + addTests(tests64gc_nofp, coveragesim) + if (args.fp): + addTests(tests64gc_fp, coveragesim) else: for sim in sims: if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one @@ -501,6 +508,9 @@ def main(): if args.ccov: TIMEOUT_DUR = 20*60 # seconds os.system('rm -f questa/cov/*.ucdb') + elif args.fcovrvvi: + TIMEOUT_DUR = 20*60 + os.system('rm -f questa/fcovrvvi_ucdb/* questa/fcovrvvi_logs/* questa/fcovrvvi/*') elif args.fcov: TIMEOUT_DUR = 1*60 os.system('rm -f questa/fcov_ucdb/* questa/fcov_logs/* questa/fcov/*') @@ -535,6 +545,8 @@ def main(): os.system('make QuestaCodeCoverage') if args.fcov: os.system('make QuestaFunctCoverage') + if args.fcovrvvi: + os.system('make QuestaFunctCoverageRvvi') # Count the number of failures if num_fail: print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) diff --git a/bin/wsim b/bin/wsim index b2288deb4..d837bca85 100755 --- a/bin/wsim +++ b/bin/wsim @@ -28,6 +28,7 @@ parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testb parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true") parser.add_argument("--fcov", "-f", help="Functional Coverage, implies lockstep", action="store_true") +parser.add_argument("--fcovrvvi", "-fr", help="Functional Coverage RVVI", action="store_true") parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_true") parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") @@ -57,7 +58,7 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che # Validate arguments -if (args.gui or args.ccov or args.fcov or args.lockstep): +if (args.gui or args.ccov or args.fcov or args.fcovrvvi or args.lockstep): if args.sim not in ["questa", "vcs"]: print("Option only supported for Questa and VCS") exit(1) @@ -95,10 +96,12 @@ if (args.ccov): flags += " --ccov" if (args.fcov): flags += " --fcov" +if (args.fcovrvvi): + flags += "--fcovrvvi" # create the output sub-directories. regressionDir = WALLY + '/sim/' -for d in ["logs", "wkdir", "cov", "ucdb", "fcov", "fcov_ucdb"]: +for d in ["logs", "wkdir", "cov", "ucdb", "fcov", "fcov_ucdb", "fcovrvvi", "fcovrvvi_ucdb"]: try: os.mkdir(regressionDir+args.sim+"/"+d) except: diff --git a/cvw-arch-verif b/cvw-arch-verif new file mode 160000 index 000000000..2a4f56ec9 --- /dev/null +++ b/cvw-arch-verif @@ -0,0 +1 @@ +Subproject commit 2a4f56ec97db7cdd6fd13fb928122d408fefbf1e diff --git a/sim/questa/wally.do b/sim/questa/wally.do index 632e2c156..43892c356 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -31,6 +31,7 @@ set WALLY $::env(WALLY) set CONFIG ${WALLY}/config set SRC ${WALLY}/src set TB ${WALLY}/testbench +set FCRVVI ${WALLY}/addins/cvw-arch-verif/fcov # create library if [file exists ${WKDIR}] { @@ -39,11 +40,16 @@ if [file exists ${WKDIR}] { vlib ${WKDIR} # Create directory for coverage data mkdir -p cov +# Create directory for functional coverage data +mkdir ${WALLY}/addins/cvw-arch-verif/work set ccov 0 set CoverageVoptArg "" set CoverageVsimArg "" +set FuncCovRVVI 0 +set FCdefineRVVI_COVERAGE "" + set FunctCoverage 0 set riscvISACOVsrc "" set FCdefineINCLUDE_TRACE2COV "" @@ -113,6 +119,13 @@ if {$CoverageIndex >= 0} { set lst [lreplace $lst $CoverageIndex $CoverageIndex] } +set FCoverageIndexRVVI [lsearch -exact $lst "--fcovrvvi"] +if {$FCoverageIndexRVVI >= 0} { + set FuncCovRVVI 1 + set FCdefineRVVI_COVERAGE "+define+RVVI_COVERAGE" + set lst [lreplace $lst $FCoverageIndexRVVI $FCoverageIndexRVVI] +} + # if +coverage found set flag and remove from list set FunctCoverageIndex [lsearch -exact $lst "--fcov"] if {$FunctCoverageIndex >= 0} { @@ -172,6 +185,7 @@ if {$DEBUG > 0} { echo "GUI = $GUI" echo "ccov = $ccov" echo "lockstep = $lockstep" + echo "FuncCovRVVI = $FuncCovRVVI" echo "FunctCoverage = $FunctCoverage" echo "remaining list = $lst" echo "Extra +args = $PlusArgs" @@ -197,7 +211,7 @@ set temp3 [lindex $PlusArgs 3] # "Extra checking for conflicts with always_comb done at vopt time" # because vsim will run vopt -vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 +vlog -lint -work ${WKDIR} +incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared ${lockstepvoptstring} ${FCdefineIDV_INCLUDE_TRACE2COV} ${FCdefineINCLUDE_TRACE2COV} ${ImperasPubInc} ${ImperasPrivInc} ${rvviFiles} ${FCdefineCOVER_BASE_RV64I} ${FCdefineCOVER_LEVEL_DV_PR_EXT} ${FCdefineCOVER_RV64I} ${FCdefineCOVER_RV64M} ${FCdefineCOVER_RV64A} ${FCdefineCOVER_RV64F} ${FCdefineCOVER_RV64D} ${FCdefineCOVER_RV64ZICSR} ${FCdefineCOVER_RV64C} ${FCdefineRVVI_COVERAGE} ${idvFiles} ${riscvISACOVsrc} ${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv +incdir+${FCRVVI}/common +incdir+${FCRVVI} ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals @@ -224,6 +238,11 @@ if {$FunctCoverage} { coverage save -onexit ${UCDB} } +if {$FuncCovRVVI} { + set UCDB ${WALLY}/addins/cvw-arch-verif/work/${CFG}_${TESTSUITE}.ucdb + coverage save -onexit ${UCDB} +} + run -all if {$ccov} { diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 89d3b06d5..c53e0a842 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -33,6 +33,12 @@ `include "idv/idv.svh" `endif +`ifdef RVVI_COVERAGE + `include "RISCV_trace_data.svh" + `include "rvvicov.svh" + `include "wrapper.sv" +`endif + import cvw::*; module testbench; @@ -982,6 +988,12 @@ test_pmp_coverage #(P) pmp_inst(clk); /* verilator lint_on WIDTHTRUNC */ /* verilator lint_on WIDTHEXPAND */ +`ifdef RVVI_COVERAGE + rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi(); + wallyTracer #(P) wallyTracer(rvvi); + wrapper #(P) wrap(clk); +`endif + endmodule /* verilator lint_on STMTDLY */ diff --git a/tests/riscof/Makefile b/tests/riscof/Makefile index aaa8a8344..1d42cf10c 100644 --- a/tests/riscof/Makefile +++ b/tests/riscof/Makefile @@ -4,13 +4,18 @@ work_dir = ./riscof_work work = ./work arch_workdir = $(work)/riscv-arch-test wally_workdir = $(work)/wally-riscv-arch-test +custom_test_dir = ../../addins/cvw-arch-verif/test +submodule_work_dir = ../../addins/cvw-arch-verif/riscof_work current_dir = $(shell pwd) #XLEN ?= 64 all: root arch32 wally32 arch32e arch64 wally64 + wally-riscv-arch-test: root wally64 wally32 +custom: new_test + root: mkdir -p $(work_dir) mkdir -p $(work) @@ -47,6 +52,9 @@ wally64: quad64: riscof run --work-dir=$(work_dir) --config=config64.ini --suite=$(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests/ --env=$(wally_dir)/riscv-test-suite/env + +new_test: + riscof run --work-dir=$(submodule_work_dir) --config=config64.ini --suite=$(custom_test_dir)/ --env=$(wally_dir)/riscv-test-suite/env --no-browser #wally32e: # riscof run --work-dir=$(work_dir) --config=config32e.ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run @@ -66,3 +74,4 @@ clean: rm -rf $(work_dir) rm -rf $(wally_workdir) rm -rf $(arch_workdir) + rm -rf $(submodule_wor_dir)