diff --git a/config/derivlist.txt b/config/derivlist.txt index 3b88fa160..3fc5c0965 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -65,6 +65,9 @@ EXT_MEM_RANGE 64'h0FFFFFFF deriv fpgagenesys2 fpga EXT_MEM_RANGE 64'h3FFFFFFF +deriv fpgaqmtechk7 fpga +EXT_MEM_RANGE 64'h0FFFFFFF + deriv fpgavcu108 fpga EXT_MEM_RANGE 64'h7FFFFFFF diff --git a/fpga/constraints/constraints-qmtechk7.xdc b/fpga/constraints/constraints-qmtechk7.xdc new file mode 100644 index 000000000..8d91e48b2 --- /dev/null +++ b/fpga/constraints/constraints-qmtechk7.xdc @@ -0,0 +1,243 @@ +# The main clocks are all autogenerated by the Xilinx IP +# mmcm_clkout0 is the clock output of the DDR3 memory interface / 4. +# 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 SPISDCClock -source [get_pins mmcm/clk_out3] -multiply_by 1 -divide_by 1 [get_pins wallypipelinedsoc/uncoregen.uncore/sdc.sdc/SPICLK] + +##### clock ##### +set_property LOC F22 [get_ports default_50mhz_clk] +set_property IOSTANDARD LVCMOS33 [get_ports default_50mhz_clk] + +# Clocks and Resets (adjust to match board) +set_property IOSTANDARD LVCMOS33 [get_ports default_200mhz_clk] +set_property IOSTANDARD LVCMOS33 [get_ports resetn] +set_property IOSTANDARD LVCMOS33 [get_ports south_reset] + +# Clock constraints +create_clock -period 20.000 -name clk_50m [get_ports default_50mhz_clk] +create_clock -period 5.000 -name sys_clk [get_ports sys_clk_i] +create_clock -period 5.000 -name idelay_refclk [get_ports clk_ref_i] +#create_clock -period 5.000 -name mig_clk_200m [get_ports sys_clk_i] + +set_property CLOCK_BUFFER_TYPE BUFG [get_nets wallypipelinedsoc/clk_out3_mmcm] + +# *** don't love this hack. RT: Don't understand why the recomemded input clock is causing a clock routing issue. +set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets default_50mhz_clk] + +##### RVVI Ethernet (not working yet) #### +set_property IOSTANDARD LVCMOS33 [get_ports {phy_txd[*] phy_tx_en}] +set_property PACKAGE_PIN C16 [get_ports {phy_txd[0]}]; +set_property PACKAGE_PIN U24 [get_ports {phy_txd[1]}]; +set_property PACKAGE_PIN A20 [get_ports {phy_txd[2]}]; +set_property PACKAGE_PIN B20 [get_ports {phy_txd[3]}]; +set_property PACKAGE_PIN F20 [get_ports {phy_tx_en}] + + +##### GPI #### +set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 PULLUP true } [get_ports { GPI[0] }] ; # GPIO4 on JP3 +set_property -dict { PACKAGE_PIN D21 IOSTANDARD LVCMOS33 PULLUP true } [get_ports { GPI[1] }] ; # GPIO5 on JP3 +set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { GPI[2] }]; # JP3 GPIO6 +set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { GPI[3] }]; # JP3 GPIO7 +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports {GPI[*]}] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports {GPI[*]}] +set_max_delay -from [get_ports {GPI[*]}] 20.000 + + +##### GPO #### +# User LEDs +set_property -dict { PACKAGE_PIN R26 IOSTANDARD LVCMOS33 } [get_ports { GPO[0] }] ; # LED2 +set_property -dict { PACKAGE_PIN P26 IOSTANDARD LVCMOS33 } [get_ports { GPO[1] }] ; # LED3 +set_property -dict { PACKAGE_PIN N26 IOSTANDARD LVCMOS33 } [get_ports { GPO[2] }] ; # LED4 +# RPI connector pins +set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { GPO[3] }]; +set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { GPO[4] }]; +set_max_delay -to [get_ports {GPO[*]}] 20.000 +set_output_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports {GPO[*]}] +set_output_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports {GPO[*]}] + + + +##### UART ##### +# JP5 is on bank #14 (3.3V) +set_property -dict { PACKAGE_PIN AE22 IOSTANDARD LVCMOS33 } [get_ports { UARTSout }]; #JP5, pin 7 (TX) +set_property -dict { PACKAGE_PIN AF22 IOSTANDARD LVCMOS33 } [get_ports { UARTSin }]; #JP5, pin 8 (RX) +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports UARTSin] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports UARTSin] +set_output_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 0.000 [get_ports UARTSout] +set_output_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 0.000 [get_ports UARTSout] + + +##### reset ##### +#************** reset is inverted +set_property -dict { PACKAGE_PIN V26 IOSTANDARD LVCMOS33 } [get_ports { south_reset }]; # SW2 on the board +set_property -dict { PACKAGE_PIN U26 IOSTANDARD LVCMOS33 } [get_ports { resetn }]; # SW3 on the board + +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 2.000 [get_ports resetn] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 2.000 [get_ports resetn] +set_max_delay -from [get_ports resetn] 20.000 +set_false_path -from [get_ports resetn] + +set_input_delay -clock [get_clocks clk_out3_mmcm] -min -add_delay 2.000 [get_ports south_reset] +set_input_delay -clock [get_clocks clk_out3_mmcm] -max -add_delay 2.000 [get_ports south_reset] +set_max_delay -from [get_ports south_reset] 20.000 +set_false_path -from [get_ports south_reset] + + + +##### SD Card I/O ##### +########################################################################################### +# Digilent micro SD card PMOD (or equivalent) connected to J13 +########################################################################################### +# pin selection +set_property PACKAGE_PIN A24 [get_ports SDCCS] +set_property PACKAGE_PIN B26 [get_ports SDCCmd] +set_property PACKAGE_PIN D26 [get_ports SDCIn] +set_property PACKAGE_PIN F25 [get_ports SDCCLK] +set_property PACKAGE_PIN C26 [get_ports SDCCD] +# NC +set_property PACKAGE_PIN E26 [get_ports SDCWP] +set_property PULLTYPE PULLUP [get_ports {SDCCS SDCIn SDCCD SDCWP SDCCmd}] +set_property IOSTANDARD LVCMOS33 [get_ports {SDCCS SDCCmd SDCIn SDCCLK SDCCD SDCWP}] + +set_output_delay -clock [get_clocks SPISDCClock] -min -add_delay 2.500 [get_ports {SDCCS}] +set_output_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_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}] + + +### ddr3 #### +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[2]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[3]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[4]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[5]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[6]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[7]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[8]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[9]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[10]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[11]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[12]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[13]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[14]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[15]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[15]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[16]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[17]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[18]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[19]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[20]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[21]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[22]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[23]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[24]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[25]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[26]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[27]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[28]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[29]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[30]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[31]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[2]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[3]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[14]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[13]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[12]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[11]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[10]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[9]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[8]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[7]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[6]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[5]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[4]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[3]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[2]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[2]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[0]}] +set_property IOSTANDARD DIFF_SSTL15_DCI [get_ports ddr3_ck_p[0]] +set_property IOSTANDARD DIFF_SSTL15_DCI [get_ports ddr3_ck_n[0]] +set_property IOSTANDARD SSTL15 [get_ports ddr3_ras_n] +set_property IOSTANDARD SSTL15 [get_ports ddr3_cas_n] +set_property IOSTANDARD SSTL15 [get_ports ddr3_we_n] +set_property IOSTANDARD SSTL15 [get_ports ddr3_reset_n] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_cke[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddr3_odt[0]}] +# DDR3 CS not driven in this board +set_property IOSTANDARD SSTL15 [get_ports ddr3_cs_n*] +set_property LOC AC12 [get_ports ddr3_cs_n*] + +set_property INTERNAL_VREF 0.75 [get_iobanks 34] +set_property INTERNAL_VREF 0.90 [get_iobanks 33] + +set_property PACKAGE_PIN AF5 [get_ports ddr3_addr[0]] +set_property PACKAGE_PIN AF2 [get_ports ddr3_addr[1]] +set_property PACKAGE_PIN AD6 [get_ports ddr3_addr[2]] +set_property PACKAGE_PIN AC6 [get_ports ddr3_addr[3]] +set_property PACKAGE_PIN AD4 [get_ports ddr3_addr[4]] +set_property PACKAGE_PIN AB6 [get_ports ddr3_addr[5]] +set_property PACKAGE_PIN AE2 [get_ports ddr3_addr[6]] +set_property PACKAGE_PIN Y5 [get_ports ddr3_addr[7]] +set_property PACKAGE_PIN AA4 [get_ports ddr3_addr[8]] +set_property PACKAGE_PIN AE6 [get_ports ddr3_addr[9]] +set_property PACKAGE_PIN AE3 [get_ports ddr3_addr[10]] +set_property PACKAGE_PIN AD5 [get_ports ddr3_addr[11]] +set_property PACKAGE_PIN AB4 [get_ports ddr3_addr[12]] +set_property PACKAGE_PIN Y6 [get_ports ddr3_addr[13]] + +set_property PACKAGE_PIN AD3 [get_ports ddr3_ba[0]] +set_property PACKAGE_PIN AE1 [get_ports ddr3_ba[1]] +set_property PACKAGE_PIN AE5 [get_ports ddr3_ba[2]] + +set_property PACKAGE_PIN AC4 [get_ports ddr3_cas_n] + +set_property PACKAGE_PIN AB5 [get_ports ddr3_ck_n[0]] +set_property PACKAGE_PIN AA5 [get_ports ddr3_ck_p[0]] +set_property PACKAGE_PIN AD1 [get_ports ddr3_cke[0]] +set_property PACKAGE_PIN V1 [get_ports ddr3_dm[0]] +set_property PACKAGE_PIN V3 [get_ports ddr3_dm[1]] +set_property PACKAGE_PIN W1 [get_ports ddr3_dq[0]] +set_property PACKAGE_PIN V2 [get_ports ddr3_dq[1]] +set_property PACKAGE_PIN Y1 [get_ports ddr3_dq[2]] +set_property PACKAGE_PIN Y3 [get_ports ddr3_dq[3]] +set_property PACKAGE_PIN AC2 [get_ports ddr3_dq[4]] +set_property PACKAGE_PIN Y2 [get_ports ddr3_dq[5]] +set_property PACKAGE_PIN AB2 [get_ports ddr3_dq[6]] +set_property PACKAGE_PIN AA3 [get_ports ddr3_dq[7]] +set_property PACKAGE_PIN U1 [get_ports ddr3_dq[8]] +set_property PACKAGE_PIN V4 [get_ports ddr3_dq[9]] +set_property PACKAGE_PIN U6 [get_ports ddr3_dq[10]] +set_property PACKAGE_PIN W3 [get_ports ddr3_dq[11]] +set_property PACKAGE_PIN V6 [get_ports ddr3_dq[12]] +set_property PACKAGE_PIN U2 [get_ports ddr3_dq[13]] +set_property PACKAGE_PIN U7 [get_ports ddr3_dq[14]] +set_property PACKAGE_PIN U5 [get_ports ddr3_dq[15]] + +set_property PACKAGE_PIN AF3 [get_ports ddr3_odt[0]] +set_property PACKAGE_PIN AC3 [get_ports ddr3_ras_n] +set_property W4 [get_ports ddr3_reset_n] +set_property PACKAGE_PIN AF4 [get_ports ddr3_we_n] + +reset_property IOSTANDARD [get_ports {ddr3_dqs_*[*]}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_dqs_p[*]}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_dqs_n[*]}] +set_property DIFF_TERM TRUE [get_ports {ddr3_dqs_p[*]}] +set_property DIFF_TERM TRUE [get_ports {ddr3_dqs_n[*]}] +set_property DIFF_PAIR ddr3_dqs_p[0] [get_ports {ddr3_dqs_n[0]}] +set_property DIFF_PAIR ddr3_dqs_p[1] [get_ports {ddr3_dqs_n[1]}] +set_property SLEW FAST [get_ports {ddr3_dqs_p[*] ddr3_dqs_n[*]}] +set_property PACKAGE_PIN AC1 [get_ports {ddr3_dqs_n[0]}] +set_property PACKAGE_PIN W5 [get_ports {ddr3_dqs_n[1]}] +set_property PACKAGE_PIN AB1 [get_ports {ddr3_dqs_p[0]}] +set_property PACKAGE_PIN W6 [get_ports {ddr3_dqs_p[1]}] + + +set_max_delay -datapath_only -from [get_pins xlnx_ddr3_c0/u_xlnx_ddr3_mig/u_memc_ui_top_axi/mem_intfc0/ddr_phy_top0/u_ddr_calib_top/init_calib_complete_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 20.000 diff --git a/fpga/generator/Makefile b/fpga/generator/Makefile index 2fbce7f5a..d28dadef3 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -2,7 +2,7 @@ dst := IP all: ArtyA7 -.PHONY: ArtyA7 vcu118 vcu108 genesys2 +.PHONY: ArtyA7 vcu118 vcu108 genesys2 qmtechk7 ArtyA7: export XILINX_PART := xc7a100tcsg324-1 ArtyA7: export XILINX_BOARD := digilentinc.com:arty-a7-100:part0:1.1 @@ -32,13 +32,21 @@ genesys2: export SYSTEMCLOCK := 40000000 genesys2: export MAXSDCCLOCK := 10000000 genesys2: FPGA_GENESYS2 +qmtechk7: export XILINX_PART := xc7k325tffg676-1 +# Not really a board from Xilinx +qmtechk7: export XILINX_BOARD := qmtechk7 +qmtechk7: export board := qmtechk7 +qmtechk7: export SYSTEMCLOCK := 40000000 +qmtechk7: export MAXSDCCLOCK := 10000000 +qmtechk7: FPGA_QMTECHK7 + # variables computed from config EXT_MEM_BASE = $(shell grep 'EXT_MEM_BASE' ../../config/deriv/fpga$(board)/config.vh | sed 's/.*=.*h\([[:alnum:]]*\);/0x\1/g') EXT_MEM_RANGE = $(shell grep 'EXT_MEM_RANGE' ../../config/deriv/fpga$(board)/config.vh | sed 's/.*=.*h\([[:alnum:]]*\);/\1/g' | sed 's/\(.*\)/base=16;\1+1/g' | bc | sed 's/\(.*\)/0x\1/g') -.PHONY: FPGA_Arty FPGA_VCU +.PHONY: FPGA_Arty FPGA_VCU FPGA_QMTECHK7 FPGA_Arty: PreProcessFiles IP_Arty zsbl vivado -mode tcl -source wally.tcl 2>&1 | tee wally.log FPGA_VCU: PreProcessFiles IP_VCU zsbl @@ -47,8 +55,11 @@ FPGA_VCU: PreProcessFiles IP_VCU zsbl FPGA_GENESYS2: PreProcessFiles IP_GENESYS2 zsbl vivado -mode tcl -source wally.tcl 2>&1 | tee wally.log +FPGA_QMTECHK7: PreProcessFiles IP_QMTECHK7 zsbl + vivado -mode tcl -source wally.tcl 2>&1 | tee wally.log + # Generate IP Blocks -.PHONY: IP_Arty IP_VCU +.PHONY: IP_Arty IP_VCU IP_QMTECHK7 IP_VCU: $(dst)/sysrst.log \ MEM_VCU \ $(dst)/clkconverter.log \ @@ -65,8 +76,14 @@ IP_GENESYS2: $(dst)/sysrst.log \ $(dst)/clkconverter.log \ $(dst)/ahbaxibridge.log +IP_QMTECHK7: $(dst)/sysrst.log \ + MEM_QMTECHK7 \ + $(dst)/mmcm-qmtechk7.log \ + $(dst)/clkconverter.log \ + $(dst)/ahbaxibridge.log + # Generate Memory IP Blocks -.PHONY: MEM_VCU MEM_Arty +.PHONY: MEM_VCU MEM_Arty MEM_QMTECHK7 MEM_VCU: $(MAKE) $(dst)/ddr4-$(board).log MEM_Arty: @@ -75,6 +92,9 @@ MEM_Arty: MEM_GENESYS2: $(MAKE) $(dst)/ddr3-$(board).log +MEM_QMTECHK7: + $(MAKE) $(dst)/ddr3-$(board).log + # Copy files and make necessary modifications .PHONY: PreProcessFiles PreProcessFiles: diff --git a/fpga/generator/ahbaxibridge.tcl b/fpga/generator/ahbaxibridge.tcl index e41eed6ce..f0771f459 100644 --- a/fpga/generator/ahbaxibridge.tcl +++ b/fpga/generator/ahbaxibridge.tcl @@ -5,7 +5,7 @@ set boardName $::env(XILINX_BOARD) set ipName ahbaxibridge create_project $ipName . -force -part $partNumber -if {$boardName!="ArtyA7"} { +if {$boardName!="ArtyA7" && $boardName!="qmtechk7"} { set_property board_part $boardName [current_project] } diff --git a/fpga/generator/clkconverter.tcl b/fpga/generator/clkconverter.tcl index e57430300..2d63dc3c0 100644 --- a/fpga/generator/clkconverter.tcl +++ b/fpga/generator/clkconverter.tcl @@ -7,7 +7,7 @@ set boardName $::env(XILINX_BOARD) set ipName clkconverter create_project $ipName . -force -part $partNumber -if {$boardName!="ArtyA7"} { +if {$boardName!="ArtyA7" && $boardName!="qmtechk7"} { set_property board_part $boardName [current_project] } diff --git a/fpga/generator/ddr3-qmtechk7.tcl b/fpga/generator/ddr3-qmtechk7.tcl new file mode 100644 index 000000000..1138683dd --- /dev/null +++ b/fpga/generator/ddr3-qmtechk7.tcl @@ -0,0 +1,20 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) + +set ipName ddr3 + +create_project $ipName . -force -part $partNumber + +create_ip -name mig_7series -vendor xilinx.com -library ip -module_name $ipName + +exec mkdir -p IP/$ipName.srcs/sources_1/ip/$ipName +exec cp ../xlnx_ddr3-qmtechk7-mig.prj $ipName.srcs/sources_1/ip/$ipName/xlnx_ddr3-qmtechk7-mig.prj + +set_property -dict [list CONFIG.XML_INPUT_FILE {xlnx_ddr3-qmtechk7-mig.prj} CONFIG.RESET_BOARD_INTERFACE {Custom} CONFIG.MIG_DONT_TOUCH_PARAM {Custom} CONFIG.BOARD_MIG_PARAM {Custom}] [get_ips $ipName] + +generate_target {instantiation_template} [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +launch_run -jobs 8 ${ipName}_synth_1 +wait_on_run ${ipName}_synth_1 + diff --git a/fpga/generator/mmcm-qmtechk7.tcl b/fpga/generator/mmcm-qmtechk7.tcl new file mode 100644 index 000000000..03f6fdb79 --- /dev/null +++ b/fpga/generator/mmcm-qmtechk7.tcl @@ -0,0 +1,35 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) +set SYSTEMCLOCK $::env(SYSTEMCLOCK) +set ipName mmcm + +set SYSTEMCLOCK_MHz [expr $SYSTEMCLOCK/1000000.0] + +create_project $ipName . -force -part $partNumber + +create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName + +# Now configure the IP +set_property -dict [list \ + CONFIG.PRIM_IN_FREQ {50.000} \ + CONFIG.PRIM_SOURCE {Single_ended_clock_capable_pin} \ + CONFIG.USE_RESET {false} \ + CONFIG.USE_LOCKED {true} \ + CONFIG.NUM_OUT_CLKS {4} \ + CONFIG.CLKOUT1_USED {true} \ + CONFIG.CLKOUT2_USED {true} \ + CONFIG.CLKOUT3_USED {true} \ + CONFIG.CLKOUT4_USED {true} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {200} \ + CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200} \ + CONFIG.CLKOUT3_REQUESTED_OUT_FREQ $SYSTEMCLOCK_MHz \ + CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {25} \ + CONFIG.CLKIN1_JITTER_PS {10.0} \ +] [get_ips $ipName] + +# Regenerate and synthesize the IP +generate_target {instantiation_template} [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +launch_run -jobs 8 ${ipName}_synth_1 +wait_on_run ${ipName}_synth_1 \ No newline at end of file diff --git a/fpga/generator/sysrst.tcl b/fpga/generator/sysrst.tcl index 7c6634bd9..cf38527cf 100644 --- a/fpga/generator/sysrst.tcl +++ b/fpga/generator/sysrst.tcl @@ -7,7 +7,7 @@ set boardName $::env(XILINX_BOARD) set ipName sysrst create_project $ipName . -force -part $partNumber -if {$boardName!="ArtyA7"} { +if {$boardName!="ArtyA7" && $boardName!="qmtechk7" } { set_property board_part $boardName [current_project] } diff --git a/fpga/generator/wally.tcl b/fpga/generator/wally.tcl index 65241afc6..916ed8bed 100644 --- a/fpga/generator/wally.tcl +++ b/fpga/generator/wally.tcl @@ -18,7 +18,7 @@ set board $::env(board) set ipName WallyFPGA create_project $ipName . -force -part $partNumber -if {$boardName!="ArtyA7"} { +if {$boardName!="ArtyA7" && $boardName!="qmtechk7" } { set_property board_part $boardName [current_project] } @@ -30,6 +30,8 @@ if {$board=="ArtyA7"} { add_files {../src/fpgaTopArtyA7.sv} } elseif {$board=="genesys2"} { add_files {../src/fpgaTopGenesys2.sv} +} elseif {$board=="qmtechk7"} { + add_files {../src/fpgaTopQmtechk7.sv} } else { add_files {../src/fpgaTop.sv} } @@ -39,7 +41,7 @@ import_ip IP/sysrst.srcs/sources_1/ip/sysrst/sysrst.xci import_ip IP/ahbaxibridge.srcs/sources_1/ip/ahbaxibridge/ahbaxibridge.xci import_ip IP/clkconverter.srcs/sources_1/ip/clkconverter/clkconverter.xci -if {$board=="ArtyA7" || $board=="genesys2"} { +if {$board=="ArtyA7" || $board=="genesys2" || $board=="qmtechk7"} { import_ip IP/ddr3.srcs/sources_1/ip/ddr3/ddr3.xci import_ip IP/mmcm.srcs/sources_1/ip/mmcm/mmcm.xci } else { @@ -67,7 +69,7 @@ report_compile_order -constraints > reports/compile_order.rpt #synth_design -rtl -name rtl_1 -flatten_hierarchy none # apply timing constraint after elaboration -if {$board=="ArtyA7" || $board=="genesys2"} { +if {$board=="ArtyA7" || $board=="genesys2" || $board=="qmtechk7"} { add_files -fileset constrs_1 -norecurse ../constraints/constraints-$board.xdc set_property PROCESSING_ORDER NORMAL [get_files ../constraints/constraints-$board.xdc] } else { @@ -103,6 +105,8 @@ if {$board=="ArtyA7"} { source ../constraints/small-debug-wfi.xdc } elseif {$board=="genesys2"} { source ../constraints/small-debug.xdc +} elseif {$board=="qmtechk7"} { + source ../constraints/small-debug.xdc } else { #source ../constraints/vcu-small-debug.xdc #source ../constraints/small-debug.xdc diff --git a/fpga/generator/xlnx_ddr3-qmtechk7-mig.prj b/fpga/generator/xlnx_ddr3-qmtechk7-mig.prj new file mode 100644 index 000000000..5c358f61b --- /dev/null +++ b/fpga/generator/xlnx_ddr3-qmtechk7-mig.prj @@ -0,0 +1,154 @@ + + + + + + + + ddr3 + + 1 + + 1 + + OFF + + 1024 + + OFF + + Enabled + + xc7k325t-ffg676/-1 + + 4.2 + + No Buffer + + Use System Clock + + ACTIVE LOW + + FALSE + + 1 + + 50 Ohms + + 0 + + + DDR3_SDRAM/Components/MT41K128M16XX-15E + 2500 + 1.8V + 4:1 + 200 + 0 + 800 + 1.000 + 1 + 1 + 1 + 1 + 16 + 1 + 1 + Disabled + Normal + 4 + FALSE + + 14 + 10 + 3 + 1.5V + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Fixed + Sequential + 6 + Normal + No + Slow Exit + Enable + RZQ/6 + Disable + Disable + RZQ/6 + 0 + Disabled + Enabled + Output Buffer Enabled + Full Array + 5 + Enabled + Normal + Dynamic ODT off + AXI + + RD_PRI_REG + 28 + 64 + 4 + 0 + + + + + diff --git a/fpga/src/fpgaTopQmtechk7.sv b/fpga/src/fpgaTopQmtechk7.sv new file mode 100644 index 000000000..f5c151199 --- /dev/null +++ b/fpga/src/fpgaTopQmtechk7.sv @@ -0,0 +1,636 @@ +/////////////////////////////////////////// +// fpgaTopQmtechk7.sv +// +// Written: jcschroeder@gmail.com 14.12.2025 +// Modified: +// +// Purpose: This is a top level for the fpga's implementation of wally. +// Instantiates wallysoc, ddr3, abh lite to axi converters, pll, etc +// +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2025 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +`include "config.vh" + +import cvw::*; + +module fpgaTop #(parameter logic RVVI_SYNTH_SUPPORTED = 0) + (input logic default_50mhz_clk, + input logic resetn, + input logic south_reset, + + // GPIO signals + input logic [3:0] GPI, + output logic [4:0] GPO, + + // UART Signals + input logic UARTSin, + output logic UARTSout, + + // SDC Signals connecting to an SPI peripheral + input logic SDCIn, + output logic SDCCLK, + output logic SDCCmd, + output logic SDCCS, + input logic SDCCD, + input logic SDCWP, + /* + * Ethernet: 100BASE-T MII + */ + // Taken from Genesys 2 (RVVI support is missing) + //output logic phy_ref_clk, // *** add back in when we add rvvi + input logic phy_rx_clk, + input logic [3:0] phy_rxd, + input logic phy_rxctl, + input logic phy_tx_clk, + output logic [3:0] phy_txd, + output logic phy_tx_en, + //output logic phy_reset_n, + + inout logic [15:0] ddr3_dq, + inout logic [1:0] ddr3_dqs_n, + inout logic [1:0] ddr3_dqs_p, + output logic [13:0] ddr3_addr, + output logic [2:0] ddr3_ba, + output logic ddr3_ras_n, + output logic ddr3_cas_n, + output logic ddr3_we_n, + output logic ddr3_reset_n, + output logic [0:0] ddr3_ck_p, + output logic [0:0] ddr3_ck_n, + output logic [0:0] ddr3_cke, + output logic [0:0] ddr3_cs_n, + output logic [1:0] ddr3_dm, + output logic [0:0] ddr3_odt + ); + + // MMCM Signals + logic CPUCLK; + logic c0_ddr4_ui_clk_sync_rst; + logic bus_struct_reset; + logic peripheral_reset; + logic interconnect_aresetn; + logic peripheral_aresetn; + logic mb_reset; + + // AHB Signals from Wally + logic HCLKOpen; + logic HRESETnOpen; + logic [63:0] HRDATAEXT; + logic HREADYEXT; + logic HRESPEXT; + logic HSELEXT; + logic [55:0] HADDR; + logic [63:0] HWDATA; + logic [64/8-1:0] HWSTRB; + logic HWRITE; + logic [2:0] HSIZE; + logic [2:0] HBURST; + logic [1:0] HTRANS; + logic HREADY; + logic [3:0] HPROT; + logic HMASTLOCK; + + // GPIO Signals + logic [31:0] GPIOIN, GPIOOUT, GPIOEN; + + // AHB to AXI Bridge Signals + logic [3:0] m_axi_awid; + logic [7:0] m_axi_awlen; + logic [2:0] m_axi_awsize; + logic [1:0] m_axi_awburst; + logic [3:0] m_axi_awcache; + logic [31:0] m_axi_awaddr; + logic [2:0] m_axi_awprot; + logic m_axi_awvalid; + logic m_axi_awready; + logic m_axi_awlock; + logic [63:0] m_axi_wdata; + logic [7:0] m_axi_wstrb; + logic m_axi_wlast; + logic m_axi_wvalid; + logic m_axi_wready; + logic [3:0] m_axi_bid; + logic [1:0] m_axi_bresp; + logic m_axi_bvalid; + logic m_axi_bready; + logic [3:0] m_axi_arid; + logic [7:0] m_axi_arlen; + logic [2:0] m_axi_arsize; + logic [1:0] m_axi_arburst; + logic [2:0] m_axi_arprot; + logic [3:0] m_axi_arcache; + logic m_axi_arvalid; + logic [31:0] m_axi_araddr; + logic m_axi_arlock; + logic m_axi_arready; + logic [3:0] m_axi_rid; + logic [63:0] m_axi_rdata; + logic [1:0] m_axi_rresp; + logic m_axi_rvalid; + logic m_axi_rlast; + logic m_axi_rready; + + // AXI Signals going out of Clock Converter + logic [3:0] BUS_axi_arregion; + logic [3:0] BUS_axi_arqos; + logic [3:0] BUS_axi_awregion; + logic [3:0] BUS_axi_awqos; + logic [3:0] BUS_axi_awid; + logic [7:0] BUS_axi_awlen; + logic [2:0] BUS_axi_awsize; + logic [1:0] BUS_axi_awburst; + logic [3:0] BUS_axi_awcache; + logic [31:0] BUS_axi_awaddr; + logic [2:0] BUS_axi_awprot; + logic BUS_axi_awvalid; + logic BUS_axi_awready; + logic BUS_axi_awlock; + logic [63:0] BUS_axi_wdata; + logic [7:0] BUS_axi_wstrb; + logic BUS_axi_wlast; + logic BUS_axi_wvalid; + logic BUS_axi_wready; + logic [3:0] BUS_axi_bid; + logic [1:0] BUS_axi_bresp; + logic BUS_axi_bvalid; + logic BUS_axi_bready; + logic [3:0] BUS_axi_arid; + logic [7:0] BUS_axi_arlen; + logic [2:0] BUS_axi_arsize; + logic [1:0] BUS_axi_arburst; + logic [2:0] BUS_axi_arprot; + logic [3:0] BUS_axi_arcache; + logic BUS_axi_arvalid; + logic [31:0] BUS_axi_araddr; + logic BUS_axi_arlock; + logic BUS_axi_arready; + logic [3:0] BUS_axi_rid; + logic [63:0] BUS_axi_rdata; + logic [1:0] BUS_axi_rresp; + logic BUS_axi_rvalid; + logic BUS_axi_rlast; + logic BUS_axi_rready; + + logic BUSCLK; + logic sdio_reset_open; + + logic c0_init_calib_complete; + logic dbg_clk; + logic [511 : 0] dbg_bus; + logic ui_clk_sync_rst; + + logic clk200i; + logic clk200; + + logic app_sr_active; + logic app_ref_ack; + logic app_zq_ack; + logic mmcm_locked; + logic [11:0] device_temp; + logic mmcm1_locked; + // ibufg + bufg for single ended input clock + wire clk_50m_ibufg; + wire clk_50m_bufg; + +(* mark_debug = "true" *) logic RVVIStall; + + assign GPIOIN = {25'b0, SDCCD, SDCWP, 1'b0, GPI}; + 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]; + + + // QMTech board has single-ended clock and IBUFG+BUFG is not automatically 'inferred'. + // The "extra" buffers add negligible latency (<1ns) while ensuring reliable operation. + IBUFG ibuf_50m ( + .I(default_50mhz_clk), // Connect to physical pin + .O(clk_50m_ibufg) // Isolated clock signal + ); + + BUFG bufg_50m ( + .I(clk_50m_ibufg), // Direct from pin F22 + .O(clk_50m_bufg) // Buffered clock + ); + + // mmcm + + // the ddr3 mig7 requires 2 input clocks + // 1. sys clock which is 167 MHz = ddr3 clock / 4 + // 2. a second clock which is 200 MHz + // Wally requires a slower clock. At this point I don't know what speed the atrix 7 will run so I'm initially targeting 25Mhz. + // the mig will output a clock at 1/4 the sys clock or 41Mhz which might work with wally so we may be able to simplify the logic a lot. + logic phy_ref_clk; // *** fix when we add rvvi + mmcm mmcm(.clk_out1(clk200i), + .clk_out2(clk200), + .clk_out3(CPUCLK), + .clk_out4(phy_ref_clk), + .locked(mmcm1_locked), + // Drive MMCM with bufg output + .clk_in1(clk_50m_bufg)); + + + + // reset controller XILINX IP + sysrst sysrst + (.slowest_sync_clk(CPUCLK), + .ext_reset_in(1'b0), + .aux_reset_in(~south_reset), + .mb_debug_sys_rst(1'b0), + .dcm_locked(c0_init_calib_complete), + .mb_reset(mb_reset), //open + .bus_struct_reset(bus_struct_reset), + .peripheral_reset(peripheral_reset), //open + .interconnect_aresetn(interconnect_aresetn), //open + .peripheral_aresetn(peripheral_aresetn)); + + `include "parameter-defs.vh" + + // Wally + wallypipelinedsoc #(P) + wallypipelinedsoc(.clk(CPUCLK), .reset_ext(bus_struct_reset), .reset(), + .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, + .HCLK(HCLKOpen), .HRESETn(HRESETnOpen), + .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, + .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), + .GPIOIN, .GPIOOUT, .GPIOEN, + .UARTSin, .UARTSout, .SDCIn, .SDCCmd, .SDCCS(SDCCSin), .SDCCLK, .ExternalStall(RVVIStall)); + + + // ahb lite to axi bridge + ahbaxibridge ahbaxibridge + (.s_ahb_hclk(CPUCLK), + .s_ahb_hresetn(peripheral_aresetn), + .s_ahb_hsel(HSELEXT), + .s_ahb_haddr(HADDR[31:0]), + .s_ahb_hprot(HPROT), + .s_ahb_htrans(HTRANS), + .s_ahb_hsize(HSIZE), + .s_ahb_hwrite(HWRITE), + .s_ahb_hburst(HBURST), + .s_ahb_hwdata(HWDATA), + .s_ahb_hready_out(HREADYEXT), + .s_ahb_hready_in(HREADY), + .s_ahb_hrdata(HRDATAEXT), + .s_ahb_hresp(HRESPEXT), + .m_axi_awid(m_axi_awid), + .m_axi_awlen(m_axi_awlen), + .m_axi_awsize(m_axi_awsize), + .m_axi_awburst(m_axi_awburst), + .m_axi_awcache(m_axi_awcache), + .m_axi_awaddr(m_axi_awaddr), + .m_axi_awprot(m_axi_awprot), + .m_axi_awvalid(m_axi_awvalid), + .m_axi_awready(m_axi_awready), + .m_axi_awlock(m_axi_awlock), + .m_axi_wdata(m_axi_wdata), + .m_axi_wstrb(m_axi_wstrb), + .m_axi_wlast(m_axi_wlast), + .m_axi_wvalid(m_axi_wvalid), + .m_axi_wready(m_axi_wready), + .m_axi_bid(m_axi_bid), + .m_axi_bresp(m_axi_bresp), + .m_axi_bvalid(m_axi_bvalid), + .m_axi_bready(m_axi_bready), + .m_axi_arid(m_axi_arid), + .m_axi_arlen(m_axi_arlen), + .m_axi_arsize(m_axi_arsize), + .m_axi_arburst(m_axi_arburst), + .m_axi_arprot(m_axi_arprot), + .m_axi_arcache(m_axi_arcache), + .m_axi_arvalid(m_axi_arvalid), + .m_axi_araddr(m_axi_araddr), + .m_axi_arlock(m_axi_arlock), + .m_axi_arready(m_axi_arready), + .m_axi_rid(m_axi_rid), + .m_axi_rdata(m_axi_rdata), + .m_axi_rresp(m_axi_rresp), + .m_axi_rvalid(m_axi_rvalid), + .m_axi_rlast(m_axi_rlast), + .m_axi_rready(m_axi_rready)); + + // AXI Clock Converter + clkconverter clkconverter + (.s_axi_aclk(CPUCLK), + .s_axi_aresetn(peripheral_aresetn), + .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(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(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), + .m_axi_awid(BUS_axi_awid), + .m_axi_awlen(BUS_axi_awlen), + .m_axi_awsize(BUS_axi_awsize), + .m_axi_awburst(BUS_axi_awburst), + .m_axi_awcache(BUS_axi_awcache), + .m_axi_awaddr(BUS_axi_awaddr), + .m_axi_awprot(BUS_axi_awprot), + .m_axi_awregion(BUS_axi_awregion), + .m_axi_awqos(BUS_axi_awqos), + .m_axi_awvalid(BUS_axi_awvalid), + .m_axi_awready(BUS_axi_awready), + .m_axi_awlock(BUS_axi_awlock), + .m_axi_wdata(BUS_axi_wdata), + .m_axi_wstrb(BUS_axi_wstrb), + .m_axi_wlast(BUS_axi_wlast), + .m_axi_wvalid(BUS_axi_wvalid), + .m_axi_wready(BUS_axi_wready), + .m_axi_bid(BUS_axi_bid), + .m_axi_bresp(BUS_axi_bresp), + .m_axi_bvalid(BUS_axi_bvalid), + .m_axi_bready(BUS_axi_bready), + .m_axi_arid(BUS_axi_arid), + .m_axi_arlen(BUS_axi_arlen), + .m_axi_arsize(BUS_axi_arsize), + .m_axi_arburst(BUS_axi_arburst), + .m_axi_arprot(BUS_axi_arprot), + .m_axi_arregion(BUS_axi_arregion), + .m_axi_arqos(BUS_axi_arqos), + .m_axi_arcache(BUS_axi_arcache), + .m_axi_arvalid(BUS_axi_arvalid), + .m_axi_araddr(BUS_axi_araddr), + .m_axi_arlock(BUS_axi_arlock), + .m_axi_arready(BUS_axi_arready), + .m_axi_rid(BUS_axi_rid), + .m_axi_rdata(BUS_axi_rdata), + .m_axi_rresp(BUS_axi_rresp), + .m_axi_rvalid(BUS_axi_rvalid), + .m_axi_rlast(BUS_axi_rlast), + .m_axi_rready(BUS_axi_rready)); + + // DDR3 Controller + ddr3 ddr3 + ( + // ddr3 I/O + .ddr3_dq(ddr3_dq), + .ddr3_dqs_n(ddr3_dqs_n), + .ddr3_dqs_p(ddr3_dqs_p), + .ddr3_addr(ddr3_addr), + .ddr3_ba(ddr3_ba), + .ddr3_ras_n(ddr3_ras_n), + .ddr3_cas_n(ddr3_cas_n), + .ddr3_we_n(ddr3_we_n), + .ddr3_reset_n(ddr3_reset_n), + .ddr3_ck_p(ddr3_ck_p), + .ddr3_ck_n(ddr3_ck_n), + .ddr3_cke(ddr3_cke), + // ddr3_cs_n: always pulled down in this board? + .ddr3_dm(ddr3_dm), + .ddr3_odt(ddr3_odt), + + // clk_ref_i: Apparently, when both are 200 MHz same clock can be used as clock input for both (including IDELAYCTRL) + //.sys_clk_i(clk200i), + .sys_clk_i(clk200), + //.clk_ref_i(clk200), // When using 'Use System Clock' in MIG this connection is not needed? + + .ui_clk(BUSCLK), + .ui_clk_sync_rst(ui_clk_sync_rst), + .aresetn(resetn), + .sys_rst(resetn), // omg. this is active low?!?!?? + .mmcm_locked(mmcm_locked), + + .app_sr_req(1'b0), // reserved command + .app_ref_req(1'b0), // refresh command + .app_zq_req(1'b0), // recalibrate command + .app_sr_active(app_sr_active), // reserved response + .app_ref_ack(app_ref_ack), // refresh ack + .app_zq_ack(app_zq_ack), // recalibrate ack + + // axi + .s_axi_awid(BUS_axi_awid), + .s_axi_awaddr(BUS_axi_awaddr[27:0]), + .s_axi_awlen(BUS_axi_awlen), + .s_axi_awsize(BUS_axi_awsize), + .s_axi_awburst(BUS_axi_awburst), + .s_axi_awlock(BUS_axi_awlock), + .s_axi_awcache(BUS_axi_awcache), + .s_axi_awprot(BUS_axi_awprot), + .s_axi_awqos(BUS_axi_awqos), + .s_axi_awvalid(BUS_axi_awvalid), + .s_axi_awready(BUS_axi_awready), + .s_axi_wdata(BUS_axi_wdata), + .s_axi_wstrb(BUS_axi_wstrb), + .s_axi_wlast(BUS_axi_wlast), + .s_axi_wvalid(BUS_axi_wvalid), + .s_axi_wready(BUS_axi_wready), + .s_axi_bready(BUS_axi_bready), + .s_axi_bid(BUS_axi_bid), + .s_axi_bresp(BUS_axi_bresp), + .s_axi_bvalid(BUS_axi_bvalid), + .s_axi_arid(BUS_axi_arid), + .s_axi_araddr(BUS_axi_araddr[27:0]), + .s_axi_arlen(BUS_axi_arlen), + .s_axi_arsize(BUS_axi_arsize), + .s_axi_arburst(BUS_axi_arburst), + .s_axi_arlock(BUS_axi_arlock), + .s_axi_arcache(BUS_axi_arcache), + .s_axi_arprot(BUS_axi_arprot), + .s_axi_arqos(BUS_axi_arqos), + .s_axi_arvalid(BUS_axi_arvalid), + .s_axi_arready(BUS_axi_arready), + .s_axi_rready(BUS_axi_rready), + .s_axi_rlast(BUS_axi_rlast), + .s_axi_rvalid(BUS_axi_rvalid), + .s_axi_rresp(BUS_axi_rresp), + .s_axi_rid(BUS_axi_rid), + .s_axi_rdata(BUS_axi_rdata), + + .init_calib_complete(c0_init_calib_complete), + .device_temp(device_temp)); + + (* mark_debug = "true" *) logic IlaTrigger; + + + if(RVVI_SYNTH_SUPPORTED) begin : rvvi_synth + localparam MAX_CSRS = 3; + localparam TOTAL_CSRS = 36; + localparam [31:0] RVVI_INIT_TIME_OUT = 32'd100000000; + localparam [31:0] RVVI_PACKET_DELAY = 32'd400; + + // pipeline controls + logic StallE, StallM, StallW, FlushE, FlushM, FlushW; + // required + logic [P.XLEN-1:0] PCM; + logic InstrValidM; + logic [31:0] InstrRawD; + logic [63:0] Mcycle, Minstret; + logic TrapM; + logic [1:0] PrivilegeModeW; + // registers gpr and fpr + logic GPRWen, FPRWen; + logic [4:0] GPRAddr, FPRAddr; + logic [P.XLEN-1:0] GPRValue, FPRValue; + logic [P.XLEN-1:0] CSRArray [TOTAL_CSRS-1:0]; + + logic valid; + logic [72+(5*P.XLEN) + MAX_CSRS*(P.XLEN+16)-1:0] rvvi; + + assign StallE = fpgaTop.wallypipelinedsoc.core.StallE; + assign StallM = fpgaTop.wallypipelinedsoc.core.StallM; + assign StallW = fpgaTop.wallypipelinedsoc.core.StallW; + assign FlushE = fpgaTop.wallypipelinedsoc.core.FlushE; + assign FlushM = fpgaTop.wallypipelinedsoc.core.FlushM; + assign FlushW = fpgaTop.wallypipelinedsoc.core.FlushW; + assign InstrValidM = fpgaTop.wallypipelinedsoc.core.ieu.InstrValidM; + assign InstrRawD = fpgaTop.wallypipelinedsoc.core.ifu.InstrRawD; + assign PCM = fpgaTop.wallypipelinedsoc.core.ifu.PCM; + assign Mcycle = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0]; + assign Minstret = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign TrapM = fpgaTop.wallypipelinedsoc.core.TrapM; + assign PrivilegeModeW = fpgaTop.wallypipelinedsoc.core.priv.priv.privmode.PrivilegeModeW; + assign GPRAddr = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.a3; + assign GPRWen = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.we3; + assign GPRValue = fpgaTop.wallypipelinedsoc.core.ieu.dp.regf.wd3; + assign FPRAddr = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.a4; + assign FPRWen = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.we4; + assign FPRValue = fpgaTop.wallypipelinedsoc.core.fpu.fpu.fregfile.wd4; + + assign CSRArray[0] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUS_REGW; // 12'h300 + assign CSRArray[1] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSTATUSH_REGW; // 12'h310 + assign CSRArray[2] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVEC_REGW; // 12'h305 + assign CSRArray[3] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEPC_REGW; // 12'h341 + assign CSRArray[4] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTEREN_REGW; // 12'h306 + assign CSRArray[5] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW; // 12'h320 + assign CSRArray[6] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MEDELEG_REGW; // 12'h302 + assign CSRArray[7] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h303 + assign CSRArray[8] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW; // 12'h344 + assign CSRArray[9] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW; // 12'h304 + assign CSRArray[10] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MISA_REGW; // 12'h301 + assign CSRArray[11] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MENVCFG_REGW; // 12'h30A + assign CSRArray[12] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MHARTID_REGW; // 12'hF14 + assign CSRArray[13] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MSCRATCH_REGW; // 12'h340 + assign CSRArray[14] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MCAUSE_REGW; // 12'h342 + assign CSRArray[15] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MTVAL_REGW; // 12'h343 + assign CSRArray[16] = 0; // 12'hF11 + assign CSRArray[17] = 0; // 12'hF12 + assign CSRArray[18] = {{P.XLEN-12{1'b0}}, 12'h100}; //P.XLEN'h100; // 12'hF13 + assign CSRArray[19] = 0; // 12'hF15 + assign CSRArray[20] = 0; // 12'h34A + // supervisor CSRs + assign CSRArray[21] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSTATUS_REGW; // 12'h100 + assign CSRArray[22] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIE_REGW & 12'h222; // 12'h104 + assign CSRArray[23] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVEC_REGW; // 12'h105 + assign CSRArray[24] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SEPC_REGW; // 12'h141 + assign CSRArray[25] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCOUNTEREN_REGW; // 12'h106 + assign CSRArray[26] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SENVCFG_REGW; // 12'h10A + assign CSRArray[27] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SATP_REGW; // 12'h180 + assign CSRArray[28] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW; // 12'h140 + assign CSRArray[29] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STVAL_REGW; // 12'h143 + assign CSRArray[30] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW; // 12'h142 + assign CSRArray[31] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIP_REGW & 12'h222 & fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrm.MIDELEG_REGW; // 12'h144 + assign CSRArray[32] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csrs.csrs.STIMECMP_REGW; // 12'h14D + // user CSRs + assign CSRArray[33] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW; // 12'h001 + assign CSRArray[34] = fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW; // 12'h002 + assign CSRArray[35] = {fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FRM_REGW, fpgaTop.wallypipelinedsoc.core.priv.priv.csr.csru.csru.FFLAGS_REGW}; // 12'h003 + + rvvisynth #(P, MAX_CSRS) rvvisynth(.clk(CPUCLK), .reset(bus_struct_reset), .StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, + .PCM, .InstrValidM, .InstrRawD, .Mcycle, .Minstret, .TrapM, + .PrivilegeModeW, .GPRWen, .FPRWen, .GPRAddr, .FPRAddr, .GPRValue, .FPRValue, .CSRArray, + .valid, .rvvi); + + // axi 4 write data channel + logic [31:0] RvviAxiWdata; + logic [3:0] RvviAxiWstrb; + logic RvviAxiWlast; + logic RvviAxiWvalid; + logic RvviAxiWready; + + logic [31:0] RvviAxiRdata; + logic [3:0] RvviAxiRstrb; + logic RvviAxiRlast; + logic RvviAxiRvalid; + + logic tx_error_underflow, tx_fifo_overflow, tx_fifo_bad_frame, tx_fifo_good_frame, rx_error_bad_frame; + logic rx_error_bad_fcs, rx_fifo_overflow, rx_fifo_bad_frame, rx_fifo_good_frame; + + packetizer #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) packetizer(.rvvi, .valid, .m_axi_aclk(CPUCLK), .m_axi_aresetn(~bus_struct_reset), .RVVIStall, + .RvviAxiWdata, .RvviAxiWstrb, .RvviAxiWlast, .RvviAxiWvalid, .RvviAxiWready); + + eth_mac_mii_fifo #(.TARGET("XILINX"), .CLOCK_INPUT_STYLE("BUFG"), .AXIS_DATA_WIDTH(32), .TX_FIFO_DEPTH(1024)) ethernet(.rst(bus_struct_reset), .logic_clk(CPUCLK), .logic_rst(bus_struct_reset), + .tx_axis_tdata(RvviAxiWdata), .tx_axis_tkeep(RvviAxiWstrb), .tx_axis_tvalid(RvviAxiWvalid), .tx_axis_tready(RvviAxiWready), + .tx_axis_tlast(RvviAxiWlast), .tx_axis_tuser('0), .rx_axis_tdata(RvviAxiRdata), + .rx_axis_tkeep(RvviAxiRstrb), .rx_axis_tvalid(RvviAxiRvalid), .rx_axis_tready(1'b1), + .rx_axis_tlast(RvviAxiRlast), .rx_axis_tuser(), + + .mii_rx_clk(phy_rx_clk), + .mii_rxd(phy_rxd), + .mii_rx_dv(phy_rx_dv), + .mii_rx_er(phy_rx_er), + .mii_tx_clk(phy_tx_clk), + .mii_txd(phy_txd), + .mii_tx_en(phy_tx_en), + .mii_tx_er(), + + // status + .tx_error_underflow, .tx_fifo_overflow, .tx_fifo_bad_frame, .tx_fifo_good_frame, .rx_error_bad_frame, + .rx_error_bad_fcs, .rx_fifo_overflow, .rx_fifo_bad_frame, .rx_fifo_good_frame, + .cfg_ifg(8'd12), .cfg_tx_enable(1'b1), .cfg_rx_enable(1'b1) + ); + + triggergen triggergen(.clk(CPUCLK), .reset(bus_struct_reset), .RvviAxiRdata, + .RvviAxiRstrb, .RvviAxiRlast, .RvviAxiRvalid, .IlaTrigger); + end else begin // if (P.RVVI_SYNTH_SUPPORTED) + assign IlaTrigger = '0; + assign RVVIStall = '0; + end + + //assign phy_reset_n = ~bus_struct_reset; + //assign phy_reset_n = ~1'b0; + +endmodule diff --git a/linux/devicetree/wally-qmtechk7.dts b/linux/devicetree/wally-qmtechk7.dts new file mode 100644 index 000000000..cb1b8f053 --- /dev/null +++ b/linux/devicetree/wally-qmtechk7.dts @@ -0,0 +1,118 @@ +/dts-v1/; + +/ { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "wally-virt"; + model = "wally-qmtech-k7"; + + chosen { + linux,initrd-end = <0x85c43a00>; + linux,initrd-start = <0x84200000>; + bootargs = "root=/dev/vda ro console=ttyS0,115200 loglevel=7"; + stdout-path = "/soc/uart@10000000"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00 0x80000000 0x00 0x10000000>; // 256 MB Qmtech board + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + clock-frequency = <40000000>; + timebase-frequency = <40000000>; + + cpu@0 { + phandle = <0x01>; + device_type = "cpu"; + reg = <0x00>; + status = "okay"; + compatible = "riscv"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "sstc", "svade", "svadu", "svinval", "svnapot", "svpbmt", "zba", "zbb", "zbc", "zbs", "zca", "zcb", "zcd", "zfa", "zfh", "zkn", "zkt", "zicbom", "zicboz", "zicntr", "zicond", "zicsr", "zifencei", "zihpm"; + riscv,cboz-block-size = <64>; + riscv,cbom-block-size = <64>; + mmu-type = "riscv,sv48"; + + interrupt-controller { + #interrupt-cells = <0x01>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + phandle = <0x02>; + }; + }; + }; + + soc { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "simple-bus"; + ranges; + + refclk: refclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <40000000>; + 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>; + clock-frequency = <40000000>; + reg = <0x00 0x10000000 0x00 0x100>; + compatible = "ns16550a"; + }; + + plic@c000000 { + phandle = <0x03>; + riscv,ndev = <0x35>; + reg = <0x00 0xc000000 0x00 0x210000>; + interrupts-extended = <0x02 0x0b 0x02 0x09>; + interrupt-controller; + compatible = "sifive,plic-1.0.0\0riscv,plic0"; + #interrupt-cells = <0x01>; + #address-cells = <0x00>; + }; + + spi@13000 { + compatible = "sifive,spi0"; + interrupt-parent = <0x03>; + 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 = <1000000>; + voltage-ranges = <3300 3300>; + disable-wp; + // gpios = <&gpio0 6 1>; + }; + }; + + clint@2000000 { + interrupts-extended = <0x02 0x03 0x02 0x07>; + reg = <0x00 0x2000000 0x00 0x10000>; + compatible = "sifive,clint0\0riscv,clint0"; + }; + }; +};