Merge branch 'main' of https://github.com/openhwgroup/cvw into installation

This commit is contained in:
Jordan Carlin 2024-08-07 20:22:55 -07:00
commit 76eef03fe4
No known key found for this signature in database
39 changed files with 1718 additions and 1271 deletions

3
.gitignore vendored
View File

@ -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

3
.gitmodules vendored
View File

@ -28,3 +28,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

View File

@ -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)

View File

@ -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:

View File

@ -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

1
cvw-arch-verif Submodule

@ -0,0 +1 @@
Subproject commit 2a4f56ec97db7cdd6fd13fb928122d408fefbf1e

View File

@ -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}]
@ -60,6 +61,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[*]}]
@ -100,42 +102,52 @@ 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}]
# 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_property -dict {PACKAGE_PIN G2 IOSTANDARD LVCMOS33 PULLUP true} [get_ports {SDCWP}]
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_input_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [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 10.000 [get_ports {SDCIn}]
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 SPISDCClock] 0.000 [get_ports SDCCLK]
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_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

View File

@ -7,7 +7,7 @@ dst := IP
# vcu108
# export XILINX_PART := xcvu095-ffva2104-2-e
#export XILINX_BOARD := xilinx.com:vcu108:part0:1.2
# export XILINX_BOARD := xilinx.com:vcu108:part0:1.7
# export board := vcu108
# Arty A7
@ -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:
@ -61,6 +61,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

View File

@ -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
@ -91,10 +91,8 @@ write_verilog -force -mode funcsim sim/syn-funcsim.v
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
}

View File

@ -33,17 +33,21 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
(* mark_debug = "true" *) input resetn,
input south_reset,
// GPIO signals
input [3:0] GPI,
output [4:0] GPO,
// UART Signals
input UARTSin,
output UARTSout,
inout [3:0] SDCDat,
// SDC Signals connecting to an SPI peripheral
input SDCIn,
output SDCCLK,
inout SDCCmd,
output SDCCmd,
output SDCCS,
input SDCCD,
input SDCWP,
/*
* Ethernet: 100BASE-T MII
*/
@ -76,6 +80,7 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
output [0:0] ddr3_odt
);
// MMCM Signals
wire CPUCLK;
wire c0_ddr4_ui_clk_sync_rst;
wire bus_struct_reset;
@ -84,12 +89,12 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
wire peripheral_aresetn;
wire mb_reset;
// AHB Signals from Wally
wire HCLKOpen;
wire HRESETnOpen;
wire [63:0] HRDATAEXT;
wire HREADYEXT;
wire HRESPEXT;
wire HSELEXTSDC; // TEMP BOOT SIGNAL - JACOB
wire HSELEXT;
wire [55:0] HADDR;
wire [63:0] HWDATA;
@ -102,12 +107,10 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
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;
@ -144,11 +147,11 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
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;
@ -188,246 +191,6 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
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 dbg_clk;
wire [511 : 0] dbg_bus;
@ -446,12 +209,15 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
(* mark_debug = "true" *) logic RVVIStall;
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;
assign calib = c0_init_calib_complete;
logic [3:0] SDCCSin;
assign SDCCS = SDCCSin[0];
// mmcm
// the ddr3 mig7 requires 2 input clocks
@ -467,25 +233,6 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
.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
@ -501,26 +248,24 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
.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,
.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,
.UARTSin, .UARTSout, .SDCIntr, .ExternalStall(RVVIStall));
.UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK, .ExternalStall(RVVIStall));
// 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),
@ -568,432 +313,49 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
.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),
@ -1037,6 +399,7 @@ module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 1)
.m_axi_rlast(BUS_axi_rlast),
.m_axi_rready(BUS_axi_rready));
// DDR3 Controller
xlnx_ddr3 xlnx_ddr3_c0
(
// ddr3 I/O

View File

@ -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 :=
@ -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

View File

@ -1,422 +1,146 @@
///////////////////////////////////////////////////////////////////////
// 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 <stddef.h>
#include "boot.h"
#include "gpt.h"
#include "uart.h"
#include "spi.h"
#include "sd.h"
#include "time.h"
#include "riscv.h"
#include "fail.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) {
uint64_t r;
UINT i;
volatile uint8_t *p = buf;
#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) */
UINT modulus = count/50;
// Capability bits
#define SDC_CAPABILITY_SD_4BIT 0x0001
#define SDC_CAPABILITY_SD_RESET 0x0002
#define SDC_CAPABILITY_ADDR 0xff00
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;
// 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;
}
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");
fail();
// return -1;
}
static int sdc_cmd_finish(unsigned cmd, uint32_t * response) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
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;
uint64_t n = 0;
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;
// Wait for 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 < 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_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;
fail();
}
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) {}
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;
if ( (i % modulus) == 0 ) {
print_uart("\r Blocks loaded: ");
print_uart_dec(i);
print_uart("/");
print_uart_dec(count);
}
static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks, uint32_t * response) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
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();
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;
}
#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();
// Initialize UART for messages
init_uart(20000000, 115200);
// BYTE * buf = (BYTE *)Dst;
// Print the wally banner
print_uart(BANNER);
// if (disk_read(buf, (LBA_t)address, (UINT)numBlocks, card_type) < 0) /* UART Print function?*/;
/* print_uart("System clock speed: "); */
/* print_uart_dec(SYSTEMCLOCK); */
/* print_uart("\r\n"); */
ret = gpt_load_partitions(card_type);
// Intialize the SD card
init_sd(SYSTEMCLOCK, 5000000);
ret = gpt_load_partitions();
}
/*
int main() {
ini_sd();
return 0;
}
*/

View File

@ -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
@ -19,8 +48,20 @@ typedef QWORD LBA_t;
#define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START
#define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR
#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, BYTE card_type);
int disk_read(BYTE * buf, LBA_t sector, UINT count);
#define SYSTEMCLOCK 20000000
#endif // WALLYBOOT

49
fpga/zsbl/fail.c Normal file
View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////
// 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"
#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) {
}
}

33
fpga/zsbl/fail.h Normal file
View File

@ -0,0 +1,33 @@
///////////////////////////////////////////////////////////////////////
// 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 <stdint.h>
void fail();

View File

@ -1,19 +1,38 @@
///////////////////////////////////////////////////////////////////////
// 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"
#include <stddef.h>
/* 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(BYTE card_type) {
// In this version of the GPT partition code
// I'm going to assume that the SD card is already initialized.
int gpt_load_partitions() {
// size_t block_size = 512/8;
// long int lba1_buf[block_size];
@ -21,26 +40,51 @@ 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);
/* Possible error handling with UART message
if ( ret != 0 ) {
}*/
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, 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);
// 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) {
print_uart("Failed to load device tree!\r\n");
return -1;
}
// 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) {
print_uart("Failed to load OpenSBI!\r\n");
return -1;
}
// 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) {
print_uart("Failed to load Linux!\r\n");
return -1;
}
print_time();
println("Done! Flashing LEDs and jumping to OpenSBI...");
return 0;
}

View File

@ -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 <stdint.h>
@ -37,4 +66,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();

58
fpga/zsbl/riscv.S Normal file
View File

@ -0,0 +1,58 @@
///////////////////////////////////////////////////////////////////////
// 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
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

36
fpga/zsbl/riscv.h Normal file
View File

@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////
// 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 <stdint.h>
uint64_t read_mcycle();
uint64_t get_ra();
void set_status_fs();
void clear_status_fs();

255
fpga/zsbl/sd.c Normal file
View File

@ -0,0 +1,255 @@
///////////////////////////////////////////////////////////////////////
// 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"
#include "fail.h"
#include "time.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;
remainder ^= (remainder >> 4) ^ (remainder >> 7);
remainder = (remainder << 1) ^ (remainder << 4);
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);
crc ^= data;
crc ^= (uint8_t)(crc >> 4) & 0xf;
crc ^= crc << 12;
crc ^= (crc & 0xff) << 5;
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;
uint8_t shiftAmnt;
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 8:
response_len = R7_RESPONSE;
break;
case 12:
response_len = R1B_RESPONSE;
break;
default:
response_len = R1_RESPONSE;
break;
}
// Make interrupt pending after response fifo receives the correct
// 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 7 bytes into transfer fifo
// spi_sendbyte(0xff);
spi_dummy();
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 < 7; 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(); */
// 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_dummy();
} while ( (rbyte & 0x80) != 0 );
// 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_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
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_dummy();
*crc = crc16(*crc, rbyte);
r = r | ((uint64_t)(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
#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.
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);
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'
// 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.");
}

49
fpga/zsbl/sd.h Normal file
View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////
// 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 <stdint.h>
// 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 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);
int init_sd(uint32_t freq, uint32_t sdclk);

91
fpga/zsbl/spi.c Normal file
View File

@ -0,0 +1,91 @@
///////////////////////////////////////////////////////////////////////
// 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"
uint8_t spi_txrx(uint8_t byte) {
spi_sendbyte(byte);
waittx();
return spi_readbyte();
}
uint8_t spi_dummy() {
return spi_txrx(0xff);
}
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;
}
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(uint32_t clkin) {
// 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);
}

87
fpga/zsbl/spi.h Normal file
View File

@ -0,0 +1,87 @@
#pragma once
#ifndef SPI_HEADER
#define SPI_HEADER
#include <stdint.h>
#define SPI_BASE 0x13000 /* Base address of SPI device used for SDC */
/* register offsets */
#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 SPI_BASE + 0x60 // SPI flash interface control
#define SPI_FFMT SPI_BASE + 0x64 // SPI flash instruction format
*/
#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) ((uint32_t)(x))
#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU
#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) ((uint32_t)(x))
#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU
#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((uint32_t)(x) << 16)
#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16)
/* csmode bits */
#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U
#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U
#define SIFIVE_SPI_CSMODE_MODE_OFF 3U
// 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);
uint8_t spi_dummy();
//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;
*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

48
fpga/zsbl/splitfile.sh Executable file
View File

@ -0,0 +1,48 @@
#######################################################################
# 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
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

49
fpga/zsbl/time.c Normal file
View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////
// 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"
#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("] ");
}

34
fpga/zsbl/time.h Normal file
View File

@ -0,0 +1,34 @@
///////////////////////////////////////////////////////////////////////
// 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 <stdint.h>
float getTime();
void print_time();

193
fpga/zsbl/uart.c Normal file
View File

@ -0,0 +1,193 @@
///////////////////////////////////////////////////////////////////////
// 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)
{
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_LSR) & 0x20;
}
int is_receive_empty()
{
return !(read_reg_u8(UART_LSR) & 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)
{
// 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
}
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_hex(uint64_t addr, int n)
{
int i;
for (i = n - 1; 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 = 1;
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]);
}
}
// 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; */
/* 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]); */
/* } */

87
fpga/zsbl/uart.h Normal file
View File

@ -0,0 +1,87 @@
///////////////////////////////////////////////////////////////////////
// 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 <stdint.h>
#include "riscv.h"
#include "time.h"
// UART register addresses
#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
// 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);
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);
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)
#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")
#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("] ") */

View File

@ -107,7 +107,7 @@ $(IMAGES)/busybox:
# Generating new Buildroot directories --------------------------------
download: $(BUILDROOT)/package/fpga-axi-sdc $(WALLYBOARD)
download: $(WALLYBOARD)
cp $(WALLYBOARD)/main.config $(BUILDROOT)/.config
@echo "Buildroot successfully download."

View File

@ -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

View File

@ -9,7 +9,7 @@
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 {

View File

@ -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} {

View File

@ -83,9 +83,28 @@ 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;
// end
// end
`ifdef VERILATOR
import "DPI-C" function string getenvval(input string env_name);
`endif
initial
if (PRELOAD_ENABLED) begin
initial begin
RAM[0] = 64'h00600100d2e3ca40;
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 RAM for FPGA
`else
$readmemh({"$WALLY/fpga/src/data.mem"}, RAM, 0); // load boot RAM for FPGA
`endif
end else begin // put something in the RAM so it is not optimized away
RAM[0] = 'h00002197;
end
end

View File

@ -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
@ -147,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
@ -358,7 +360,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])));
@ -366,21 +368,24 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
assign Active0 = (state == ACTIVE_0);
// 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 = ~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); // 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];

View File

@ -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;
@ -75,18 +78,18 @@ 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;
(* 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({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; // 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 SDCCS = 4'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

View File

@ -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,
// fpga debug signals
input logic ExternalStall,
// outputs to external memory, shared with uncore memory
@ -57,10 +56,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,12 +87,12 @@ 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, .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;
assign {HRDATA, HREADY, HRESP, HSELEXT, MTimerInt, MSwInt, MExtInt, SExtInt,
MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS, SPICLK, SDCCmd, SDCCS, SDCCLK} = '0;
end

View File

@ -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;
@ -77,7 +83,6 @@ module testbench;
// DUT signals
logic [P.AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT;
logic HSELEXTSDC;
logic [P.PA_BITS-1:0] HADDR;
logic [P.AHBW-1:0] HWDATA;
logic [P.XLEN/8-1:0] HWSTRB;
@ -93,7 +98,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;
@ -372,6 +381,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"};
@ -506,6 +520,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
@ -585,16 +616,16 @@ 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, .ExternalStall(RVVIStall),
.HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.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
@ -957,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 */

View File

@ -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,15 @@ 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;
logic ExternalStall;
// instantiate device to be tested
@ -72,9 +77,9 @@ module wallywrapper import cvw::*;(
assign ExternalStall = '0;
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC,
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall, .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, .SDCIntr);
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK);
endmodule

View File

@ -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)
@ -48,6 +53,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
# rsync -a $(work_dir)/rv32i_m/ $(wally_workdir)/rv32i_m/ || echo "error suppressed"
@ -66,3 +74,4 @@ clean:
rm -rf $(work_dir)
rm -rf $(wally_workdir)
rm -rf $(arch_workdir)
rm -rf $(submodule_wor_dir)