From e3ff5106cfeafdafebe64c94c601f8b65c034911 Mon Sep 17 00:00:00 2001 From: slederer Date: Thu, 19 Sep 2024 00:44:08 +0200 Subject: [PATCH] import Vivado project --- .gitignore | 3 +- rtl/arty-a7/Arty-A7-35-Master.xdc | 218 ++ rtl/arty-a7/Arty_C_mig.ucf | 48 + rtl/arty-a7/mig_dram_0/mig_a.prj | 148 ++ rtl/arty-a7/mig_dram_0/mig_b.prj | 148 ++ rtl/arty-a7/mig_dram_0/mig_dram_0.xci | 2876 ++++++++++++++++++++++++ rtl/arty-a7/sdspi_testbench_behav.wcfg | 176 ++ rtl/arty-a7/testbench_behav1.wcfg | 88 + rtl/arty-a7/tridoracpu.tcl | 724 ++++++ rtl/src/bram_tdp.v | 46 + rtl/src/cpuclk.v | 83 + rtl/src/display_clock.v | 96 + rtl/src/dram_bridge.v | 165 ++ rtl/src/fifo.v | 53 + rtl/src/fifo_testbench.v | 116 + rtl/src/irqctrl.v | 73 + rtl/src/mem.v | 161 ++ rtl/src/palette.v | 28 + rtl/src/sdspi.v | 372 +++ rtl/src/sdspi_testbench.v | 199 ++ rtl/src/stack.v | 42 + rtl/src/stackcpu.v | 427 ++++ rtl/src/testbench.v | 54 + rtl/src/top.v | 288 +++ rtl/src/uart.v | 262 +++ rtl/src/uart_tb.v | 100 + rtl/src/vgafb.v | 292 +++ 27 files changed, 7285 insertions(+), 1 deletion(-) create mode 100644 rtl/arty-a7/Arty-A7-35-Master.xdc create mode 100644 rtl/arty-a7/Arty_C_mig.ucf create mode 100644 rtl/arty-a7/mig_dram_0/mig_a.prj create mode 100644 rtl/arty-a7/mig_dram_0/mig_b.prj create mode 100644 rtl/arty-a7/mig_dram_0/mig_dram_0.xci create mode 100644 rtl/arty-a7/sdspi_testbench_behav.wcfg create mode 100644 rtl/arty-a7/testbench_behav1.wcfg create mode 100644 rtl/arty-a7/tridoracpu.tcl create mode 100644 rtl/src/bram_tdp.v create mode 100644 rtl/src/cpuclk.v create mode 100644 rtl/src/display_clock.v create mode 100644 rtl/src/dram_bridge.v create mode 100644 rtl/src/fifo.v create mode 100644 rtl/src/fifo_testbench.v create mode 100644 rtl/src/irqctrl.v create mode 100644 rtl/src/mem.v create mode 100644 rtl/src/palette.v create mode 100644 rtl/src/sdspi.v create mode 100644 rtl/src/sdspi_testbench.v create mode 100644 rtl/src/stack.v create mode 100644 rtl/src/stackcpu.v create mode 100644 rtl/src/testbench.v create mode 100644 rtl/src/top.v create mode 100644 rtl/src/uart.v create mode 100644 rtl/src/uart_tb.v create mode 100644 rtl/src/vgafb.v diff --git a/.gitignore b/.gitignore index 9f2164b..9db2d5c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.sasmout *.lib *.img +*.mem *.lsym *.zip go.sum @@ -17,10 +18,10 @@ sine.pas graph.pas graph2.pas chase.pas -*.img !runtime.s **/tridoracpu.*/ rtl/arty-a7/mig_dram_0/_tmp rtl/arty-a7/mig_dram_0/mig_dram_0 rtl/arty-a7/mig_dram_0/xil_txt.* rtl/arty-a7/mig_dram_0/*.veo +rtl/arty-a7/mig_dram_0/*.tcl diff --git a/rtl/arty-a7/Arty-A7-35-Master.xdc b/rtl/arty-a7/Arty-A7-35-Master.xdc new file mode 100644 index 0000000..c618478 --- /dev/null +++ b/rtl/arty-a7/Arty-A7-35-Master.xdc @@ -0,0 +1,218 @@ +## This file is a general .xdc for the Arty A7-35 Rev. D +## To use it in a project: +## - uncomment the lines corresponding to used pins +## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project + +## Clock signal +set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk] +create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk] + +## Switches +set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0] +set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1] +#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2] +#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3] + +## RGB LEDs +#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { led0_b }]; #IO_L18N_T2_35 Sch=led0_b +#set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { led0_g }]; #IO_L19N_T3_VREF_35 Sch=led0_g +#set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { led0_r }]; #IO_L19P_T3_35 Sch=led0_r +#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { led1_b }]; #IO_L20P_T3_35 Sch=led1_b +#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { led1_g }]; #IO_L21P_T3_DQS_35 Sch=led1_g +#set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { led1_r }]; #IO_L20N_T3_35 Sch=led1_r +#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { led2_b }]; #IO_L21N_T3_DQS_35 Sch=led2_b +#set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { led2_g }]; #IO_L22N_T3_35 Sch=led2_g +#set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { led2_r }]; #IO_L22P_T3_35 Sch=led2_r +#set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { led3_b }]; #IO_L23P_T3_35 Sch=led3_b +#set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { led3_g }]; #IO_L24P_T3_35 Sch=led3_g +#set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { led3_r }]; #IO_L23N_T3_35 Sch=led3_r + +## LEDs +set_property -dict {PACKAGE_PIN H5 IOSTANDARD LVCMOS33} [get_ports led0] +set_property -dict {PACKAGE_PIN J5 IOSTANDARD LVCMOS33} [get_ports led1] +set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports led2] +set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3] + +## Buttons +set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0] +#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1] +#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2] +#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3] + +## Pmod Header JA +set_property -dict {PACKAGE_PIN G13 IOSTANDARD LVCMOS33} [get_ports sd_cs_n] +set_property -dict {PACKAGE_PIN B11 IOSTANDARD LVCMOS33} [get_ports sd_mosi] +set_property -dict {PACKAGE_PIN A11 IOSTANDARD LVCMOS33} [get_ports sd_miso] +set_property -dict {PACKAGE_PIN D12 IOSTANDARD LVCMOS33} [get_ports sd_sck] +#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { sd_dat1 }]; #IO_L6N_T0_VREF_15 Sch=ja[7] +#set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { sd_dat2 }]; #IO_L10P_T1_AD11P_15 Sch=ja[8] +set_property -dict {PACKAGE_PIN A18 IOSTANDARD LVCMOS33} [get_ports sd_cd] +#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { sd_nc }]; #IO_25_15 Sch=ja[10] + +###Pmod Header JB +set_property -dict {PACKAGE_PIN E15 IOSTANDARD LVCMOS33} [get_ports {VGA_R[0]}] +set_property -dict {PACKAGE_PIN E16 IOSTANDARD LVCMOS33} [get_ports {VGA_R[1]}] +set_property -dict {PACKAGE_PIN D15 IOSTANDARD LVCMOS33} [get_ports {VGA_R[2]}] +set_property -dict {PACKAGE_PIN C15 IOSTANDARD LVCMOS33} [get_ports {VGA_R[3]}] +set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS33} [get_ports {VGA_B[0]}] +set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS33} [get_ports {VGA_B[1]}] +set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS33} [get_ports {VGA_B[2]}] +set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {VGA_B[3]}] + +###Pmod Header JC +set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {VGA_G[0]}] +set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports {VGA_G[1]}] +set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {VGA_G[2]}] +set_property -dict {PACKAGE_PIN V11 IOSTANDARD LVCMOS33} [get_ports {VGA_G[3]}] +set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports VGA_HS_O] +set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports VGA_VS_O] +#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { jc[6] }]; #IO_L23P_T3_A03_D19_14 Sch=jc_p[4] +#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4] + +## Pmod Header JD +#set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L11N_T1_SRCC_35 Sch=jd[1] +#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L12N_T1_MRCC_35 Sch=jd[2] +#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3] +#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L13N_T2_MRCC_35 Sch=jd[4] +#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7] +#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8] +#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9] +#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L15N_T2_DQS_35 Sch=jd[10] + +## USB-UART Interface +set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS33} [get_ports uart_rxd_out] +set_property -dict {PACKAGE_PIN A9 IOSTANDARD LVCMOS33} [get_ports uart_txd_in] + +## ChipKit Outer Digital Header +#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ck_io0 }]; #IO_L16P_T2_CSI_B_14 Sch=ck_io[0] +#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { ck_io1 }]; #IO_L18P_T2_A12_D28_14 Sch=ck_io[1] +#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { ck_io2 }]; #IO_L8N_T1_D12_14 Sch=ck_io[2] +#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { ck_io3 }]; #IO_L19P_T3_A10_D26_14 Sch=ck_io[3] +#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { ck_io4 }]; #IO_L5P_T0_D06_14 Sch=ck_io[4] +#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { ck_io5 }]; #IO_L14P_T2_SRCC_14 Sch=ck_io[5] +#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { ck_io6 }]; #IO_L14N_T2_SRCC_14 Sch=ck_io[6] +#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { ck_io7 }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=ck_io[7] +#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { ck_io8 }]; #IO_L11P_T1_SRCC_14 Sch=ck_io[8] +#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { ck_io9 }]; #IO_L10P_T1_D14_14 Sch=ck_io[9] +#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { ck_io10 }]; #IO_L18N_T2_A11_D27_14 Sch=ck_io[10] +#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ck_io11 }]; #IO_L17N_T2_A13_D29_14 Sch=ck_io[11] +#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { ck_io12 }]; #IO_L12N_T1_MRCC_14 Sch=ck_io[12] +#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { ck_io13 }]; #IO_L12P_T1_MRCC_14 Sch=ck_io[13] + +## ChipKit Inner Digital Header +#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { ck_io26 }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=ck_io[26] +#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { ck_io27 }]; #IO_L16N_T2_A15_D31_14 Sch=ck_io[27] +#set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { ck_io28 }]; #IO_L6N_T0_D08_VREF_14 Sch=ck_io[28] +#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { ck_io29 }]; #IO_25_14 Sch=ck_io[29] +#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { ck_io30 }]; #IO_0_14 Sch=ck_io[30] +#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { ck_io31 }]; #IO_L5N_T0_D07_14 Sch=ck_io[31] +#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { ck_io32 }]; #IO_L13N_T2_MRCC_14 Sch=ck_io[32] +#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ck_io33 }]; #IO_L13P_T2_MRCC_14 Sch=ck_io[33] +#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { ck_io34 }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=ck_io[34] +#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { ck_io35 }]; #IO_L11N_T1_SRCC_14 Sch=ck_io[35] +#set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { ck_io36 }]; #IO_L8P_T1_D11_14 Sch=ck_io[36] +#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { ck_io37 }]; #IO_L17P_T2_A14_D30_14 Sch=ck_io[37] +#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { ck_io38 }]; #IO_L7N_T1_D10_14 Sch=ck_io[38] +#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { ck_io39 }]; #IO_L7P_T1_D09_14 Sch=ck_io[39] +#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { ck_io40 }]; #IO_L9N_T1_DQS_D13_14 Sch=ck_io[40] +#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ck_io41 }]; #IO_L9P_T1_DQS_14 Sch=ck_io[41] + +## ChipKit Outer Analog Header - as Single-Ended Analog Inputs +## NOTE: These ports can be used as single-ended analog inputs with voltages from 0-3.3V (ChipKit analog pins A0-A5) or as digital I/O. +## WARNING: Do not use both sets of constraints at the same time! +## NOTE: The following constraints should be used with the XADC IP core when using these ports as analog inputs. +#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { vaux4_n }]; #IO_L1N_T0_AD4N_35 Sch=ck_an_n[0] ChipKit pin=A0 +#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { vaux4_p }]; #IO_L1P_T0_AD4P_35 Sch=ck_an_p[0] ChipKit pin=A0 +#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { vaux5_n }]; #IO_L3N_T0_DQS_AD5N_35 Sch=ck_an_n[1] ChipKit pin=A1 +#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { vaux5_p }]; #IO_L3P_T0_DQS_AD5P_35 Sch=ck_an_p[1] ChipKit pin=A1 +#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { vaux6_n }]; #IO_L7N_T1_AD6N_35 Sch=ck_an_n[2] ChipKit pin=A2 +#set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { vaux6_p }]; #IO_L7P_T1_AD6P_35 Sch=ck_an_p[2] ChipKit pin=A2 +#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { vaux7_n }]; #IO_L9N_T1_DQS_AD7N_35 Sch=ck_an_n[3] ChipKit pin=A3 +#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { vaux7_p }]; #IO_L9P_T1_DQS_AD7P_35 Sch=ck_an_p[3] ChipKit pin=A3 +#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { vaux15_n }]; #IO_L10N_T1_AD15N_35 Sch=ck_an_n[4] ChipKit pin=A4 +#set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { vaux15_p }]; #IO_L10P_T1_AD15P_35 Sch=ck_an_p[4] ChipKit pin=A4 +#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { vaux0_n }]; #IO_L1N_T0_AD0N_15 Sch=ck_an_n[5] ChipKit pin=A5 +#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { vaux0_p }]; #IO_L1P_T0_AD0P_15 Sch=ck_an_p[5] ChipKit pin=A5 +## ChipKit Outer Analog Header - as Digital I/O +## NOTE: the following constraints should be used when using these ports as digital I/O. +#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { ck_a0 }]; #IO_0_35 Sch=ck_a[0] ChipKit pin=A0 +#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { ck_a1 }]; #IO_L4P_T0_35 Sch=ck_a[1] ChipKit pin=A1 +#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { ck_a2 }]; #IO_L4N_T0_35 Sch=ck_a[2] ChipKit pin=A2 +#set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { ck_a3 }]; #IO_L6P_T0_35 Sch=ck_a[3] ChipKit pin=A3 +#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { ck_a4 }]; #IO_L6N_T0_VREF_35 Sch=ck_a[4] ChipKit pin=A4 +#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { ck_a5 }]; #IO_L11P_T1_SRCC_35 Sch=ck_a[5] ChipKit pin=A5 + +## ChipKit Inner Analog Header - as Differential Analog Inputs +## NOTE: These ports can be used as differential analog inputs with voltages from 0-1.0V (ChipKit Analog pins A6-A11) or as digital I/O. +## WARNING: Do not use both sets of constraints at the same time! +## NOTE: The following constraints should be used with the XADC core when using these ports as analog inputs. +#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { vaux12_p }]; #IO_L2P_T0_AD12P_35 Sch=ad_p[12] ChipKit pin=A6 +#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { vaux12_n }]; #IO_L2N_T0_AD12N_35 Sch=ad_n[12] ChipKit pin=A7 +#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { vaux13_p }]; #IO_L5P_T0_AD13P_35 Sch=ad_p[13] ChipKit pin=A8 +#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { vaux13_n }]; #IO_L5N_T0_AD13N_35 Sch=ad_n[13] ChipKit pin=A9 +#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { vaux14_p }]; #IO_L8P_T1_AD14P_35 Sch=ad_p[14] ChipKit pin=A10 +#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { vaux14_n }]; #IO_L8N_T1_AD14N_35 Sch=ad_n[14] ChipKit pin=A11 +## ChipKit Inner Analog Header - as Digital I/O +## NOTE: the following constraints should be used when using the inner analog header ports as digital I/O. +#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { ck_io20 }]; #IO_L2P_T0_AD12P_35 Sch=ad_p[12] ChipKit pin=A6 +#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { ck_io21 }]; #IO_L2N_T0_AD12N_35 Sch=ad_n[12] ChipKit pin=A7 +#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { ck_io22 }]; #IO_L5P_T0_AD13P_35 Sch=ad_p[13] ChipKit pin=A8 +#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { ck_io23 }]; #IO_L5N_T0_AD13N_35 Sch=ad_n[13] ChipKit pin=A9 +#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { ck_io24 }]; #IO_L8P_T1_AD14P_35 Sch=ad_p[14] ChipKit pin=A10 +#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { ck_io25 }]; #IO_L8N_T1_AD14N_35 Sch=ad_n[14] ChipKit pin=A11 + +## ChipKit SPI +#set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { ck_miso }]; #IO_L17N_T2_35 Sch=ck_miso +#set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { ck_mosi }]; #IO_L17P_T2_35 Sch=ck_mosi +#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { ck_sck }]; #IO_L18P_T2_35 Sch=ck_sck +#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { ck_ss }]; #IO_L16N_T2_35 Sch=ck_ss + +## ChipKit I2C +#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L4P_T0_D04_14 Sch=ck_scl +#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L4N_T0_D05_14 Sch=ck_sda +#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { scl_pup }]; #IO_L9N_T1_DQS_AD3N_15 Sch=scl_pup +#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { sda_pup }]; #IO_L9P_T1_DQS_AD3P_15 Sch=sda_pup + +## Misc. ChipKit Ports +#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { ck_ioa }]; #IO_L10N_T1_D15_14 Sch=ck_ioa +set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33} [get_ports rst] + +## SMSC Ethernet PHY +#set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { eth_col }]; #IO_L16N_T2_A27_15 Sch=eth_col +#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { eth_crs }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=eth_crs +#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { eth_mdc }]; #IO_L14N_T2_SRCC_15 Sch=eth_mdc +#set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { eth_mdio }]; #IO_L17P_T2_A26_15 Sch=eth_mdio +#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { eth_ref_clk }]; #IO_L22P_T3_A17_15 Sch=eth_ref_clk +#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { eth_rstn }]; #IO_L20P_T3_A20_15 Sch=eth_rstn +#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_clk }]; #IO_L14P_T2_SRCC_15 Sch=eth_rx_clk +#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_dv }]; #IO_L13N_T2_MRCC_15 Sch=eth_rx_dv +#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[0] }]; #IO_L21N_T3_DQS_A18_15 Sch=eth_rxd[0] +#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[1] }]; #IO_L16P_T2_A28_15 Sch=eth_rxd[1] +#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[2] }]; #IO_L21P_T3_DQS_15 Sch=eth_rxd[2] +#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[3] }]; #IO_L18N_T2_A23_15 Sch=eth_rxd[3] +#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxerr }]; #IO_L20N_T3_A19_15 Sch=eth_rxerr +#set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_clk }]; #IO_L13P_T2_MRCC_15 Sch=eth_tx_clk +#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_en }]; #IO_L19N_T3_A21_VREF_15 Sch=eth_tx_en +#set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[0] }]; #IO_L15P_T2_DQS_15 Sch=eth_txd[0] +#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[1] }]; #IO_L19P_T3_A22_15 Sch=eth_txd[1] +#set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[2] }]; #IO_L17N_T2_A25_15 Sch=eth_txd[2] +#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[3] }]; #IO_L18P_T2_A24_15 Sch=eth_txd[3] + +## Quad SPI Flash +#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { qspi_cs }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_cs +#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] +#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1] +#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] +#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] + +## Power Measurements +#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports { vsnsvu_n }]; #IO_L7N_T1_AD2N_15 Sch=ad_n[2] +#set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports { vsnsvu_p }]; #IO_L7P_T1_AD2P_15 Sch=ad_p[2] +#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { vsns5v0_n }]; #IO_L3N_T0_DQS_AD1N_15 Sch=ad_n[1] +#set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { vsns5v0_p }]; #IO_L3P_T0_DQS_AD1P_15 Sch=ad_p[1] +#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { isns5v0_n }]; #IO_L5N_T0_AD9N_15 Sch=ad_n[9] +#set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { isns5v0_p }]; #IO_L5P_T0_AD9P_15 Sch=ad_p[9] +#set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_n }]; #IO_L8N_T1_AD10N_15 Sch=ad_n[10] +#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_p }]; #IO_L8P_T1_AD10P_15 Sch=ad_p[10] + +set_property BITSTREAM.GENERAL.COMPRESS True [current_design] diff --git a/rtl/arty-a7/Arty_C_mig.ucf b/rtl/arty-a7/Arty_C_mig.ucf new file mode 100644 index 0000000..5a36c18 --- /dev/null +++ b/rtl/arty-a7/Arty_C_mig.ucf @@ -0,0 +1,48 @@ +NET "ddr3_dq[0]" LOC = "K5" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[1]" LOC = "L3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[2]" LOC = "K3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[3]" LOC = "L6" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[4]" LOC = "M3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[5]" LOC = "M1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[6]" LOC = "L4" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[7]" LOC = "M2" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[8]" LOC = "V4" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[9]" LOC = "T5" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[10]" LOC = "U4" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[11]" LOC = "V5" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[12]" LOC = "V1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[13]" LOC = "T3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[14]" LOC = "U3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[15]" LOC = "R3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dm[0]" LOC = "L1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dm[1]" LOC = "U1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dqs_p[0]" LOC = "N2" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_dqs_n[0]" LOC = "N1" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_dqs_p[1]" LOC = "U2" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_dqs_n[1]" LOC = "V2" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_addr[13]" LOC = "T8" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[12]" LOC = "T6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[11]" LOC = "U6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[10]" LOC = "R6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[9]" LOC = "V7" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[8]" LOC = "R8" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[7]" LOC = "U7" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[6]" LOC = "V6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[5]" LOC = "R7" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[4]" LOC = "N6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[3]" LOC = "T1" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[2]" LOC = "N4" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[1]" LOC = "M6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[0]" LOC = "R2" | IOSTANDARD = SSTL135 ; +NET "ddr3_ba[2]" LOC = "P2" | IOSTANDARD = SSTL135 ; +NET "ddr3_ba[1]" LOC = "P4" | IOSTANDARD = SSTL135 ; +NET "ddr3_ba[0]" LOC = "R1" | IOSTANDARD = SSTL135 ; +NET "ddr3_ck_p[0]" LOC = "U9" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_ck_n[0]" LOC = "V9" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_ras_n" LOC = "P3" | IOSTANDARD = SSTL135 ; +NET "ddr3_cas_n" LOC = "M4" | IOSTANDARD = SSTL135 ; +NET "ddr3_we_n" LOC = "P5" | IOSTANDARD = SSTL135 ; +NET "ddr3_reset_n" LOC = "K6" | IOSTANDARD = SSTL135 ; +NET "ddr3_cke[0]" LOC = "N5" | IOSTANDARD = SSTL135 ; +NET "ddr3_odt[0]" LOC = "R5" | IOSTANDARD = SSTL135 ; +NET "ddr3_cs_n[0]" LOC = "U8" | IOSTANDARD = SSTL135 ; diff --git a/rtl/arty-a7/mig_dram_0/mig_a.prj b/rtl/arty-a7/mig_dram_0/mig_a.prj new file mode 100644 index 0000000..b263a25 --- /dev/null +++ b/rtl/arty-a7/mig_dram_0/mig_a.prj @@ -0,0 +1,148 @@ + + + + + + + + mig_dram_0 + + 1 + + 1 + + OFF + + 1024 + + ON + + Enabled + + xc7a35ti-csg324/-1L + + 4.2 + + No Buffer + + No Buffer + + ACTIVE LOW + + FALSE + + 1 + + 50 Ohms + + 0 + + + DDR3_SDRAM/Components/MT41K128M16XX-15E + 3000 + 1.8V + 4:1 + 83.333 + 0 + 666 + 1.000 + 1 + 1 + 1 + 1 + 16 + 1 + 1 + Disabled + Strict + 4 + FALSE + + 14 + 10 + 3 + 1.35V + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Fixed + Sequential + 5 + Normal + No + Slow Exit + Enable + RZQ/6 + Disable + Enable + RZQ/6 + 0 + Disabled + Enabled + Output Buffer Enabled + Full Array + 5 + Enabled + Normal + Dynamic ODT off + NATIVE + + + + diff --git a/rtl/arty-a7/mig_dram_0/mig_b.prj b/rtl/arty-a7/mig_dram_0/mig_b.prj new file mode 100644 index 0000000..b263a25 --- /dev/null +++ b/rtl/arty-a7/mig_dram_0/mig_b.prj @@ -0,0 +1,148 @@ + + + + + + + + mig_dram_0 + + 1 + + 1 + + OFF + + 1024 + + ON + + Enabled + + xc7a35ti-csg324/-1L + + 4.2 + + No Buffer + + No Buffer + + ACTIVE LOW + + FALSE + + 1 + + 50 Ohms + + 0 + + + DDR3_SDRAM/Components/MT41K128M16XX-15E + 3000 + 1.8V + 4:1 + 83.333 + 0 + 666 + 1.000 + 1 + 1 + 1 + 1 + 16 + 1 + 1 + Disabled + Strict + 4 + FALSE + + 14 + 10 + 3 + 1.35V + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Fixed + Sequential + 5 + Normal + No + Slow Exit + Enable + RZQ/6 + Disable + Enable + RZQ/6 + 0 + Disabled + Enabled + Output Buffer Enabled + Full Array + 5 + Enabled + Normal + Dynamic ODT off + NATIVE + + + + diff --git a/rtl/arty-a7/mig_dram_0/mig_dram_0.xci b/rtl/arty-a7/mig_dram_0/mig_dram_0.xci new file mode 100644 index 0000000..3da3694 --- /dev/null +++ b/rtl/arty-a7/mig_dram_0/mig_dram_0.xci @@ -0,0 +1,2876 @@ + + + xilinx.com + xci + unknown + 1.0 + + + mig_dram_0 + + + 0 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 0 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + + 0 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + TDM + 8 + false + 11 + 11 + true + + true + 8 + + COMPONENTS + ROW_COLUMN_BANK + Single + 1250 + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + + + + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 0 + false + 100000000 + + + + 100000000 + 0 + 0 + 0.000 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 32 + 32 + 32 + 4 + 1048576 + 32 + 4 + 1048576 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 100.0 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 1200.0 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + DIFF + FALSE + 0 + 0 + 28 + 32 + 32 + 4 + 1048576 + 128 + 2 + 268435456 + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + 1 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + 28 + 3 + 1 + 1 + 1 + 16 + OFF + 2 + 1 + 2 + 16 + 1 + OFF + 14 + 1 + 1 + 1 + 4 + 1 + 8 + 8 + 2 + OFF + 1 + OFF + 83333333 + FALSE + 8 + 3 + 1 + 1 + 1 + 8 + OFF + 1 + 1 + 1 + 8 + OFF + 14 + 1 + 1 + 1 + 2 + 1 + DDR3 + FALSE + 10.0 + FALSE + 10 + FALSE + 10 + FALSE + 10 + FALSE + 10 + 666 + 1 + 0.000 + ACTIVE_LOW + 29 + 1 + 8 + 18 + OFF + 1 + NOBUF + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 1 + 18 + OFF + 1 + 1 + 1 + 8 + 1 + 29 + 1 + 29 + 2 + 1 + 18 + 1 + 1 + NOBUF + INTERNAL + FALSE + 0 + Custom + mig_dram_0 + Custom + Custom + mig_b.prj + artix7 + digilentinc.com:arty-a7-35:part0:1.0 + + xc7a35ti + csg324 + VERILOG + + MIXED + -1L + + I + TRUE + TRUE + IP_Flow + 1 + TRUE + . + + . + 2020.1 + OUT_OF_CONTEXT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rtl/arty-a7/sdspi_testbench_behav.wcfg b/rtl/arty-a7/sdspi_testbench_behav.wcfg new file mode 100644 index 0000000..bb29917 --- /dev/null +++ b/rtl/arty-a7/sdspi_testbench_behav.wcfg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + clk + clk + + + tx_data[7:0] + tx_data[7:0] + + + rx_data[7:0] + rx_data[7:0] + + + rx_shifter[7:0] + rx_shifter[7:0] + + + tx_shifter[7:0] + tx_shifter[7:0] + + + tx_fifo_out[7:0] + tx_fifo_out[7:0] + + + tx_fifo_rd_en + tx_fifo_rd_en + + + tx_fifo_wr_en + tx_fifo_wr_en + + + rx_fifo_wr_en + rx_fifo_wr_en + + + rx_bit_recvd + rx_bit_recvd + + + tail_x[4:0] + tail_x[4:0] + + + head_x[4:0] + head_x[4:0] + + + tx_ready + tx_ready + + + tx_empty + tx_empty + + + rx_avail + rx_avail + + + tx_write + tx_write + + + rx_read + rx_read + + + ctrl_write + ctrl_write + + + rx_filter_en + rx_filter_en + + + txrx_en + txrx_en + + + spiclk_div_wr + spiclk_div_wr + + + spi_clk_on + spi_clk_on + + + spiclk_f_en + spiclk_f_en + + + spi_clk_f_on + spi_clk_f_on + + + sd_cs_n + sd_cs_n + #DCDCDC + true + + + sd_mosi + sd_mosi + #00FFFF + true + + + sd_miso + sd_miso + + + sd_sck + sd_sck + #FFFF00 + true + + + xcvr_on + xcvr_on + + + hphase_start + hphase_start + #F0E68C + true + + + clk_phase[1:0] + clk_phase[1:0] + #D2691E + true + + + running + running + + + xcvr_bitcount[3:0] + xcvr_bitcount[3:0] + + + spi_clk_count[6:0] + spi_clk_count[6:0] + + + spi_clk_div[6:0] + spi_clk_div[6:0] + + diff --git a/rtl/arty-a7/testbench_behav1.wcfg b/rtl/arty-a7/testbench_behav1.wcfg new file mode 100644 index 0000000..1a2bc03 --- /dev/null +++ b/rtl/arty-a7/testbench_behav1.wcfg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + clk + clk + + + addr[31:0] + addr[31:0] + + + data_in[31:0] + data_in[31:0] + + + data_out[31:0] + data_out[31:0] + + + seq_state[1:0] + seq_state[1:0] + + + PC[31:0] + PC[31:0] + + + nPC[31:0] + nPC[31:0] + + + ins[15:0] + ins[15:0] + BINARYRADIX + + + ins_branch + ins_branch + + + ins_loadrel + ins_loadrel + + + X[31:0] + X[31:0] + + + nX[31:0] + nX[31:0] + + + FP[31:0] + FP[31:0] + + + pc_next_ins[31:0] + pc_next_ins[31:0] + + + mem_wait + mem_wait + + + ins_buf[15:0] + ins_buf[15:0] + + diff --git a/rtl/arty-a7/tridoracpu.tcl b/rtl/arty-a7/tridoracpu.tcl new file mode 100644 index 0000000..e18483e --- /dev/null +++ b/rtl/arty-a7/tridoracpu.tcl @@ -0,0 +1,724 @@ +#***************************************************************************************** +# Vivado (TM) v2020.1 (64-bit) +# +# tridoracpu.tcl: Tcl script for re-creating project 'tridoracpu' +# +# Generated by Vivado on Sat Sep 14 23:58:12 +0200 2024 +# IP Build 2902112 on Wed May 27 22:43:36 MDT 2020 +# +# This file contains the Vivado Tcl commands for re-creating the project to the state* +# when this script was generated. In order to re-create the project, please source this +# file in the Vivado Tcl Shell. +# +# * Note that the runs in the created project will be configured the same way as the +# original project, however they will not be launched automatically. To regenerate the +# run results please launch the synthesis/implementation runs as needed. +# +#***************************************************************************************** +# NOTE: In order to use this script for source control purposes, please make sure that the +# following files are added to the source control system:- +# +# 1. This project restoration tcl script (tridoracpu.tcl) that was generated. +# +# 2. The following source(s) files that were local or imported into the original project. +# (Please see the '$orig_proj_dir' and '$origin_dir' variable setting below at the start of the script) +# +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/cpuclk.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/display_clock.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/mem.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/stack.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/stackcpu.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/vgafb.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/top.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/testbench.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/rom.mem" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/ip/mig_dram_0/mig_a.prj" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/ip/mig_dram_0/mig_b.prj" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/dram_bridge.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/sdspi.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/bram_tdp.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/palette.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/irqctrl.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/fifo.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/fifo_testbench.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/sdspi_testbench.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/ip/mig_dram_0/mig_dram_0.xci" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sim_1/new/uart_tb.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/testbench_behav1.wcfg" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/fifo.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/new/fifo_testbench.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/sdspi_testbench_behav.wcfg" +# +# 3. The following remote source files that were added to the original project:- +# +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/sources_1/imports/verilog/uart.v" +# "C:/Users/sebastian/develop/fpga/tridoracpu/tridoracpu.srcs/constrs_1/imports/fpga/Arty-A7-35-Master.xdc" +# +#***************************************************************************************** + +#xhub::refresh_catalog [xhub::get_xstores xilinx_board_store] +# this will take quite some time +#xhub::install [xhub::get_xitems] + +# Set the reference directory for source file relative paths (by default the value is script directory path) +set origin_dir "C:/Users/sebastian/develop/Tridora/rtl" + +# Oh come on, Xilinx, why? +#set xilinx_board_store_dir "../../../../AppData/Roaming/Xilinx/Vivado/2020.1/xhub/board_store/xilinx_board_store" +set xilinx_board_store_dir [get_property LOCAL_ROOT_DIR [xhub::get_xstores xilinx_board_store]] +set_param board.repoPaths [get_property LOCAL_ROOT_DIR [xhub::get_xstores xilinx_board_store]] + +# Use origin directory path location variable, if specified in the tcl shell +if { [info exists ::origin_dir_loc] } { + set origin_dir $::origin_dir_loc +} + +# Set the project name +set _xil_proj_name_ "tridoracpu" + +# Use project name variable, if specified in the tcl shell +if { [info exists ::user_project_name] } { + set _xil_proj_name_ $::user_project_name +} + +variable script_file +set script_file "tridoracpu.tcl" + +# Help information for this script +proc print_help {} { + variable script_file + puts "\nDescription:" + puts "Recreate a Vivado project from this script. The created project will be" + puts "functionally equivalent to the original project for which this script was" + puts "generated. The script contains commands for creating a project, filesets," + puts "runs, adding/importing sources and setting properties on various objects.\n" + puts "Syntax:" + puts "$script_file" + puts "$script_file -tclargs \[--origin_dir \]" + puts "$script_file -tclargs \[--project_name \]" + puts "$script_file -tclargs \[--help\]\n" + puts "Usage:" + puts "Name Description" + puts "-------------------------------------------------------------------------" + puts "\[--origin_dir \] Determine source file paths wrt this path. Default" + puts " origin_dir path value is \".\", otherwise, the value" + puts " that was set with the \"-paths_relative_to\" switch" + puts " when this script was generated.\n" + puts "\[--project_name \] Create project with the specified name. Default" + puts " name is the name of the project from where this" + puts " script was generated.\n" + puts "\[--help\] Print help information for this script" + puts "-------------------------------------------------------------------------\n" + exit 0 +} + +if { $::argc > 0 } { + for {set i 0} {$i < $::argc} {incr i} { + set option [string trim [lindex $::argv $i]] + switch -regexp -- $option { + "--origin_dir" { incr i; set origin_dir [lindex $::argv $i] } + "--project_name" { incr i; set _xil_proj_name_ [lindex $::argv $i] } + "--help" { print_help } + default { + if { [regexp {^-} $option] } { + puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n" + return 1 + } + } + } + } +} + +# Set the directory path for the original project from where this script was exported +set orig_proj_dir "[file normalize "${origin_dir}/arty-a7"]" + +# Create project +create_project ${_xil_proj_name_} ./${_xil_proj_name_} -part xc7a35ticsg324-1L + +# Set the directory path for the new project +set proj_dir [get_property directory [current_project]] + +# Set project properties +set obj [current_project] +#set_property -name "board_part_repo_paths" -value "[file normalize "$xilinx_board_store_dir"]" -objects $obj +set_property -name "board_part" -value "digilentinc.com:arty-a7-35:part0:1.0" -objects $obj +set_property -name "default_lib" -value "xil_defaultlib" -objects $obj +set_property -name "enable_vhdl_2008" -value "1" -objects $obj +set_property -name "ip_cache_permissions" -value "read write" -objects $obj +set_property -name "ip_output_repo" -value "$proj_dir/${_xil_proj_name_}.cache/ip" -objects $obj +set_property -name "mem.enable_memory_map_generation" -value "1" -objects $obj +set_property -name "platform.board_id" -value "arty-a7-35" -objects $obj +set_property -name "sim.central_dir" -value "$proj_dir/${_xil_proj_name_}.ip_user_files" -objects $obj +set_property -name "sim.ip.auto_export_scripts" -value "1" -objects $obj +set_property -name "simulator_language" -value "Mixed" -objects $obj +set_property -name "source_mgmt_mode" -value "DisplayOnly" -objects $obj +set_property -name "webtalk.activehdl_export_sim" -value "4" -objects $obj +set_property -name "webtalk.ies_export_sim" -value "4" -objects $obj +set_property -name "webtalk.modelsim_export_sim" -value "4" -objects $obj +set_property -name "webtalk.questa_export_sim" -value "4" -objects $obj +set_property -name "webtalk.riviera_export_sim" -value "4" -objects $obj +set_property -name "webtalk.vcs_export_sim" -value "4" -objects $obj +set_property -name "webtalk.xsim_export_sim" -value "4" -objects $obj +set_property -name "webtalk.xsim_launch_sim" -value "537" -objects $obj + +# Create 'sources_1' fileset (if not found) +if {[string equal [get_filesets -quiet sources_1] ""]} { + create_fileset -srcset sources_1 +} + +# Set 'sources_1' fileset object +set obj [get_filesets sources_1] +set files [list \ + [file normalize "${origin_dir}/src/uart.v"] \ +] +add_files -norecurse -fileset $obj $files + +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/src/cpuclk.v" ]\ + [file normalize "${origin_dir}/src/display_clock.v" ]\ + [file normalize "${origin_dir}/src/mem.v" ]\ + [file normalize "${origin_dir}/src/stack.v" ]\ + [file normalize "${origin_dir}/src/stackcpu.v" ]\ + [file normalize "${origin_dir}/src/vgafb.v" ]\ + [file normalize "${origin_dir}/src/top.v" ]\ + [file normalize "${origin_dir}/src/testbench.v" ]\ + [file normalize "${orig_proj_dir}/rom.mem" ]\ + [file normalize "${orig_proj_dir}/mig_dram_0/mig_a.prj" ]\ + [file normalize "${orig_proj_dir}/mig_dram_0/mig_b.prj" ]\ + [file normalize "${origin_dir}/src/dram_bridge.v" ]\ + [file normalize "${origin_dir}/src/sdspi.v" ]\ + [file normalize "${origin_dir}/src/bram_tdp.v" ]\ + [file normalize "${origin_dir}/src/palette.v" ]\ + [file normalize "${origin_dir}/src/irqctrl.v" ]\ + [file normalize "${origin_dir}/src/fifo.v" ]\ + [file normalize "${origin_dir}/src/fifo_testbench.v" ]\ + [file normalize "${origin_dir}/src/sdspi_testbench.v" ]\ +] +set added_files [add_files -fileset sources_1 $files] + +# Set 'sources_1' fileset file properties for remote files +set file "$origin_dir/src/uart.v" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + + +# Set 'sources_1' fileset file properties for local files +set file "src/cpuclk.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/display_clock.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "is_enabled" -value "0" -objects $file_obj + +set file "src/mem.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/stack.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/stackcpu.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/vgafb.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/top.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/testbench.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "" -objects $file_obj +set_property -name "used_in_implementation" -value "0" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj +set_property -name "used_in_synthesis" -value "0" -objects $file_obj + +set file "arty-a7/rom.mem" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Memory File" -objects $file_obj + +set file "arty-a7/mig_dram_0/mig_a.prj" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "scoped_to_cells" -value "mig_dram_0" -objects $file_obj + +set file "arty-a7/mig_dram_0/mig_b.prj" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "scoped_to_cells" -value "mig_dram_0" -objects $file_obj + +set file "src/dram_bridge.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/palette.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/irqctrl.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/fifo_testbench.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "" -objects $file_obj +set_property -name "used_in_implementation" -value "0" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj +set_property -name "used_in_synthesis" -value "0" -objects $file_obj + + +# Set 'sources_1' fileset properties +set obj [get_filesets sources_1] +set_property -name "top" -value "top" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj + +# Set 'sources_1' fileset object +set obj [get_filesets sources_1] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${orig_proj_dir}/mig_dram_0/mig_dram_0.xci" ]\ +] +set added_files [add_files -fileset sources_1 $files] + +# Set 'sources_1' fileset file properties for remote files +# None + +# Set 'sources_1' fileset file properties for local files +set file "arty-a7/mig_dram_0/mig_dram_0.xci" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "generate_files_for_reference" -value "0" -objects $file_obj +set_property -name "registered_with_manager" -value "1" -objects $file_obj +if { ![get_property "is_locked" $file_obj] } { + set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj +} +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + + +# Create 'constrs_1' fileset (if not found) +if {[string equal [get_filesets -quiet constrs_1] ""]} { + create_fileset -constrset constrs_1 +} + +# Set 'constrs_1' fileset object +set obj [get_filesets constrs_1] + +# Add/Import constrs file and set constrs file properties +set file "[file normalize ${origin_dir}/arty-a7/Arty-A7-35-Master.xdc]" +set file_added [add_files -norecurse -fileset $obj [list $file]] +set file "$origin_dir/arty-a7/Arty-A7-35-Master.xdc" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets constrs_1] [list "*$file"]] +set_property -name "file_type" -value "XDC" -objects $file_obj + +# Set 'constrs_1' fileset properties +set obj [get_filesets constrs_1] +set_property -name "target_constrs_file" -value "$orig_proj_dir/Arty-A7-35-Master.xdc" -objects $obj +set_property -name "target_ucf" -value "$orig_proj_dir/Arty-A7-35-Master.xdc" -objects $obj + +# Create 'sim_1' fileset (if not found) +if {[string equal [get_filesets -quiet sim_1] ""]} { + create_fileset -simset sim_1 +} + +# Set 'sim_1' fileset object +set obj [get_filesets sim_1] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/src/uart_tb.v" ]\ + [file normalize "${orig_proj_dir}/testbench_behav1.wcfg" ]\ +] +set added_files [add_files -fileset sim_1 $files] + +# Set 'sim_1' fileset file properties for remote files +# None + +# Set 'sim_1' fileset file properties for local files +set file [file normalize "${origin_dir}/src/uart_tb.v"] +set file_obj [get_files -of_objects [get_filesets sim_1] [list "*$file"]] +set_property -name "used_in" -value "" -objects $file_obj +set_property -name "used_in_implementation" -value "0" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj +set_property -name "used_in_synthesis" -value "0" -objects $file_obj + + +# Set 'sim_1' fileset properties +set obj [get_filesets sim_1] +set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj +set_property -name "nl.mode" -value "funcsim" -objects $obj +set_property -name "top" -value "testbench" -objects $obj +set_property -name "top_lib" -value "xil_defaultlib" -objects $obj + +# Create 'sim_fifo' fileset (if not found) +if {[string equal [get_filesets -quiet sim_fifo] ""]} { + create_fileset -simset sim_fifo +} + +# Set 'sim_fifo' fileset object +set obj [get_filesets sim_fifo] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/src/fifo.v" ]\ + [file normalize "${origin_dir}/src/fifo_testbench.v" ]\ +] +set added_files [add_files -fileset sim_fifo $files] + +# Set 'sim_fifo' fileset file properties for remote files +# None + +# Set 'sim_fifo' fileset file properties for local files +# None + +# Set 'sim_fifo' fileset properties +set obj [get_filesets sim_fifo] +set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj +set_property -name "top" -value "fifo_testbench" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj + +# Create 'sim_sdspi' fileset (if not found) +if {[string equal [get_filesets -quiet sim_sdspi] ""]} { + create_fileset -simset sim_sdspi +} + +# Set 'sim_sdspi' fileset object +set obj [get_filesets sim_sdspi] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${orig_proj_dir}/sdspi_testbench_behav.wcfg" ]\ +] +set added_files [add_files -fileset sim_sdspi $files] + +# Set 'sim_sdspi' fileset file properties for remote files +# None + +# Set 'sim_sdspi' fileset file properties for local files +# None + +# Set 'sim_sdspi' fileset properties +set obj [get_filesets sim_sdspi] +set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj +set_property -name "sim_mode" -value "post-synthesis" -objects $obj +set_property -name "top" -value "sdspi_testbench" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj +set_property -name "top_lib" -value "xil_defaultlib" -objects $obj +set_property -name "xsim.simulate.runtime" -value "10ms" -objects $obj + +# Set 'utils_1' fileset object +set obj [get_filesets utils_1] +# Empty (no sources present) + +# Set 'utils_1' fileset properties +set obj [get_filesets utils_1] + +# Create 'synth_1' run (if not found) +if {[string equal [get_runs -quiet synth_1] ""]} { + create_run -name synth_1 -part xc7a35ticsg324-1L -flow {Vivado Synthesis 2020} -strategy "Vivado Synthesis Defaults" -report_strategy {No Reports} -constrset constrs_1 +} else { + set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1] + set_property flow "Vivado Synthesis 2020" [get_runs synth_1] +} +set obj [get_runs synth_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Synthesis Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'synth_1_synth_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } { + create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1 +} +set obj [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] +if { $obj != "" } { + +} +set obj [get_runs synth_1] +set_property -name "needs_refresh" -value "1" -objects $obj +set_property -name "strategy" -value "Vivado Synthesis Defaults" -objects $obj + +# set the current synth run +current_run -synthesis [get_runs synth_1] + +# Create 'impl_1' run (if not found) +if {[string equal [get_runs -quiet impl_1] ""]} { + create_run -name impl_1 -part xc7a35ticsg324-1L -flow {Vivado Implementation 2020} -strategy "Performance_RefinePlacement" -report_strategy {No Reports} -constrset constrs_1 -parent_run synth_1 +} else { + set_property strategy "Performance_RefinePlacement" [get_runs impl_1] + set_property flow "Vivado Implementation 2020" [get_runs impl_1] +} +set obj [get_runs impl_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Implementation Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'impl_1_init_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_init_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps init_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_opt_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] "" ] } { + create_report_config -report_name impl_1_opt_report_drc_0 -report_type report_drc:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] +if { $obj != "" } { + +} +# Create 'impl_1_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_place_report_io_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] "" ] } { + create_report_config -report_name impl_1_place_report_io_0 -report_type report_io:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] +if { $obj != "" } { + +} +# Create 'impl_1_place_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] "" ] } { + create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] +if { $obj != "" } { + +} +# Create 'impl_1_place_report_control_sets_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] "" ] } { + create_report_config -report_name impl_1_place_report_control_sets_0 -report_type report_control_sets:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] +if { $obj != "" } { +set_property -name "options.verbose" -value "1" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_1' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_1 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj + +} +# Create 'impl_1_place_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_place_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_post_place_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_place_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_place_power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_route_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] "" ] } { + create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_methodology_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] "" ] } { + create_report_config -report_name impl_1_route_report_methodology_0 -report_type report_methodology:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_power_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] "" ] } { + create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_route_status_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] "" ] } { + create_report_config -report_name impl_1_route_report_route_status_0 -report_type report_route_status:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_route_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] +if { $obj != "" } { +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_route_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_route_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_clock_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] "" ] } { + create_report_config -report_name impl_1_route_report_clock_utilization_0 -report_type report_clock_utilization:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_route_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] +if { $obj != "" } { +set_property -name "options.warn_on_violation" -value "1" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "options.max_paths" -value "10" -objects $obj +set_property -name "options.warn_on_violation" -value "1" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] +if { $obj != "" } { +set_property -name "options.warn_on_violation" -value "1" -objects $obj + +} +set obj [get_runs impl_1] +set_property -name "needs_refresh" -value "1" -objects $obj +set_property -name "strategy" -value "Performance_RefinePlacement" -objects $obj +set_property -name "steps.place_design.args.directive" -value "ExtraPostPlacementOpt" -objects $obj +set_property -name "steps.phys_opt_design.args.directive" -value "Explore" -objects $obj +set_property -name "steps.route_design.args.directive" -value "Explore" -objects $obj +set_property -name "steps.write_bitstream.args.bin_file" -value "1" -objects $obj +set_property -name "steps.write_bitstream.args.readback_file" -value "0" -objects $obj +set_property -name "steps.write_bitstream.args.verbose" -value "0" -objects $obj + +# set the current impl run +current_run -implementation [get_runs impl_1] + +puts "INFO: Project created:${_xil_proj_name_}" +# Create 'drc_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "drc_1" ] ] ""]} { +create_dashboard_gadget -name {drc_1} -type drc +} +set obj [get_dashboard_gadgets [ list "drc_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_drc_0" -objects $obj + +# Create 'methodology_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "methodology_1" ] ] ""]} { +create_dashboard_gadget -name {methodology_1} -type methodology +} +set obj [get_dashboard_gadgets [ list "methodology_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_methodology_0" -objects $obj + +# Create 'power_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "power_1" ] ] ""]} { +create_dashboard_gadget -name {power_1} -type power +} +set obj [get_dashboard_gadgets [ list "power_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_power_0" -objects $obj + +# Create 'timing_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "timing_1" ] ] ""]} { +create_dashboard_gadget -name {timing_1} -type timing +} +set obj [get_dashboard_gadgets [ list "timing_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_timing_summary_0" -objects $obj + +# Create 'utilization_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "utilization_1" ] ] ""]} { +create_dashboard_gadget -name {utilization_1} -type utilization +} +set obj [get_dashboard_gadgets [ list "utilization_1" ] ] +set_property -name "reports" -value "synth_1#synth_1_synth_report_utilization_0" -objects $obj +set_property -name "run.step" -value "synth_design" -objects $obj +set_property -name "run.type" -value "synthesis" -objects $obj + +# Create 'utilization_2' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "utilization_2" ] ] ""]} { +create_dashboard_gadget -name {utilization_2} -type utilization +} +set obj [get_dashboard_gadgets [ list "utilization_2" ] ] +set_property -name "reports" -value "impl_1#impl_1_place_report_utilization_0" -objects $obj + +move_dashboard_gadget -name {utilization_1} -row 0 -col 0 +move_dashboard_gadget -name {power_1} -row 1 -col 0 +move_dashboard_gadget -name {drc_1} -row 2 -col 0 +move_dashboard_gadget -name {timing_1} -row 0 -col 1 +move_dashboard_gadget -name {utilization_2} -row 1 -col 1 +move_dashboard_gadget -name {methodology_1} -row 2 -col 1 diff --git a/rtl/src/bram_tdp.v b/rtl/src/bram_tdp.v new file mode 100644 index 0000000..9537b9c --- /dev/null +++ b/rtl/src/bram_tdp.v @@ -0,0 +1,46 @@ +`timescale 1ns / 1ps +// taken from https://danstrother.com/2010/09/11/inferring-rams-in-fpgas/ +// modified for one read/write-port and one read-only-port, +/// A parameterized, inferable, true dual-port, dual-clock block RAM in Verilog. + +module bram_tdp #( + parameter DATA = 72, + parameter ADDR = 10 +) ( + // Port A + input wire a_clk, + input wire a_rd, + input wire a_wr, + input wire [ADDR-1:0] a_addr, + input wire [DATA-1:0] a_din, + output reg [DATA-1:0] a_dout, + // Port B + input wire b_clk, + input wire [ADDR-1:0] b_addr, + output reg [DATA-1:0] b_dout, + input wire b_rd +); + +// Shared memory + reg [DATA-1:0] mem [(2**ADDR)-1:0]; + + wire a_en = a_rd || a_wr; + +// Port A +always @(posedge a_clk) begin + if(a_en) + begin + if(a_wr) + mem[a_addr] <= a_din; + else if(a_rd) + a_dout <= mem[a_addr]; + end +end + +// Port B +always @(posedge b_clk) begin + if(b_rd) + b_dout <= mem[b_addr]; +end + +endmodule diff --git a/rtl/src/cpuclk.v b/rtl/src/cpuclk.v new file mode 100644 index 0000000..613d85e --- /dev/null +++ b/rtl/src/cpuclk.v @@ -0,0 +1,83 @@ +`timescale 1ns / 1ps + +module cpu_clkgen( + input wire rst, + input wire clk100, + output wire cpuclk, + output wire dram_refclk, + output wire pixclk, + output wire locked + ); + + wire cpuclk_pre, clk_fb, refclk_pre, pixclk_pre; + + MMCME2_BASE #( + .BANDWIDTH("OPTIMIZED"), // Jitter programming (OPTIMIZED, HIGH, LOW) + .CLKFBOUT_MULT_F(10.0), // Multiply value for all CLKOUT (2.000-64.000). + .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000). + .CLKIN1_PERIOD(10.0), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). + // CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128) + .CLKOUT0_DIVIDE_F(12.0), // Divide amount for CLKOUT0 (1.000-128.000). + .CLKOUT1_DIVIDE(5), + .CLKOUT2_DIVIDE(40), // 40 = 25MHz pixel clock (should be 25.175MHz per spec) for 640x480 + //.CLKOUT2_DIVIDE(25), // 25 = 40MHz pixel clock for 800x600 + //.CLKOUT2_DIVIDE(15), // 15 = 66.66MHz pixel clock (should be 65.0Mhz per spec) for 1024x768 + .CLKOUT3_DIVIDE(1), + .CLKOUT4_DIVIDE(1), + .CLKOUT5_DIVIDE(1), + .CLKOUT6_DIVIDE(1), + // CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99). + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT6_DUTY_CYCLE(0.5), + // CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000). + .CLKOUT0_PHASE(0.0), + .CLKOUT1_PHASE(0.0), + .CLKOUT2_PHASE(0.0), + .CLKOUT3_PHASE(0.0), + .CLKOUT4_PHASE(0.0), + .CLKOUT5_PHASE(0.0), + .CLKOUT6_PHASE(0.0), + .CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE) + .DIVCLK_DIVIDE(1), // Master division value (1-106) + .REF_JITTER1(0.010), // Reference input jitter in UI (0.000-0.999). + .STARTUP_WAIT("FALSE") // Delays DONE until MMCM is locked (FALSE, TRUE) + ) + + MMCME2_BASE_inst ( + /* verilator lint_off PINCONNECTEMPTY */ + // Clock Outputs: 1-bit (each) output: User configurable clock outputs + .CLKOUT0(cpuclk_pre), // 1-bit output: CLKOUT0 + .CLKOUT0B(), // 1-bit output: Inverted CLKOUT0 + .CLKOUT1(refclk_pre), // 1-bit output: CLKOUT1 + .CLKOUT1B(), // 1-bit output: Inverted CLKOUT1 + .CLKOUT2(pixclk_pre), // 1-bit output: CLKOUT2 + .CLKOUT2B(), // 1-bit output: Inverted CLKOUT2 + .CLKOUT3(), // 1-bit output: CLKOUT3 + .CLKOUT3B(), // 1-bit output: Inverted CLKOUT3 + .CLKOUT4(), // 1-bit output: CLKOUT4 + .CLKOUT5(), // 1-bit output: CLKOUT5 + .CLKOUT6(), // 1-bit output: CLKOUT6 + // Feedback Clocks: 1-bit (each) output: Clock feedback ports + .CLKFBOUT(clk_fb), // 1-bit output: Feedback clock + .CLKFBOUTB(), // 1-bit output: Inverted CLKFBOUT + // Status Ports: 1-bit (each) output: MMCM status ports + .LOCKED(locked), // 1-bit output: LOCK + // Clock Inputs: 1-bit (each) input: Clock input + .CLKIN1(clk100), // 1-bit input: Clock + // Control Ports: 1-bit (each) input: MMCM control ports + .PWRDWN(), // 1-bit input: Power-down + /* verilator lint_on PINCONNECTEMPTY */ + .RST(rst), // 1-bit input: Reset + // Feedback Clocks: 1-bit (each) input: Clock feedback ports + .CLKFBIN(clk_fb) // 1-bit input: Feedback clock + ); + + BUFG bufg_cpuclk(.I(cpuclk_pre), .O(cpuclk)); + BUFG bufg_refclk(.I(refclk_pre), .O(dram_refclk)); + BUFG bufg_pixclk(.I(pixclk_pre), .O(pixclk)); +endmodule diff --git a/rtl/src/display_clock.v b/rtl/src/display_clock.v new file mode 100644 index 0000000..898ef7a --- /dev/null +++ b/rtl/src/display_clock.v @@ -0,0 +1,96 @@ +`timescale 1ns / 1ps +`default_nettype none + +// Project F: Display Clocks +// (C)2019 Will Green, Open source hardware released under the MIT License +// Learn more at https://projectf.io + +// Defaults to 25.2 and 126 MHz for 640x480 at 60 Hz + +module display_clock #( + MULT_MASTER=31.5, // master clock multiplier (2.000-64.000) + DIV_MASTER=5, // master clock divider (1-106) + DIV_5X=5.0, // 5x clock divider (1-128) + DIV_1X=25, // 1x clock divider (1-128) + IN_PERIOD=10.0 // period of i_clk in ns (100 MHz = 10.0 ns) + ) + ( + input wire i_clk, // input clock + input wire i_rst, // reset (active high) + output wire o_clk_1x, // pixel clock + output wire o_clk_5x, // 5x clock for 10:1 DDR SerDes + output wire o_locked // clock locked? (active high) + ); + + wire clk_fb; // internal clock feedback + wire clk_1x_pre; + wire clk_5x_pre; + + MMCME2_BASE #( + .BANDWIDTH("OPTIMIZED"), // Jitter programming (OPTIMIZED, HIGH, LOW) + .CLKFBOUT_MULT_F(MULT_MASTER), // Multiply value for all CLKOUT (2.000-64.000). + .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000). + .CLKIN1_PERIOD(IN_PERIOD), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). + // CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128) + .CLKOUT0_DIVIDE_F(DIV_5X), // Divide amount for CLKOUT0 (1.000-128.000). + .CLKOUT1_DIVIDE(DIV_1X), + .CLKOUT2_DIVIDE(1), + .CLKOUT3_DIVIDE(1), + .CLKOUT4_DIVIDE(1), + .CLKOUT5_DIVIDE(1), + .CLKOUT6_DIVIDE(1), + // CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99). + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT6_DUTY_CYCLE(0.5), + // CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000). + .CLKOUT0_PHASE(0.0), + .CLKOUT1_PHASE(0.0), + .CLKOUT2_PHASE(0.0), + .CLKOUT3_PHASE(0.0), + .CLKOUT4_PHASE(0.0), + .CLKOUT5_PHASE(0.0), + .CLKOUT6_PHASE(0.0), + .CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE) + .DIVCLK_DIVIDE(DIV_MASTER), // Master division value (1-106) + .REF_JITTER1(0.010), // Reference input jitter in UI (0.000-0.999). + .STARTUP_WAIT("FALSE") // Delays DONE until MMCM is locked (FALSE, TRUE) + ) + MMCME2_BASE_inst ( + /* verilator lint_off PINCONNECTEMPTY */ + // Clock Outputs: 1-bit (each) output: User configurable clock outputs + .CLKOUT0(clk_5x_pre), // 1-bit output: CLKOUT0 + .CLKOUT0B(), // 1-bit output: Inverted CLKOUT0 + .CLKOUT1(clk_1x_pre), // 1-bit output: CLKOUT1 + .CLKOUT1B(), // 1-bit output: Inverted CLKOUT1 + .CLKOUT2(), // 1-bit output: CLKOUT2 + .CLKOUT2B(), // 1-bit output: Inverted CLKOUT2 + .CLKOUT3(), // 1-bit output: CLKOUT3 + .CLKOUT3B(), // 1-bit output: Inverted CLKOUT3 + .CLKOUT4(), // 1-bit output: CLKOUT4 + .CLKOUT5(), // 1-bit output: CLKOUT5 + .CLKOUT6(), // 1-bit output: CLKOUT6 + // Feedback Clocks: 1-bit (each) output: Clock feedback ports + .CLKFBOUT(clk_fb), // 1-bit output: Feedback clock + .CLKFBOUTB(), // 1-bit output: Inverted CLKFBOUT + // Status Ports: 1-bit (each) output: MMCM status ports + .LOCKED(o_locked), // 1-bit output: LOCK + // Clock Inputs: 1-bit (each) input: Clock input + .CLKIN1(i_clk), // 1-bit input: Clock + // Control Ports: 1-bit (each) input: MMCM control ports + .PWRDWN(), // 1-bit input: Power-down + /* verilator lint_on PINCONNECTEMPTY */ + .RST(i_rst), // 1-bit input: Reset + // Feedback Clocks: 1-bit (each) input: Clock feedback ports + .CLKFBIN(clk_fb) // 1-bit input: Feedback clock + ); + + // explicitly buffer output clocks + BUFG bufg_clk_pix(.I(clk_1x_pre), .O(o_clk_1x)); + BUFG bufg_clk_pix_5x(.I(clk_5x_pre), .O(o_clk_5x)); + +endmodule \ No newline at end of file diff --git a/rtl/src/dram_bridge.v b/rtl/src/dram_bridge.v new file mode 100644 index 0000000..102a8cf --- /dev/null +++ b/rtl/src/dram_bridge.v @@ -0,0 +1,165 @@ +`timescale 1ns / 1ps + +module dram_bridge #(ADDR_WIDTH = 32, WIDTH = 32) +( + // local bus + input wire [ADDR_WIDTH-1:0] mem_addr, + output wire [WIDTH-1:0] mem_read_data, + input wire [WIDTH-1:0] mem_write_data, + input wire mem_read_enable, + input wire mem_write_enable, + output wire mem_wait, + + input wire rst_n, + input wire dram_front_clk, + input wire dram_refclk, + + // DDR3 SDRAM + inout wire [15:0] ddr3_dq, + inout wire [1:0] ddr3_dqs_n, + inout wire [1:0] ddr3_dqs_p, + + output wire [13:0] ddr3_addr, + output wire [2:0] ddr3_ba, + output wire ddr3_ras_n, + output wire ddr3_cas_n, + output wire ddr3_we_n, + output wire ddr3_reset_n, + output wire [0:0] ddr3_ck_p, + output wire [0:0] ddr3_ck_n, + output wire [0:0] ddr3_cke, + output wire [0:0] ddr3_cs_n, + output wire [1:0] ddr3_dm, + output wire [0:0] ddr3_odt +); + + localparam DRAM_ADDR_WIDTH = 28, DRAM_DATA_WIDTH = 128, DRAM_MASK_WIDTH = 16; + wire [DRAM_ADDR_WIDTH-1:0] app_addr; + wire [2:0] app_cmd; + wire app_en; + wire app_rdy; + wire [DRAM_DATA_WIDTH-1:0] app_rd_data; + wire app_rd_data_end; + wire app_rd_data_valid; + wire [DRAM_DATA_WIDTH-1:0] app_wdf_data; + wire app_wdf_end; + wire [DRAM_MASK_WIDTH-1:0] app_wdf_mask; + wire app_wdf_rdy; + wire app_sr_active; + wire app_ref_ack; + wire app_zq_ack; + wire app_wdf_wren; + wire [11:0] device_temp; + wire ui_clk, ui_rst_sync; + wire init_calib_complete; + + localparam CMD_READ = 3'b1; + localparam CMD_WRITE = 3'b0; + + mig_dram_0 dram0( + // Inouts + .ddr3_dq(ddr3_dq), + .ddr3_dqs_n(ddr3_dqs_n), + .ddr3_dqs_p(ddr3_dqs_p), + // Outputs + .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(ddr3_cs_n), + .ddr3_dm(ddr3_dm), + .ddr3_odt(ddr3_odt), +// Application interface ports + .app_addr (app_addr), + .app_cmd (app_cmd), + .app_en (app_en), + .app_wdf_data (app_wdf_data), + .app_wdf_mask (app_wdf_mask), + .app_wdf_end (app_wdf_end), + .app_wdf_wren (app_wdf_wren), + .app_rd_data (app_rd_data), + .app_rd_data_end (app_rd_data_end), + .app_rd_data_valid (app_rd_data_valid), + .app_rdy (app_rdy), + .app_wdf_rdy (app_wdf_rdy), + .app_sr_req (1'b0), + .app_ref_req (1'b0), + .app_zq_req (1'b0), + .app_sr_active (app_sr_active), + .app_ref_ack (app_ref_ack), + .app_zq_ack (app_zq_ack), + .ui_clk (ui_clk), + .ui_clk_sync_rst (ui_rst_sync), + +// System Clock Ports + .sys_clk_i (dram_front_clk), +// Reference Clock Ports + .clk_ref_i (dram_refclk), + .device_temp (device_temp), + .init_calib_complete (init_calib_complete), + .sys_rst (rst_n) + ); + +// reg [DRAM_DATA_WIDTH-1:0] read_cache; +// reg [ADDR_WIDTH-1:0] cached_addr; +// wire cache_hit = cached_addr == mem_addr; +// wire [DRAM_DATA_WIDTH-1:0] read_data_wrapper = cache_hit ? read_cache : app_rd_data; + + reg [WIDTH-1:0] read_buf; + reg read_inprogress = 0; + + assign app_rd_data_end = 1'b1; + //assign app_wdf_mask = 16'b1111111111111100; + + // addresses on the memory interface are aligned to 16 bytes + // and 28 bits wide (=256MB) + assign app_addr = { mem_addr[DRAM_ADDR_WIDTH:4], 4'b0000 }; + //assign app_addr = { 28'b0 }; + + // select a word from the 128 bits transferred by the dram controller + // according to the lower bits of the address (ignoring bits 1:0) + wire [WIDTH-1:0] read_word; + wire [1:0] word_sel = mem_addr[3:2]; + + assign read_word = word_sel == 3'b11 ? app_rd_data[31:0] : + word_sel == 3'b10 ? app_rd_data[63:32] : + word_sel == 3'b01 ? app_rd_data[95:64] : + app_rd_data[127:96]; + + assign mem_read_data = app_rd_data_valid ? read_word : read_buf; + + // set the write mask according to the lower bits of the address + // (ignoring bit 0) + assign app_wdf_mask = word_sel == 3'b11 ? 16'b1111111111110000 : + word_sel == 3'b10 ? 16'b1111111100001111 : + word_sel == 3'b01 ? 16'b1111000011111111 : + 16'b0000111111111111 ; + + wire write_ready = mem_write_enable & app_wdf_rdy & app_rdy; + assign app_wdf_wren = mem_write_enable & write_ready; + assign app_wdf_end = mem_write_enable & write_ready; + assign app_wdf_data = { {4{mem_write_data}} }; + + assign mem_wait = (mem_read_enable & ~read_inprogress) | + (mem_write_enable & (~app_wdf_rdy | ~app_rdy)) | + (read_inprogress & ~app_rd_data_valid); + + assign app_en = (mem_read_enable & ~read_inprogress) | + (mem_write_enable & write_ready); + assign app_cmd = mem_read_enable ? CMD_READ : CMD_WRITE; + + always @(posedge dram_front_clk) + begin + if(mem_read_enable & ~read_inprogress & app_rdy) + read_inprogress <= 1; + if(read_inprogress & app_rd_data_valid) + read_inprogress <= 0; + if(mem_read_enable & app_rd_data_valid) + read_buf <= mem_read_data; + end +endmodule diff --git a/rtl/src/fifo.v b/rtl/src/fifo.v new file mode 100644 index 0000000..16d9583 --- /dev/null +++ b/rtl/src/fifo.v @@ -0,0 +1,53 @@ +`timescale 1ns / 1ps + +// a simple fifo +module fifo #(parameter DATA_WIDTH = 8, ADDR_WIDTH = 4)( + input wire clk, + input wire reset, + input wire wr_en, + input wire rd_en, + input wire [DATA_WIDTH-1:0] wr_data, + output wire [DATA_WIDTH-1:0] rd_data, + output wire wr_full, + output wire rd_empty + ); + + reg [DATA_WIDTH-1:0] mem [0:2**ADDR_WIDTH-1]; + reg [ADDR_WIDTH:0] head_x = 0; // head and tail have one extra bit + reg [ADDR_WIDTH:0] tail_x = 0; // for detecting overflows + wire [ADDR_WIDTH-1:0] head = head_x[ADDR_WIDTH-1:0]; + wire [ADDR_WIDTH-1:0] tail = tail_x[ADDR_WIDTH-1:0]; + + assign rd_data = mem[tail]; + // the fifo is full when head and tail pointer are the same + // and the extra bits differ (a wraparound occured) + assign wr_full = (head == tail) && (head_x[ADDR_WIDTH] != tail_x[ADDR_WIDTH]); + // the fifo is empty when head and tail pointer are the same + // and the extra bits are the same (no wraparound) + assign rd_empty = (head == tail) && (head_x[ADDR_WIDTH] == tail_x[ADDR_WIDTH]); + + // Writing to FIFO + always @(posedge clk) begin + if (reset) + head_x <= 0; + else if (wr_en) + begin + mem[head] <= wr_data; + // move head, possible wraparound + head_x <= head_x + 1'b1; + end + end + + // Reading from FIFO + always @(posedge clk) + begin + if (reset) + tail_x <= 0; + else if (rd_en) + begin + // rd_data always has current tail data + // move tail, possible wraparound + tail_x <= tail_x + 1'b1; + end + end +endmodule \ No newline at end of file diff --git a/rtl/src/fifo_testbench.v b/rtl/src/fifo_testbench.v new file mode 100644 index 0000000..ccc29ee --- /dev/null +++ b/rtl/src/fifo_testbench.v @@ -0,0 +1,116 @@ +`timescale 1ns / 1ns +`default_nettype none + +module fifo_testbench(); + // Test signals + reg clk = 0; + reg reset = 0; + reg wr_en = 0; + reg rd_en = 0; + reg [7:0] wr_data = 0; + wire [7:0] rd_data; + wire wr_full; + wire rd_empty; + + parameter CLOCK_NS = 10; + + // Unit Under Test + fifo #( + .DATA_WIDTH(8), + .ADDR_WIDTH(4) + ) UUT ( + .clk(clk), + .reset(reset), + .wr_en(wr_en), + .rd_en(rd_en), + .rd_data(rd_data), + .wr_data(wr_data), + .wr_full(wr_full), + .rd_empty(rd_empty) + ); + + // testbench clock + always + #(CLOCK_NS/2) clk <= ~clk; + + initial + begin + // issue reset + reset = 1'b1; + #10 + reset = 1'b0; + #10 + + // Write two bytes + wr_data <= 8'hAB; + wr_en <= 1'b1; + #10; + wr_data <= 8'hCD; + wr_en <= 1'b1; + #10; + wr_en <= 1'b0; + #10 + + // read fifo tail + if (rd_data == 8'hAB) + $display("Pass - Byte 1"); + else + $display("Failed - Byte 2"); + + // read/remove byte from tail + rd_en <= 1'b1; + #10 + // check next byte + if (rd_data == 8'hCD) + $display("Pass - Byte 2"); + else + $display("Failed - Byte 2"); + + // remove 2nd byte + rd_en <= 1'b1; + #10 + + rd_en <= 1'b0; + #10 + + // Write until full + rd_en <= 1'b0; + wr_en <= 1'b0; + + for (integer i = 0; i < 16; i = i + 1) begin + wr_data <= i; + wr_en <= 1'b1; + #10; + end + wr_en <= 1'b0; + + if (wr_full) + $display("Pass - Fifo full"); + else + $display("Failed - Fifo full"); + + + // read until empty + rd_en <= 1'b0; + wr_en <= 1'b0; + + for (integer i = 0; i < 16; i = i + 1) begin + rd_en <= 1'b1; + #10; + end + rd_en <= 1'b0; + + if (rd_empty) + $display("Pass - Fifo empty"); + else + $display("Failed - Fifo empty"); + $finish(); + end + + initial + begin + // Required to dump signals + $dumpfile("fifo_tb_dump.vcd"); + $dumpvars(0); + end +endmodule diff --git a/rtl/src/irqctrl.v b/rtl/src/irqctrl.v new file mode 100644 index 0000000..1a079bf --- /dev/null +++ b/rtl/src/irqctrl.v @@ -0,0 +1,73 @@ +`timescale 1ns / 1ps + +module irqctrl #(IRQ_LINES = 2, IRQ_DELAY_WIDTH = 4) ( + input wire clk, + input wire [IRQ_LINES-1:0] irq_in, + input wire cs, + input wire wr_en, + input wire irq_wr_seten, + output wire [IRQ_LINES-1:0] rd_data, + output wire irq_out + ); + + reg [IRQ_LINES-1:0] irq_status; // a 1 bit here means we have seen an interrupt on that line + reg [IRQ_LINES-1:0] irq_mask; // a bit in irq_status is only set if the corresponding bit in irq_mask is not set + // irq_mask is set from irq_status when an interrupt occurs (ie irq_out is set) + + reg irq_enabled; // globally enable/disable irq_out + reg [IRQ_DELAY_WIDTH-1:0] irq_delay; // counter to delay irq_out for a few cycles + reg irq_delaying; // delay is active + + wire irq_pending = (irq_status != 0); + + assign rd_data = irq_mask; + assign irq_out = irq_enabled && irq_pending && !irq_delaying; + + // irq_status and irq_pending flags + always @(posedge clk) + begin + if(irq_out) // when an interrupt is being signaled to the cpu, + irq_status <= 0; // clear irq status, status will be copied to irq_mask (see below) + else + if(irq_in != 0) + irq_status <= irq_status | (irq_in & ~irq_mask); // add active irq to irq_status + end + + // irq mask + always @(posedge clk) + begin + if (cs && wr_en && irq_wr_seten) // when enabling interrupts, clear mask + irq_mask <= 0; + else + if(irq_out) // when signalling an interrupt, set mask from status + irq_mask <= irq_status; + end + + // manage irq_enabled and irq_delay/irq_delaying + always @(posedge clk) + begin + if(cs && wr_en) // when writing to control register + begin + if(irq_wr_seten) // if wr_seten flag is set, enable interrupts and start delay + begin + irq_enabled <= 1; + irq_delaying <= 1; + irq_delay <= 1; + end + else + irq_enabled <= 0; // else disable interrupts + end + else if(irq_out) irq_enabled <= 0; // after sending interrupt to cpu, disable further interrupts + + if(irq_delaying) // the delay gives the CPU a chance to return from an interrupt handler + begin // if an interrupt is triggered again right after re-enabling interrupts + if(irq_delay==0) + begin + irq_delay <= 1; + irq_delaying <= 0; + end + else + irq_delay <= irq_delay + 1; + end + end + endmodule diff --git a/rtl/src/mem.v b/rtl/src/mem.v new file mode 100644 index 0000000..954443a --- /dev/null +++ b/rtl/src/mem.v @@ -0,0 +1,161 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 05.01.2021 21:53:41 +// Design Name: +// Module Name: mem +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + +// 32 bit wide rom with byte addressing (address bits 1-0 are ignored) +module rom32 #(parameter ADDR_WIDTH = 11, DATA_WIDTH = 32) +( + input wire clk, + input wire [ADDR_WIDTH-1:0] addr, + output reg [DATA_WIDTH-1:0] data_out, + input wire read_enable + ); + + wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bit 0 + reg [DATA_WIDTH-1:0] rom [0:(2**(ADDR_WIDTH-2))-1]; + + initial begin + $readmemb("C:\\Users\\sebastian\\develop\\fpga\\vdumbcpu\\rom.mem", rom); + end + + always @(posedge clk) data_out <= rom[internal_addr]; + +endmodule + +module ram32 #(parameter ADDR_WIDTH = 16, DATA_WIDTH = 32) + +( + input wire clk, + input wire [ADDR_WIDTH-1:0] addr, + output reg [DATA_WIDTH-1:0] data_out, + input wire read_enable, + input wire [DATA_WIDTH-1:0] data_in, + input wire write_enable + ); + + reg [DATA_WIDTH-1:0] ram [0:(2**(ADDR_WIDTH-2))-1]; // 32bit words with byte addressing + wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bit 1-0 + + always @(posedge clk) + begin + if(read_enable) + data_out <= ram[internal_addr]; + if(write_enable) + ram[internal_addr] <= data_in; + end +endmodule + +module mem #(parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 32) +( + input wire clk, rst_n, + input wire [ADDR_WIDTH-1:0] addr, + output wire [DATA_WIDTH-1:0] data_out, + input wire read_enable, + input wire [DATA_WIDTH-1:0] data_in, + input wire write_enable, + output wire io_enable, + input wire [DATA_WIDTH-1:0] io_rd_data, + output wire mem_wait, + + output wire [ADDR_WIDTH-1:0] dram_addr, + input wire [DATA_WIDTH-1:0] dram_read_data, + output wire [DATA_WIDTH-1:0] dram_write_data, + output wire dram_read_enable, + output wire dram_write_enable, + input wire dram_wait + ); + + wire [DATA_WIDTH-1:0] ram_out, rom_out, dram_out; + + // address map: + // ROM $0000 - $07FF 2K + // IO $0800 - $0FFF 2K + // RAM1 $1000 - $FFFF 60K + // RAM2 $10000 - $FFFFFFFF ~4GB + + wire ram_cs = addr[ADDR_WIDTH-1:12] != { {(ADDR_WIDTH-12){1'b0}}}; + wire ram1_cs = ram_cs && (addr[ADDR_WIDTH-1:16] == { {(ADDR_WIDTH-16){1'b0}}}); + wire ram2_cs = ram_cs && !ram1_cs; + wire rom_cs = !ram_cs && addr[11] == 1'b0; + wire io_cs = !ram_cs && addr[11] == 1'b1; + + assign io_enable = io_cs; + + wire ram_read = ram1_cs && read_enable; + wire ram_write = ram1_cs && write_enable; + wire rom_read = rom_cs && read_enable; + + reg [DATA_WIDTH-1:0] data_buf; + + localparam SEL_RAM1 = 0; + localparam SEL_RAM2 = 1; + localparam SEL_ROM = 2; + localparam SEL_IO = 3; + localparam SEL_ERR = 4; + + reg [1:0] out_sel; + + // test + reg [1:0] wait_state; + + ram32 #(.ADDR_WIDTH(16)) ram0 // 64KB RAM + ( + .clk(clk), + .addr(addr[15:0]), + .data_out(ram_out), + .read_enable(ram_read), + .data_in(data_in), + .write_enable(ram_write) + ); + + rom32 #(.ADDR_WIDTH(11)) rom0 // 2KB ROM + ( + .clk(clk), + .addr(addr[10:0]), + .data_out(rom_out), + .read_enable(rom_read) + ); + + assign dram_out = dram_read_data; + assign dram_addr = addr; + assign dram_write_data = data_in; + assign dram_read_enable = ram2_cs & read_enable; + assign dram_write_enable = ram2_cs & write_enable; + + assign data_out = (out_sel == SEL_RAM1 ) ? ram_out : + (out_sel == SEL_RAM2 ) ? dram_out : + (out_sel == SEL_ROM ) ? rom_out : + (out_sel == SEL_IO ) ? io_rd_data : + data_buf; + + assign mem_wait = ram2_cs && dram_wait; + + always @(posedge clk) + begin + data_buf <= data_out; + if(read_enable) out_sel <= + ram1_cs ? SEL_RAM1 : + ram2_cs ? SEL_RAM2: + rom_cs ? SEL_ROM : + io_cs ? SEL_IO : + SEL_ERR; + end +endmodule diff --git a/rtl/src/palette.v b/rtl/src/palette.v new file mode 100644 index 0000000..d076453 --- /dev/null +++ b/rtl/src/palette.v @@ -0,0 +1,28 @@ +`timescale 1ns / 1ps +// taken from https://danstrother.com/2010/09/11/inferring-rams-in-fpgas/ +// modified for one read/write-port and one read-only-port, +/// A parameterized, inferable, true dual-port, dual-clock block RAM in Verilog. + +module palette #( + parameter SLOTS_WIDTH = 4, COLOR_WIDTH = 12 +) ( + input wire wr_clk, + input wire rd_clk, + input wire wr_en, + input wire [SLOTS_WIDTH-1:0] wr_slot, + input wire [COLOR_WIDTH-1:0] wr_data, + input wire [SLOTS_WIDTH-1:0] rd_slot, + output wire [COLOR_WIDTH-1:0] rd_data +); + +// Shared memory + reg [COLOR_WIDTH-1:0] colors [(2**SLOTS_WIDTH)-1:0]; + + assign rd_data = colors[rd_slot]; + + always @(posedge wr_clk) begin + if(wr_en) colors[wr_slot] <= wr_data; + end + +endmodule + diff --git a/rtl/src/sdspi.v b/rtl/src/sdspi.v new file mode 100644 index 0000000..7141288 --- /dev/null +++ b/rtl/src/sdspi.v @@ -0,0 +1,372 @@ +`timescale 1ns / 1ps + + +// Every spi_clk_div cpu clock cycles the spi clock line is inverted. +// So a spi clock cycle is 2*spi_clk_div cpu clock cycles. +// spi_clk_count counts the cpu cycles from spi_clk_div down to zero. +// The resulting spi clock frequency is: +// (cpu clock freq) / ((sclk_count + 1) * 2) +// So for a 83.33 MHz cpu clock, we get +// spi_clk_div = 10: 83.333 / 22 = 3.788 MHz +// spi_clk_div = 124: 83.333 / 250 = 333.33 KHz + + +module sdspi( + input wire clk, // bus clock + input wire reset, + + input wire[7:0] tx_data, // data to transmit + output wire[7:0] rx_data, // data received + output wire tx_ready, // ready to write a data byte + output wire tx_empty, // transmitter fifo is empty + output wire rx_avail, // a byte has been received + output wire rx_ovr, // receiver overrun + input wire tx_write, // write strobe + input wire rx_read, // read strobe (clears rx_ovr) + + output wire card_detect, // true is card is present + output wire card_changed, // card_detect signal has changed + output wire card_busy, // card is busy (MISO/DO is 0) + + input wire ctrl_write, // set the following flags + input wire rx_filter_en, // set to discard received $FF bytes + input wire txrx_en, // enable transmitter and receiver + input wire spiclk_f_en, // enable spi clock without cs + input wire spiclk_div_wr, // set clock divider via tx_data + + // PMOD connections + output wire sd_cs_n, + output reg sd_mosi, + input wire sd_miso, + output wire sd_sck, + input wire sd_cd + ); + + localparam CLKPHASE_0A = 2'b00; + localparam CLKPHASE_0B = 2'b01; + localparam CLKPHASE_1A = 2'b10; + localparam CLKPHASE_1B = 2'b11; + reg [1:0] clk_phase; + + reg xcvr_on; // if turned off, the rest of the current byte + // will still transmitted, and until then "running" + // will be 1 + (* KEEP *) + reg running; // transmitting/receiving a byte (maybe a dummy byte) + + (* KEEP *) reg [3:0] xcvr_bitcount; // number of bits left of the current byte + + reg [7:0] tx_shifter; + wire tx_fifo_wr_en; + reg tx_fifo_rd_en; + wire tx_fifo_full; + wire tx_fifo_empty; + wire [7:0] tx_fifo_out; + + reg [7:0] rx_shifter; + reg rx_filter; + reg rx_fifo_wr_en; + wire rx_fifo_rd_en; + wire rx_fifo_full; + wire rx_fifo_empty; + wire [7:0] rx_fifo_out; + + reg rx_bit_recvd; // this flag signals a received bit + + reg rx_overrun; // byte received when rx fifo is full + + reg c_changed; + reg c_cs; + + reg spi_clk; // the spi clock signal + reg spi_clk_on; // enable clock, either via init mode or by xcvr_on + reg spi_clk_f_on; // init clock mode, i.e. start clock but no tx/rx + reg [6:0] spi_clk_count; // counting cpu clock ticks + reg [6:0] spi_clk_div; // tick counter for spi clock phases + wire spi_clk_count_z = (spi_clk_count == 7'b0); + reg hphase_start; // start of a spi clock half-phase + + assign tx_ready = !tx_fifo_full; + assign tx_empty = tx_fifo_empty; + assign rx_avail = !rx_fifo_empty; + assign rx_ovr = rx_overrun; + assign rx_data = rx_fifo_out; + + assign card_busy = (sd_miso == 0); + assign card_changed = c_changed; + + assign sd_sck = spi_clk; + assign sd_cs_n = ~c_cs; + + assign card_detect = sd_cd; + + fifo #(.ADDR_WIDTH(4)) tx_fifo(clk, reset, + tx_fifo_wr_en, tx_fifo_rd_en, + tx_data, tx_fifo_out, + tx_fifo_full, + tx_fifo_empty + ); + + fifo #(.ADDR_WIDTH(8)) rx_fifo(clk, reset, + rx_fifo_wr_en, rx_fifo_rd_en, + rx_shifter, rx_fifo_out, + rx_fifo_full, + rx_fifo_empty + ); + + // spi clock + always @(posedge clk) + begin + if(reset) + begin + spi_clk <= 1; // CLK is high when inactive + spi_clk_on <= 0; + spi_clk_count <= 0; + end + else if(spi_clk_on) + begin + + // set spi_clk at start of every half-phase + if(hphase_start) + case(clk_phase) + CLKPHASE_0A: spi_clk <= 1'b0; + CLKPHASE_0B: spi_clk <= 1'b0; + CLKPHASE_1A: spi_clk <= 1'b1; + CLKPHASE_1B: spi_clk <= 1'b1; + endcase + + if(spi_clk_count_z) + begin + spi_clk_count <= spi_clk_div; + clk_phase <= clk_phase + 2'b1; + end + else + spi_clk_count <= spi_clk_count - 7'd1; + end + + // start the clock if needed + if( (spi_clk_on == 0) && (running || spi_clk_f_on)) + begin + spi_clk_on <= 1; + spi_clk_count <= spi_clk_div; + clk_phase <= CLKPHASE_1A; + end + + // turn off the clock if transceiver not running + // and the force-clock-on flag is not set + if( (spi_clk_on == 1) && (!running && !spi_clk_f_on)) + begin + spi_clk_on <= 0; + spi_clk <= 1'b1; + end + end + + // half-phase-start flag trails spi_clk_count_z by one tick + always @(posedge clk) + begin + if(reset) + hphase_start <= 0; + else + hphase_start <= spi_clk_on && spi_clk_count_z; + end + + // handle the force clock enable flag + always @(posedge clk) + begin + if (reset) + spi_clk_f_on <= 0; + else + if (ctrl_write) + spi_clk_f_on <= spiclk_f_en; + end + + // clock divider + always @(posedge clk) + begin + if (spiclk_div_wr) spi_clk_div <= tx_data[6:0]; + end + + // card_changed flag + always @(posedge clk) + begin + if(sd_cd) + c_changed <= 1; + else if(ctrl_write || reset) + c_changed <= 0; + end + + // cs signal + always @(posedge clk) + begin + if(hphase_start && clk_phase == CLKPHASE_0A || !running) + c_cs <= running; + end + + // transmitter + always @(posedge clk) + begin + if(reset) + begin + // ???? we start the bitcount at 1 because we start + // at the second clock phase where the bitcount + // is decremented and the next byte gets loaded + xcvr_bitcount <= 0; + + tx_shifter <= 8'b1; + xcvr_on <= 0; + sd_mosi <= 1; + tx_fifo_rd_en <= 0; + end + else + begin + // handle a control write to disable the transceiver + if(ctrl_write && !txrx_en && xcvr_on) + xcvr_on <= 0; + // a byte might still be in transit, so + // we do not disable the transceiver + // immediately (see "handle running status" below) + else + // handle control write to enable the transceiver + if(ctrl_write && txrx_en && !running) + begin + xcvr_on <= 1; + xcvr_bitcount <= 0; + // next clock phase must be 1B when starting the transceiver, + // so that the first byte is loaded into the shifter then + tx_shifter <= 8'b11111111; + // in case the transceiver is enabled, but no data is in the fifo, + // initialize the shifter with $FF + end + else + // handle clock phases + if (running) + begin + if(hphase_start) + case(clk_phase) + // set mosi signal at start of clock pulse + CLKPHASE_0A: sd_mosi <= tx_shifter[7]; + CLKPHASE_0B: ; + CLKPHASE_1A: begin // shift at rising clock + tx_shifter <= tx_shifter << 1; + xcvr_bitcount <= xcvr_bitcount - 1; + end + CLKPHASE_1B: begin // in the middle of the high clock pulse, + // fetch the next byte if there are no bits + // left in the shift register + if (xcvr_bitcount == 0) + begin + if(!tx_fifo_empty) + begin + tx_shifter <= tx_fifo_out; + tx_fifo_rd_en <= 1; + end + else + tx_shifter <= 8'b11111111; + xcvr_bitcount <= 8; + end + else + tx_fifo_rd_en <= 0; + end + endcase + else + tx_fifo_rd_en <= 0; + end + end + end + + // handle data write + assign tx_fifo_wr_en = tx_write && !tx_fifo_full; + + // Enable fifo read signal if fifo is not empty. + // The data at the fifo tail is always available at + // rx_data, the read signal just moves the tail pointer + // forward. + assign rx_fifo_rd_en = rx_read && !rx_fifo_empty; + + // receiver + always @(posedge clk) + begin + if(reset) + begin + rx_bit_recvd <= 0; + rx_shifter <= 8'b11111111; + rx_fifo_wr_en <= 0; + rx_filter <= 0; + rx_overrun <= 0; + end + else + begin + // handle a control write + if(ctrl_write) + begin + rx_filter <= rx_filter_en; + rx_overrun <= 0; + if(txrx_en && !running) + rx_shifter <= 8'b0; + end + + if (running && hphase_start) + case(clk_phase) + CLKPHASE_0A: ; + CLKPHASE_0B: ; + CLKPHASE_1A: ; + CLKPHASE_1B: begin // in the middle of the high clock pulse, + // sample MISO and put into shift register + // and shift at the same time + rx_shifter <= { rx_shifter[6:0],sd_miso}; + rx_bit_recvd <= 1; + end + endcase + + if (rx_bit_recvd && !sd_cs_n && clk_phase == CLKPHASE_1B) + begin + rx_bit_recvd <= 0; + + // if a complete byte was received, bitcount will be + // 8 because the transmitter has already loaded the next byte + // at this half-phase + if (xcvr_bitcount == 8) + begin + // discard $FF bytes if filter is enabled + if(!rx_filter || rx_shifter != 8'b11111111) + begin + if(rx_fifo_full) // discard received byte if fifo is full + rx_overrun <= 1; // and set overrun flag + else + rx_fifo_wr_en <= 1; // otherwise, enable fifo write strobe, + // fifo will take data from rx_shifter + end + + // turn off filter if a byte != $FF was received + if (rx_filter && rx_shifter != 8'b11111111) + rx_filter <= 0; + end + end + else + rx_fifo_wr_en <= 0; + + end + end + + // handle running status + // (especially keep transmitter running when there are still bits left to be + // transmitted) + always@(posedge clk) + begin + if (reset) + running <= 0; + else + begin + // if we want to turn the transceiver on, set running flag + if (!running && xcvr_on) + running <= 1; + + // when running and a byte has been transmitted, + // check if we should turn the transceiver off + if (running && hphase_start && xcvr_bitcount==0) + if(clk_phase == CLKPHASE_1B) + if (!xcvr_on) + running <= 0; + end + end +endmodule diff --git a/rtl/src/sdspi_testbench.v b/rtl/src/sdspi_testbench.v new file mode 100644 index 0000000..a4113fb --- /dev/null +++ b/rtl/src/sdspi_testbench.v @@ -0,0 +1,199 @@ +`timescale 1ns / 1ns +`default_nettype none + +module sdspi_testbench(); + parameter CLOCK_NS = 10; + integer i,j; + + reg[7:0] rx_testdata[0:3]; + reg[7:0] read_data; + + // Test signals + reg clk = 0; + reg reset = 0; + + reg[7:0] tx_data = 0; + wire[7:0] rx_data; + wire tx_ready; + wire tx_empty; + wire rx_avail; + wire rx_ovr; + reg tx_write = 0; + reg rx_read = 0; + + wire card_detect; + wire card_changed; + wire card_busy; + + reg ctrl_write = 0; + reg rx_filter_en = 0; + reg txrx_en = 0; + reg spiclk_f_en = 0; + reg spiclk_div_wr = 0; + + // PMOD connections + wire sd_cs_n; + wire sd_mosi; + reg sd_miso = 1; + wire sd_sck; + reg sd_cd = 1; + + // Unit Under Test + sdspi UUT ( + .clk(clk), + .reset(reset), + .tx_data(tx_data), + .rx_data(rx_data), + .tx_ready(tx_ready), + .tx_empty(tx_empty), + .rx_avail(rx_avail), + .rx_ovr(rx_ovr), + .tx_write(tx_write), + .rx_read(rx_read), + .card_detect(card_detect), + .card_changed(card_changed), + .card_busy(card_busy), + .ctrl_write(ctrl_write), + .rx_filter_en(rx_filter_en), + .txrx_en(txrx_en), + .spiclk_f_en(spiclk_f_en), + .spiclk_div_wr(spiclk_div_wr), + .sd_cs_n(sd_cs_n), + .sd_mosi(sd_mosi), + .sd_miso(sd_miso), + .sd_sck(sd_sck), + .sd_cd(sd_cd) + ); + + // testbench clock + always + #(CLOCK_NS/2) clk <= ~clk; + + initial + begin + rx_testdata[0] <= 'hFF; + rx_testdata[1] <= 'hFF; + rx_testdata[2] <= 'hCA; + rx_testdata[3] <= 'hFE; + + // issue reset + reset = 1'b1; + #10 + reset = 1'b0; + #10 + + // set clock divider + tx_data <= 3; + spiclk_div_wr <= 1'b1; + #10 + spiclk_div_wr <= 1'b0; + #10 + + // Card initialization phase, + // cycle the clock at least 74 times + // while cs is off and mosi is high . + // we do 32 cycles + spiclk_f_en <= 1'b1; + ctrl_write <= 1'b1; + #10 + spiclk_f_en <= 1'b0; + ctrl_write <= 1'b0; + #10 + for (i=0; i<32*16; i = i + 1) + #10; + spiclk_f_en <= 1'b0; + ctrl_write <= 1'b1; + #10 + ctrl_write <= 1'b0; + #10 + for (i=0; i<32*16; i = i + 1) + #10; + + // Write two bytes + tx_data <= 8'hAB; + tx_write <= 1'b1; + #10; + tx_data <= 8'hCD; + tx_write <= 1'b1; + #10; + tx_write <= 1'b0; + #10 + + // start transceiver, enable rx_filter + txrx_en <= 1'b1; + rx_filter_en <= 1'b1; + ctrl_write <= 1'b1; + #10 + txrx_en <= 1'b0; + rx_filter_en <= 1'b0; + ctrl_write <= 1'b0; + + for (i = 0; i < 2048; i = i + 1) + begin + if (!sd_cs_n && (i % 16)==15) sd_miso <= rx_testdata[(i/(16*8)) % 4][7 - (i/16 % 8)]; + #10; + end + tx_write <= 1'b0; + #10 + + // read from rx fifo + read_data <= rx_data; + #10 + $display("read data 1: %02h", read_data); + + + // strobe rx_read to go to next byte + rx_read <= 1'b1; + #10 // one cycle to transfer the data + rx_read <= 1'b0; + #10 // we need this extra cycle for the fifo tail to move + + read_data <= rx_data; + #10 + $display("read data 2: %02h", read_data); + + // strobe rx_read to go to next byte + rx_read <= 1'b1; + #10 + rx_read <= 1'b0; + #10 // we need this extra cycle for the fifo tail to move + + read_data <= rx_data; + #10 + $display("read data 3: %02h", read_data); + + + // set flag to turn transceiver off + txrx_en <= 1'b0; + ctrl_write <= 1'b1; + #10 + ctrl_write <= 1'b0; + #10; + + // wait for the transceiver to actually turn off + for (i=0; i<32*16; i = i + 1) + #10; + + #10 + // clear rx fifo + for(i=0; i<14; i = i + 1) + begin + $display("clear fifo data %02h", rx_data); + rx_read <= 1'b1; + #10 + rx_read <= 1'b0; + #10 + #10 + #10; // simulate the four cycles of an instruction + end + + $finish(); + end + + initial + begin + // Required to dump signals + $dumpfile("sdspi_tb_dump.vcd"); + $dumpvars(0); + end +endmodule diff --git a/rtl/src/stack.v b/rtl/src/stack.v new file mode 100644 index 0000000..965c070 --- /dev/null +++ b/rtl/src/stack.v @@ -0,0 +1,42 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 17.01.2021 20:59:29 +// Design Name: +// Module Name: stack +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module stack + #(parameter ADDR_WIDTH=4, DATA_WIDTH=16) + ( + input wire clk, + input wire [ADDR_WIDTH-1:0] rd_addr, + input wire [ADDR_WIDTH-1:0] wr_addr, + input wire wr_enable, + output wire [DATA_WIDTH-1:0] rd_data, + input wire [DATA_WIDTH-1:0] wr_data + ); + + reg [DATA_WIDTH-1:0] stack[0:2**ADDR_WIDTH-1]; + + always @(posedge clk) + begin + if(wr_enable) stack[wr_addr] <= wr_data; + end + + assign rd_data = stack[rd_addr]; +endmodule diff --git a/rtl/src/stackcpu.v b/rtl/src/stackcpu.v new file mode 100644 index 0000000..c65ae4e --- /dev/null +++ b/rtl/src/stackcpu.v @@ -0,0 +1,427 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32, + WORDSIZE = 4, WORDSIZE_SHIFT = 2) ( + input wire clk, + input wire rst, + + input wire irq, + + output reg [ADDR_WIDTH-1:0] addr, + input wire [WIDTH-1:0] data_in, + output wire read_enable, + output wire [WIDTH-1:0] data_out, + output wire write_enable, + input wire mem_wait, + + output wire led1, + output wire led2, + output wire led3, + + output wire [WIDTH-1:0] debug_out1, + output wire [WIDTH-1:0] debug_out2, + output wire [WIDTH-1:0] debug_out3, + output wire [WIDTH-1:0] debug_out4, + output wire [WIDTH-1:0] debug_out5, + output wire [WIDTH-1:0] debug_out6 + ); + + localparam EVAL_STACK_INDEX_WIDTH = 6; + + wire reset = !rst; + + (* KEEP *) reg [1:0] seq_state; + localparam FETCH = 2'b00; localparam DECODE = 2'b01; localparam EXEC = 2'b10; localparam MEM = 2'b11; + + (* KEEP*) reg [WIDTH-1:0] X, nX; + wire [WIDTH-1:0] Y; + (* KEEP *) reg [WIDTH-1:0] PC, nPC; + reg [WIDTH-1:0] RP, nRP; + reg [WIDTH-1:0] FP, BP; + reg [WIDTH-1:0] IV,IR; + + wire [WIDTH-1:0] pc_next_ins = PC + 2; + + reg [EVAL_STACK_INDEX_WIDTH-1:0] ESP, nESP; + reg stack_write; + + reg irq_pending; + + // eval stack + stack #(.ADDR_WIDTH(EVAL_STACK_INDEX_WIDTH), .DATA_WIDTH(WIDTH)) estack ( + .clk(clk), + .rd_addr(ESP), + .wr_addr(nESP), + .wr_enable(stack_write), + .rd_data(Y), + .wr_data(X) + ); + + reg [15:0] ins; + + wire [WIDTH-1:0] operand; + + // decoded instructions + wire ins_loadrel; + wire ins_load; + wire ins_loadc; + wire ins_store; + wire ins_aluop; + wire ins_ext; + wire ins_xfer; + wire ins_branch; + wire ins_cbranch; + + // decoded extended instructions + wire ins_mem, ins_loadi, ins_storei; + wire ins_fpadj; + wire ins_reg, ins_loadreg, ins_storereg; + wire ins_reg_fp, ins_reg_bp, ins_reg_rp; + wire ins_reg_iv, ins_reg_ir; + wire ins_reg_esp; + wire loadstore_base; + wire cbranch_n; + + wire xfer_x2p, xfer_r2p, xfer_p2r; + wire [1:0] xfer_rs; + + wire [3:0] aluop; + wire [1:0] aluop_sd; + wire aluop_x2y, aluop_ext; + + wire cmp_i, cmp_e, cmp_l; + + wire mem_read; + wire mem_write; + + wire x_is_zero; + // wire [WIDTH-1:0] y_plus_operand = Y + operand; + + wire x_equals_y = X == Y; + wire y_lessthan_x = $signed(Y) < $signed(X); + wire yx_unsigned_less = Y < X; + + reg [WIDTH-1:0] mem_write_data; + + wire mem_read_enable, mem_write_enable; + + assign read_enable = mem_read_enable; + assign data_out = mem_write_data; + assign write_enable = mem_write_enable; + + // debug output ------------------------------------------------------------------------------------ + assign led1 = reset; + assign led2 = ins_loadc; + assign led3 = ins_branch; +// assign debug_out1 = { mem_read_enable, mem_write_enable, x_is_zero, +// ins_branch, ins_aluop, y_lessthan_x, x_equals_y, {7{1'b0}}, seq_state}; +// assign debug_out2 = data_in; +// assign debug_out3 = nX; +// assign debug_out4 = nPC; +// assign debug_out5 = ins; +// assign debug_out6 = IV; + //-------------------------------------------------------------------------------------------------- + + // instruction decoding + assign ins_branch = (ins[15:13] == 3'b000); + assign ins_aluop = (ins[15:13] == 3'b001); + assign ins_store = (ins[15:13] == 3'b010); + assign ins_xfer = (ins[15:13] == 3'b011); + assign ins_load = (ins[15:13] == 3'b100); + assign ins_cbranch = (ins[15:13] == 3'b101); + assign ins_loadc = (ins[15:13] == 3'b110); + assign ins_ext = (ins[15:13] == 3'b111); + + // sub-decode LOAD/STORE + assign loadstore_base = ins[0]; + + // sub-decode CBRANCH + assign cbranch_n = ins[0]; + + // sub-decode XFER + assign xfer_x2p = ins[0]; + assign xfer_r2p = ins[7]; + assign xfer_p2r = ins[6]; + assign xfer_rs = ins[9:8]; + + // sub-decode OP + assign aluop = ins[12:9]; + assign aluop_x2y = ins[6]; + assign aluop_sd = ins[5:4]; + assign aluop_ext = ins[7]; + + // sub-decode OP.CMP + assign cmp_i = ins[2]; + assign cmp_e = ins[1]; + assign cmp_l = ins[0]; + + assign x_is_zero = X == {WIDTH{1'b0}}; + + // decode extended instructions + assign ins_reg = (ins_ext && ins[12:10] == 3'b000); + assign ins_mem = (ins_ext && ins[12:10] == 3'b001); + assign ins_loadi = (ins_mem && ins[9] == 1'b0); + assign ins_storei = (ins_mem && ins[9] == 1'b1); + assign ins_fpadj = (ins_ext && ins[12:10] == 3'b011); + assign ins_loadrel= (ins_ext && ins[12:10] == 3'b101); + + // sub-decode LOADREG/STOREREG + assign ins_loadreg = (ins_reg && ins[9] == 1'b0); + assign ins_storereg = (ins_reg && ins[9] == 1'b1); + assign ins_reg_fp = (ins_reg && ins[3:0] == 4'b0000); + assign ins_reg_bp = (ins_reg && ins[3:0] == 4'b0001); + assign ins_reg_rp = (ins_reg && ins[3:0] == 4'b0010); + assign ins_reg_iv = (ins_reg && ins[3:0] == 4'b0011); + assign ins_reg_ir = (ins_reg && ins[3:0] == 4'b0100); + assign ins_reg_esp = (ins_reg && ins[3:0] == 4'b0101); + + assign mem_read = ins_loadi || ins_load || ins_loadrel || (ins_xfer && xfer_r2p); + assign mem_write = ins_storei || ins_store || (ins_xfer && xfer_p2r); + + assign mem_read_enable = (seq_state == FETCH) || (seq_state == EXEC && mem_read); + assign mem_write_enable = (seq_state == MEM && mem_write); + + initial + begin + PC <= 0; nPC <= 0; seq_state <= MEM; + ESP <= -1; nESP <= -1; + addr <= 0; + FP <= 0; BP <= 0; RP <= 0; nRP <= 0; + IV <= 0; IR <= 0; + irq_pending <= 0; + end + + // instruction sequencer + always @(posedge clk) + begin + if(reset) + seq_state <= MEM; + else if(mem_wait == 1'b0) + case(seq_state) + FETCH: seq_state <= DECODE; + DECODE: seq_state <= EXEC; + EXEC: seq_state <= MEM; + MEM: seq_state <= FETCH; + default: seq_state <= FETCH; + endcase + end + + // operand register + assign operand = + (ins_load || ins_store || ins_branch || ins_cbranch) ? + { {(WIDTH-13){ins[12]}}, ins[12:1], 1'b0 } + : (ins_loadc) ? { {(WIDTH-13){ins[12]}}, ins[12:0] } // sign extend + : (ins_aluop || ins_mem) ? + { {(WIDTH-4){1'b0}}, ins[3:0] } + : (ins_loadrel) ? { {(WIDTH-10){1'b0}}, ins[9:0] } + : (ins_fpadj) ? { {(WIDTH-10){ins[9]}}, ins[9:0] } // sign extend + : { {WIDTH{1'b0}} }; + + // program counter + always @(posedge clk) + begin + if(reset) nPC <= 0; + else + case(seq_state) + EXEC: + if(ins_xfer && xfer_x2p) nPC <= X; + else if(ins_branch || (ins_cbranch && (x_is_zero != cbranch_n))) nPC <= PC + operand; + else nPC <= pc_next_ins; + MEM: + if(ins_xfer && xfer_r2p) nPC <= data_in; + else if(irq_pending) nPC <= IV; + endcase + end + + // return stack pointer + always @* + begin + if(seq_state == EXEC || seq_state == DECODE || seq_state == MEM) + begin + if (ins_xfer) nRP <= RP + + ({ {(ADDR_WIDTH-3){xfer_rs[1]}},xfer_rs} << WORDSIZE_SHIFT); + // sign extend xfer_rs and multiply by word size + else if (ins_storereg && ins_reg_rp) nRP <= X; + else nRP <= RP; + end + else nRP <= nRP; + end + + // instruction fetch + // depending on bit 1 of the PC, read either the upper or lower half word as an instruction + always @* if(seq_state == DECODE) ins <= PC[1] ? data_in[15:0] : data_in[31:16]; + + // RAM read/write + always @(posedge clk) + begin + if(reset) + begin + addr <= 0; + mem_write_data <= 0; + end + else + case(seq_state) + DECODE: + if(ins_load || ins_store) // read from address in BP/FP + offset + addr <= operand + ( loadstore_base ? BP: FP); + else if (ins_loadi) // read from address in X + addr <= X; + else if (ins_storei) // write to address in Y + addr <= Y; + else if (ins_loadrel) // read from address next to current instruction + addr <= PC + operand; + else if (ins_xfer && xfer_r2p) // read from return stack + addr <= RP; // use the current RP + else if (ins_xfer && xfer_p2r) // write to return stack + addr <= nRP; // use the new RP + EXEC: + begin + if (ins_store) + mem_write_data <= X; + else if (ins_storei) + mem_write_data <= X; + else if (ins_xfer && xfer_p2r) + mem_write_data <= pc_next_ins; + else + mem_write_data <= 0; + end + MEM: + if(!mem_wait) // do not change the address if mem_wait is active + begin + if(ins_xfer && xfer_r2p) addr <= data_in; // on RET take addr for next instruction from the data we just read from mem + else addr <= irq_pending ? IV : nPC; // prepare fetch cycle + end + endcase + end + + // X/ToS-Register + always @(posedge clk) + begin + if(reset) nX <= 0; + else + case(seq_state) + // default: nX <= X; + FETCH, DECODE:; + EXEC: + if(ins_loadc) nX <= operand; + else if(ins_cbranch || ins_store || ins_storereg || (ins_xfer && xfer_x2p)) nX <= Y; + else if(ins_storei) nX <= Y + operand; + else if(ins_loadreg && ins_reg_fp) nX <= FP; + else if(ins_loadreg && ins_reg_bp) nX <= BP; + else if(ins_loadreg && ins_reg_rp) nX <= RP; + else if(ins_loadreg && ins_reg_iv) nX <= IV; + else if(ins_loadreg && ins_reg_ir) nX <= IR; + else if(ins_loadreg && ins_reg_esp) nX <= ESP; + else if(ins_aluop) + begin + case(aluop) + 4'b0000: nX = X + Y; // ADD + 4'b0001: nX = Y - X; // SUB + 4'b0010: nX = ~X; // NOT + 4'b0011: nX = X & Y; // AND + 4'b0100: nX = X | Y; // OR + 4'b0101: nX = X ^ Y; // XOR + 4'b0110: nX = // CMP + cmp_i ^ ((cmp_e && x_equals_y) || (cmp_l && y_lessthan_x)); + 4'b0111: nX = Y; // Y + 4'b1000: nX = aluop_ext ? X >>> 1 : X >> 1; // SHR + 4'b1001: nX = operand[1] ? X << 2 : X << 1; // SHL + 4'b1010: nX = X + operand; // INC + 4'b1011: nX = X - operand; // DEC + 4'b1100: nX = // CMPU + cmp_i ^ ((cmp_e && x_equals_y) || (cmp_l && yx_unsigned_less)); + // 4'b1101: nX = X[7:0] << ((3 - Y[1:0]) << 3); // BPLC + 4'b1101: nX = Y[1:0] == 0 ? { X[7:0], 24'b0 } : + Y[1:0] == 1 ? { 8'b0, X[7:0], 16'b0 } : + Y[1:0] == 2 ? { 16'b0, X[7:0], 8'b0 } : + { 24'b0, X[7:0]}; // BPLC + 4'b1110: nX = { X[23:16], X[15:8], X[7:0], X[31:24] }; // BROT + 4'b1111: nX = { 24'b0, Y[1:0] == 0 ? X[31:24] : Y[1:0] == 1 ? X[23:16] : + Y[1:0] == 2 ? X[15: 8] : X[7:0] }; // BSEL +// 4'b1110: nX = X * Y; // MUL +// 4'b1111: nX = X / Y; // DIV + default: nX = X; + endcase + end + MEM: + if (ins_loadi || ins_load || ins_loadrel) + nX = data_in; + endcase + end + + // estack movement + wire [EVAL_STACK_INDEX_WIDTH-1:0] delta = + ((ins_load || ins_loadc || ins_loadreg || ins_loadrel)) ? 1 + : ((ins_aluop || ins_loadi || ins_storei || ins_xfer)) ? + { {(EVAL_STACK_INDEX_WIDTH-2){aluop_sd[1]}},aluop_sd} // sign extend + : ((ins_store || ins_cbranch || ins_xfer || ins_storereg)) ? -1 + : 0; + + + always @* + begin + if(reset) + nESP <= 0; + else + if(seq_state == EXEC) + begin + nESP = ESP + delta; + end + end + + always @(posedge clk) + begin + // when to write (old) X back to stack (new Y) + // stack write is a reg so it is 1 in the next cycle i.e. MEM state + stack_write <= (seq_state == EXEC && + (ins_load || ins_loadc || ins_loadrel || ins_loadreg + || ((ins_loadi || ins_storei || ins_aluop) && aluop_x2y))); + end + + // FP register + always @(posedge clk) + begin + if(seq_state == EXEC) + begin + if(ins_fpadj) FP <= FP + operand; + else if(ins_storereg && ins_reg_fp) FP <= X; + end + end + + // BP register + always @(posedge clk) if(seq_state == EXEC && ins_storereg && ins_reg_bp) BP <= X; + + // IV register + always @(posedge clk) + begin + if(reset) + IV <= 0; + else if(seq_state == EXEC && ins_storereg && ins_reg_iv) + IV <= X; + end + + // IR register + always @(posedge clk) + begin + if(seq_state == MEM && irq_pending) IR <= nPC; // use nPC as interrupt return addr + end + + // process irq + always @(posedge clk) + begin + if(seq_state == MEM && irq_pending && !(ins_xfer & xfer_r2p)) // in FETCH state, clear irq_pending. + irq_pending <= 0; + else + irq_pending <= irq_pending || irq; // else set irq_pending when irq is high + end + + // advance CPU state + always @ (posedge clk) + begin + if(reset) + { PC, X, ESP, RP } <= { {WIDTH{1'b0}}, {WIDTH{1'b0}}, {WIDTH{1'b0}}, {WIDTH{1'b0}} }; + else if(seq_state == FETCH) + { PC, X, ESP, RP } <= { nPC, nX, nESP, nRP}; + end +endmodule diff --git a/rtl/src/testbench.v b/rtl/src/testbench.v new file mode 100644 index 0000000..8d26bb4 --- /dev/null +++ b/rtl/src/testbench.v @@ -0,0 +1,54 @@ +`timescale 1ns/1ps +`default_nettype none + +module testbench(); + reg clk; + reg rst_n; + wire btn0; + wire sw0; + wire sw1; + wire led0; + wire led1; + wire led2; + wire led3; + wire uart_txd_in; + wire uart_rxd_out; + + wire [15:0] ddr3_dq; + wire [1:0] ddr3_dqs_n; + wire [1:0] ddr3_dqs_p; + wire [13:0] ddr3_addr; + wire [2:0] ddr3_ba; + wire ddr3_ras_n; + wire ddr3_cas_n; + wire ddr3_we_n; + wire ddr3_reset_n; + wire [0:0] ddr3_ck_p; + wire [0:0] ddr3_ck_n; + wire [0:0] ddr3_cke; + wire [0:0] ddr3_cs_n; + wire [1:0] ddr3_dm; + wire [0:0] ddr3_odt; + + integer t; + + top top0(clk, rst_n, btn0, sw0,sw1, led0, led1, led2, led3, uart_txd_in, uart_rxd_out, + ddr3_dq, ddr3_dqs_n, ddr3_dqs_p, ddr3_addr, ddr3_ba, ddr3_ras_n, ddr3_cas_n, + ddr3_we_n, ddr3_reset_n, ddr3_ck_p, ddr3_ck_n, ddr3_cke, ddr3_cs_n, ddr3_dm, ddr3_odt); + + initial begin + clk = 1; + t = 0; + rst_n = 0; + end + + always #5.0 clk = ~clk; + + always @(posedge clk) begin + t <= t + 1; + if (t == 2) + rst_n = 1; + if (t == 400) + $finish; + end +endmodule diff --git a/rtl/src/top.v b/rtl/src/top.v new file mode 100644 index 0000000..e79d611 --- /dev/null +++ b/rtl/src/top.v @@ -0,0 +1,288 @@ +`timescale 1ns / 1ps +// either define clock as clk (100MHz on Arty) +// or as clk_1hz for debugging + +`define clock cpuclk +`define clkfreq 83333333 +//`define clock clk +//`define clkfreq 100000000 +//`define clock clk_1hz +`define ENABLE_VGAFB +`define ENABLE_MICROSD + +module top( + input wire clk, + input wire rst, + input wire btn0, + input wire sw0, + input wire sw1, + output wire led0, + output wire led1, + output wire led2, + output wire led3, + input wire uart_txd_in, + output wire uart_rxd_out, + + // DDR3 SDRAM + inout wire [15:0] ddr3_dq, + inout wire [1:0] ddr3_dqs_n, + inout wire [1:0] ddr3_dqs_p, + + output wire [13:0] ddr3_addr, + output wire [2:0] ddr3_ba, + output wire ddr3_ras_n, + output wire ddr3_cas_n, + output wire ddr3_we_n, + output wire ddr3_reset_n, + output wire [0:0] ddr3_ck_p, + output wire [0:0] ddr3_ck_n, + output wire [0:0] ddr3_cke, + output wire [0:0] ddr3_cs_n, + output wire [1:0] ddr3_dm, + output wire [0:0] ddr3_odt + +`ifdef ENABLE_VGAFB + , + output wire [3:0] VGA_R, + output wire [3:0] VGA_G, + output wire [3:0] VGA_B, + + output wire VGA_HS_O, + output wire VGA_VS_O +`endif + +`ifdef ENABLE_MICROSD + , + output wire sd_cs_n, + output wire sd_mosi, + input wire sd_miso, + output wire sd_sck, + input wire sd_cd +`endif +); + + reg clk_1hz; + reg [31:0] counter; + + localparam ADDR_WIDTH = 32, WIDTH = 32, + ROMADDR_WIDTH = 11, IOADDR_WIDTH = 11, IOADDR_SEL = 4; + + wire [ADDR_WIDTH-1:0] mem_addr; + wire [WIDTH-1:0] mem_read_data; + wire [WIDTH-1:0] mem_write_data; + (* KEEP *) wire mem_wait; + + (* KEEP *) wire mem_read_enable; + (* KEEP *) wire mem_write_enable; + (* KEEP *) wire io_enable; + wire [WIDTH-1:0] io_rd_data; + wire [IOADDR_SEL-1:0] io_slot = mem_addr[IOADDR_WIDTH-1:IOADDR_WIDTH-IOADDR_SEL]; + + wire irq; + + // assign led0 = mem_wait; + + wire [WIDTH-1:0] debug_data1, debug_data2, + debug_data3, debug_data4, + debug_data5, debug_data6; + + assign led0 = debug_data6[0]; + + wire cpuclk, cpuclk_locked; + wire dram_refclk200; + wire pixclk; + cpu_clkgen cpuclk_0(~rst, clk, cpuclk, dram_refclk200, pixclk, cpuclk_locked); + + // DRAM -------------------------------------------------------------------------- + wire [ADDR_WIDTH-1:0] dram_addr; + wire [WIDTH-1:0] dram_read_data, dram_write_data; + wire dram_read_enable, dram_write_enable, dram_wait; + + dram_bridge dram_bridge0 (dram_addr, + dram_read_data, dram_write_data, dram_read_enable, dram_write_enable, dram_wait, + rst, cpuclk, dram_refclk200, + ddr3_dq, ddr3_dqs_n, ddr3_dqs_p, ddr3_addr, + ddr3_ba, ddr3_ras_n, ddr3_cas_n, ddr3_we_n, + ddr3_reset_n, ddr3_ck_p, ddr3_ck_n, ddr3_cke, + ddr3_cs_n, ddr3_dm, ddr3_odt); + + mem #(.ADDR_WIDTH(ADDR_WIDTH), .DATA_WIDTH(WIDTH)) mem0( + .clk(`clock), .rst_n(rst), .addr(mem_addr), + .data_out(mem_read_data), .read_enable(mem_read_enable), + .data_in(mem_write_data), .write_enable(mem_write_enable), + .io_enable(io_enable), + .io_rd_data(io_rd_data), + .mem_wait(mem_wait), + .dram_addr(dram_addr), + .dram_read_data(dram_read_data), + .dram_write_data(dram_write_data), + .dram_read_enable(dram_read_enable), + .dram_write_enable(dram_write_enable), + .dram_wait(dram_wait) + ); + +`ifdef ENABLE_VGAFB + localparam FB_ADDR_WIDTH = 14; + wire [FB_ADDR_WIDTH-1:0] fb_rd_addr; + wire [FB_ADDR_WIDTH-1:0] fb_wr_addr; + wire [WIDTH-1:0] fb_rd_data; + wire [WIDTH-1:0] fb_wr_data; + wire fb_rd_en, fb_wr_en; + + wire fb_cs_en = io_enable && (io_slot == 2); + + assign fb_rd_en = fb_cs_en && mem_read_enable; + assign fb_wr_en = fb_cs_en && mem_write_enable; + assign fb_wr_data = mem_write_data; + + vgafb vgafb0(`clock, pixclk, rst, + mem_addr[3:0], fb_rd_data, fb_wr_data, + fb_rd_en, fb_wr_en, + VGA_HS_O, VGA_VS_O, VGA_R, VGA_G, VGA_B); +`endif + + // SPI SD card controller ------------------------------------------------------------------- +`ifdef ENABLE_MICROSD + wire [7:0] spi_tx_data; + (*KEEP*) wire [7:0] spi_rx_data; + wire spi_tx_ready; // ready to transmit new data + wire spi_tx_empty; // tx fifo is empty + wire spi_rx_avail; // a byte has been received + wire spi_rx_ovr; // receiver overrun + wire spi_tx_write; // write strobe + wire spi_rx_read; // read strobe (clears rx_avail) + + wire spi_card_detect; // true is card is present + wire spi_card_changed; // card_detect signal has changed + wire spi_card_busy; // card is busy (MISO/DO is 0) + + wire spi_ctrl_write; // set the following flags + wire spi_rx_filter_en; // set to wait for start bit (1-to-0) when receiving + wire spi_txrx_en; // enable transmitter and receiver + wire spi_sclk_f_en; // enable spi clock without transceiver + wire spi_sclk_div_wr; // set clock divider from tx_data + + wire spi_cs; // cs signal for spi controller + wire [WIDTH-1:0] spi_rd_data; + + assign spi_cs = io_enable && (io_slot == 1); + + // spi read data: [ 0,...,0,cd,cc,cb,tr,te,ra,ro,d,d,d,d,d,d,d,d ] + // cd = card detect, cc = card changed, cb = card busy, + // tr = transmitter ready, te = tx fifo empty, + // ra = received byte available, ro = receive overrun, d = received byte + assign spi_rd_data = + { {WIDTH-15{1'b0}}, spi_card_detect, spi_card_changed, spi_card_busy, + spi_tx_ready, spi_tx_empty, + spi_rx_avail, spi_rx_ovr, spi_rx_data }; + + // spi write data: [ 0,...,0,CW,CF,Cx,Cc,Cd,DR,DW,d,d,d,d,d,d,d,d ] + // CW = control write, CF = enable receive filter, Cx = enable transceiver, + // Cc = force spi clock on, Cd = write clock divider, + // DR = read acknowledge, DW = data write, d = byte to be sent + assign spi_ctrl_write = spi_cs && mem_write_enable && mem_write_data[14]; + assign spi_rx_filter_en = mem_write_data[13]; + assign spi_txrx_en = mem_write_data[12]; + assign spi_sclk_f_en = mem_write_data[11]; + assign spi_sclk_div_wr = spi_cs && mem_write_enable && mem_write_data[10]; + assign spi_rx_read = mem_write_data[9]; + assign spi_tx_write = spi_cs && mem_write_enable && mem_write_data[8]; + assign spi_tx_data = mem_write_data[7:0]; + + sdspi sdspi0(.clk(`clock), .reset(~rst), + .tx_data(spi_tx_data), .rx_data(spi_rx_data), + .tx_ready(spi_tx_ready), .tx_empty(spi_tx_empty), + .rx_avail(spi_rx_avail), .rx_ovr(spi_rx_ovr), + .tx_write(spi_tx_write), .rx_read(spi_rx_read), + .card_detect(spi_card_detect), .card_changed(spi_card_changed), .card_busy(spi_card_busy), + // ctrl_write is used with rx_filter_en, txrx_en and spiclk_f_en + .ctrl_write(spi_ctrl_write), + .rx_filter_en(spi_rx_filter_en), .txrx_en(spi_txrx_en), .spiclk_f_en(spi_sclk_f_en), + // + .spiclk_div_wr(spi_sclk_div_wr), + .sd_cs_n(sd_cs_n), + .sd_mosi(sd_mosi), .sd_miso(sd_miso), .sd_sck(sd_sck), .sd_cd(sd_cd)); +`endif + + // UART ----------------------------------------------------------------------- + + // uart write data: [ 0, 0, 0, 0, 0, T, C, 0, c, c, c, c, c, c, c, c ] + // T = transmit enable, C = receiver clear, c = 8-bit-character + // uart read data: [ 0, 0, 0, 0, 0, 0, A, B, c, c, c, c, c, c, c, c ] + // A = char available, B = tx busy, c = 8-bit-character + wire uart_cs = io_enable && (io_slot == 0); + wire uart_tx_en = uart_cs && mem_write_enable && mem_write_data[10]; + wire uart_rx_clear = uart_cs && mem_write_enable && mem_write_data[9]; + wire uart_rx_avail; + wire uart_rx_busy, uart_tx_busy; + wire uart_err; + wire [7:0] uart_rx_data; + wire [7:0] uart_tx_data; + wire [31:0] uart_baud = 32'd115200; + wire [WIDTH-1:0] uart_rd_data; + + assign uart_tx_data = mem_write_data[7:0]; + assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data }; + + reg timer_tick; + reg[23:0] tick_count; + wire [1:0] irq_in = { timer_tick, uart_rx_avail }; + wire [1:0] irqc_rd_data0; + wire [WIDTH-1:0] irqc_rd_data = { tick_count, 6'b0, irqc_rd_data0 }; + wire irqc_seten = mem_write_data[7]; + wire irqc_cs = io_enable && (io_slot == 3); + + assign io_rd_data = (io_slot == 0) ? uart_rd_data : + `ifdef ENABLE_MICROSD + (io_slot == 1) ? spi_rd_data : + `endif + `ifdef ENABLE_VGAFB + (io_slot == 2) ? fb_rd_data : + `endif + (io_slot == 3) ? irqc_rd_data: + + -1; + + buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst, + uart_baud, + uart_txd_in, uart_rxd_out, + uart_rx_clear, uart_tx_en, + uart_rx_avail, uart_tx_busy, + uart_tx_data, uart_rx_data); + + // CPU ----------------------------------------------------------------- + stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq), + .addr(mem_addr), + .data_in(mem_read_data), .read_enable(mem_read_enable), + .data_out(mem_write_data), .write_enable(mem_write_enable), + .mem_wait(mem_wait), + .led1(led1), .led2(led2), .led3(led3), + .debug_out1(debug_data1), + .debug_out2(debug_data2), + .debug_out3(debug_data3), + .debug_out4(debug_data4), + .debug_out5(debug_data5), + .debug_out6(debug_data6)); + + // Interrupt Controller + irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable, + irqc_seten, irqc_rd_data0, + irq); + + // count clock ticks + // generate interrupt every 20nth of a second + always @ (posedge `clock) + begin + counter <= counter + 1; + if (counter >= (`clkfreq/20)) + begin + counter <= 0; + timer_tick <= 1; + tick_count <= tick_count + 1'b1; + end + else + begin + timer_tick <= 0; + end + end +endmodule diff --git a/rtl/src/uart.v b/rtl/src/uart.v new file mode 100644 index 0000000..fec26a3 --- /dev/null +++ b/rtl/src/uart.v @@ -0,0 +1,262 @@ +/* +Copyright (c) 2010-2020, James Bowman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of swapforth nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +`default_nettype none +//`define def_clkfreq 100000000 +`define def_clkfreq 83333333 + +module baudgen( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire restart, + output wire ser_clk); + parameter CLKFREQ = `def_clkfreq; + + wire [38:0] aclkfreq = CLKFREQ; + reg [38:0] d; + wire [38:0] dInc = d[38] ? ({4'd0, baud}) : (({4'd0, baud}) - aclkfreq); + wire [38:0] dN = restart ? 0 : (d + dInc); + wire fastclk = ~d[38]; + assign ser_clk = fastclk; + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + d <= 0; + end else begin + d <= dN; + end + end +endmodule + +/* + +-----+ +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- + | | | | | | | | | | | | + |start| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |stop1|stop2| + | | | | | | | | | | | ? | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + + +*/ + +module uart( + input wire clk, // System clock + input wire resetq, + + // Outputs + output wire uart_busy, // High means UART is transmitting + output reg uart_tx, // UART transmit wire + // Inputs + input wire [31:0] baud, + input wire uart_wr_i, // Raise to transmit byte + input wire [7:0] uart_dat_i // 8-bit data +); + parameter CLKFREQ = `def_clkfreq; + + reg [3:0] bitcount; + reg [8:0] shifter; + + assign uart_busy = |bitcount; + wire sending = |bitcount; + + wire ser_clk; + + wire starting = uart_wr_i & ~uart_busy; + baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( + .clk(clk), + .resetq(resetq), + .baud(baud), + .restart(1'b0), + .ser_clk(ser_clk)); + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + uart_tx <= 1; + bitcount <= 0; + shifter <= 0; + end else begin + if (starting) begin + shifter <= { uart_dat_i[7:0], 1'b0 }; + bitcount <= 1 + 8 + 1; + end + + if (sending & ser_clk) begin + { shifter, uart_tx } <= { 1'b1, shifter }; + bitcount <= bitcount - 4'd1; + end + end + end + +endmodule + +module rxuart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire uart_rx, // UART recv wire + input wire rd, // read strobe + output wire valid, // has data + output wire [7:0] data); // data + parameter CLKFREQ = `def_clkfreq; + + reg [4:0] bitcount; + reg [7:0] shifter; + + // On starting edge, wait 3 half-bits then sample, and sample every 2 bits thereafter + + wire idle = &bitcount; + wire sample; + reg [2:0] hh = 3'b111; + wire [2:0] hhN = {hh[1:0], uart_rx}; + wire startbit = idle & (hhN[2:1] == 2'b10); + wire [7:0] shifterN = sample ? {hh[1], shifter[7:1]} : shifter; + + wire ser_clk; + baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( + .clk(clk), + .baud({baud[30:0], 1'b0}), + .resetq(resetq), + .restart(startbit), + .ser_clk(ser_clk)); + + assign valid = (bitcount == 18); + reg [4:0] bitcountN; + always @* + if (startbit) + bitcountN = 0; + else if (!idle & !valid & ser_clk) + bitcountN = bitcount + 5'd1; + else if (valid & rd) + bitcountN = 5'b11111; + else + bitcountN = bitcount; + + // 3,5,7,9,11,13,15,17 + assign sample = (bitcount > 2) & bitcount[0] & !valid & ser_clk; + assign data = shifter; + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + hh <= 3'b111; + bitcount <= 5'b11111; + shifter <= 0; + end else begin + hh <= hhN; + bitcount <= bitcountN; + shifter <= shifterN; + end + end +endmodule + +module fifo_rxuart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire uart_rx, // UART recv wire + input wire rd, // read strobe + output wire valid, // has data + output wire [7:0] data); // data + parameter CLKFREQ = `def_clkfreq; + + localparam ADDR_WIDTH = 6; + localparam DATA_WIDTH = 8; + + reg fifo_wr_en; + (*KEEP*) wire fifo_rd_en, fifo_full, fifo_empty; + wire [DATA_WIDTH-1:0] fifo_wr_data, fifo_rd_data; + (*KEEP*) wire rx_avail; + + assign valid = !fifo_empty; + assign data = fifo_rd_data; + assign fifo_rd_en = rd; + + fifo #(.ADDR_WIDTH(ADDR_WIDTH)) rx_fifo(clk, ~resetq, + fifo_wr_en, fifo_rd_en, + fifo_wr_data, fifo_rd_data, + fifo_full, + fifo_empty + ); + + rxuart #(.CLKFREQ(CLKFREQ)) _rx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_rx(uart_rx), + .rd(fifo_wr_en), // strobe read signal on fifo write + .valid(rx_avail), + .data(fifo_wr_data)); + + always @(posedge clk) + begin + if (!resetq) + fifo_wr_en <= 0; + else if(!fifo_wr_en && rx_avail) // ILA shows fifo_wr_en stays 0 ?? + fifo_wr_en <= 1; // pulse fifo_wr_en for one clock + else // rx_avail goes zero one clock later + fifo_wr_en <= 0; + end +endmodule + +module buart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire rx, // recv wire + output wire tx, // xmit wire + input wire rd, // read strobe + input wire wr, // write strobe + output wire valid, // has recv data + output wire busy, // is transmitting + input wire [7:0] tx_data, + output wire [7:0] rx_data // data +); + parameter CLKFREQ = `def_clkfreq; + + fifo_rxuart #(.CLKFREQ(CLKFREQ)) _rx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_rx(rx), + .rd(rd), + .valid(valid), + .data(rx_data)); + uart #(.CLKFREQ(CLKFREQ)) _tx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_busy(busy), + .uart_tx(tx), + .uart_wr_i(wr), + .uart_dat_i(tx_data)); +endmodule diff --git a/rtl/src/uart_tb.v b/rtl/src/uart_tb.v new file mode 100644 index 0000000..7f794a2 --- /dev/null +++ b/rtl/src/uart_tb.v @@ -0,0 +1,100 @@ +////////////////////////////////////////////////////////////////////// +// File Downloaded from http://www.nandland.com +////////////////////////////////////////////////////////////////////// + +// This testbench will exercise both the UART Tx and Rx. +// It sends out byte 0xAB over the transmitter +// It then exercises the receive by receiving byte 0x3F +`timescale 1ns/10ps + +module uart_tb (); + + // Testbench uses a 10 MHz clock + // Want to interface to 115200 baud UART + // 10000000 / 115200 = 87 Clocks Per Bit. + parameter c_CLOCK_PERIOD_NS = 100; + parameter c_CLKS_PER_BIT = 87; + parameter c_BIT_PERIOD = 8600; + + reg r_Clock = 0; + reg r_Tx_DV = 0; + wire w_Tx_Done; + reg [7:0] r_Tx_Byte = 0; + reg r_Rx_Serial = 1; + wire [7:0] w_Rx_Byte; + + + // Takes in input byte and serializes it + task UART_WRITE_BYTE; + input [7:0] i_Data; + integer ii; + begin + + // Send Start Bit + r_Rx_Serial <= 1'b0; + #(c_BIT_PERIOD); + #1000; + + + // Send Data Byte + for (ii=0; ii<8; ii=ii+1) + begin + r_Rx_Serial <= i_Data[ii]; + #(c_BIT_PERIOD); + end + + // Send Stop Bit + r_Rx_Serial <= 1'b1; + #(c_BIT_PERIOD); + end + endtask // UART_WRITE_BYTE + + + uart_rx #(.CLKS_PER_BIT(c_CLKS_PER_BIT)) UART_RX_INST + (.i_Clock(r_Clock), + .i_Rx_Serial(r_Rx_Serial), + .o_Rx_DV(), + .o_Rx_Byte(w_Rx_Byte) + ); + + uart_tx #(.CLKS_PER_BIT(c_CLKS_PER_BIT)) UART_TX_INST + (.i_Clock(r_Clock), + .i_Tx_DV(r_Tx_DV), + .i_Tx_Byte(r_Tx_Byte), + .o_Tx_Active(), + .o_Tx_Serial(), + .o_Tx_Done(w_Tx_Done) + ); + + + always + #(c_CLOCK_PERIOD_NS/2) r_Clock <= !r_Clock; + + + // Main Testing: + initial + begin + + // Tell UART to send a command (exercise Tx) + @(posedge r_Clock); + @(posedge r_Clock); + r_Tx_DV <= 1'b1; + r_Tx_Byte <= 8'hAB; + @(posedge r_Clock); + r_Tx_DV <= 1'b0; + @(posedge w_Tx_Done); + + // Send a command to the UART (exercise Rx) + @(posedge r_Clock); + UART_WRITE_BYTE(8'h3F); + @(posedge r_Clock); + + // Check that the correct command was received + if (w_Rx_Byte == 8'h3F) + $display("Test Passed - Correct Byte Received"); + else + $display("Test Failed - Incorrect Byte Received"); + + end + +endmodule \ No newline at end of file diff --git a/rtl/src/vgafb.v b/rtl/src/vgafb.v new file mode 100644 index 0000000..4e8d668 --- /dev/null +++ b/rtl/src/vgafb.v @@ -0,0 +1,292 @@ +`timescale 1ns / 1ps +`default_nettype none + +// Project F: Display Timings +// (C)2019 Will Green, Open Source Hardware released under the MIT License +// Learn more at https://projectf.io + +//128K video memory is not enough for 640x480x4 +`define RES_640_400 +//`define RES_1024_768 + +module display_timings #( + H_RES=640, // horizontal resolution (pixels) + V_RES=480, // vertical resolution (lines) + H_FP=16, // horizontal front porch + H_SYNC=96, // horizontal sync + H_BP=48, // horizontal back porch + V_FP=10, // vertical front porch + V_SYNC=2, // vertical sync + V_BP=33, // vertical back porch + H_POL=0, // horizontal sync polarity (0:neg, 1:pos) + V_POL=0 // vertical sync polarity (0:neg, 1:pos) + ) + ( + input wire i_pix_clk, // pixel clock + input wire i_rst, // reset: restarts frame (active high) + output wire o_hs, // horizontal sync + output wire o_vs, // vertical sync + output wire o_de, // display enable: high during active video + output wire o_frame, // high for one tick at the start of each frame + output wire o_scanline, // high for one tick at the start of each scanline + output reg o_vblank, // high during vertical blank phase + output reg signed [15:0] o_sx, // horizontal beam position (including blanking) + output reg signed [15:0] o_sy // vertical beam position (including blanking) + ); + + // Horizontal: sync, active, and pixels + localparam signed H_STA = 0 - H_FP - H_SYNC - H_BP; // horizontal start + localparam signed HS_STA = H_STA + H_FP; // sync start + localparam signed HS_END = HS_STA + H_SYNC; // sync end + localparam signed HA_STA = 0; // active start + localparam signed HA_END = H_RES - 1; // active end + + // Vertical: sync, active, and pixels + localparam signed V_STA = 0 - V_FP - V_SYNC - V_BP; // vertical start + localparam signed VS_STA = V_STA + V_FP; // sync start + localparam signed VS_END = VS_STA + V_SYNC; // sync end + localparam signed VA_STA = 0; // active start + localparam signed VA_END = V_RES - 1; // active end + + // generate sync signals with correct polarity + assign o_hs = H_POL ? (o_sx > HS_STA && o_sx <= HS_END) + : ~(o_sx > HS_STA && o_sx <= HS_END); + assign o_vs = V_POL ? (o_sy > VS_STA && o_sy <= VS_END) + : ~(o_sy > VS_STA && o_sy <= VS_END); + + // display enable: high during active period + assign o_de = (o_sx >= 0 && o_sy >= 0); + + // o_frame: high for one tick at the start of each frame + assign o_frame = (o_sy == V_STA && o_sx == H_STA); + // o_scanline: high for one tick at the start of each visible scanline + assign o_scanline = (o_sy >= VA_STA) && (o_sy <= VA_END) && (o_sx == H_STA); + + always @(posedge i_pix_clk) + begin + if(o_frame) o_vblank <= 1; + else if (o_de) o_vblank <= 0; + end + + always @ (posedge i_pix_clk) + begin + if (i_rst) // reset to start of frame + begin + o_sx <= H_STA; + o_sy <= V_STA; + end + else + begin + if (o_sx == HA_END) // end of line + begin + o_sx <= H_STA; + if (o_sy == VA_END) // end of frame + o_sy <= V_STA; + else + o_sy <= o_sy + 16'sh1; + end + else + o_sx <= o_sx + 16'sh1; + end + end +endmodule + +// Project F: Display Controller VGA Demo +// (C)2020 Will Green, Open source hardware released under the MIT License +// Learn more at https://projectf.io + +// This demo requires the following Verilog modules: +// * display_clocks +// * display_timings +// * test_card_simple or another test card + +module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) ( + input wire cpu_clk, // cpu clock + input wire CLK, // pixel clock + input wire RST_BTN, // reset button + input wire[3:0] reg_sel, // register select/address + output wire [VMEM_DATA_WIDTH-1:0] rd_data, + input wire [VMEM_DATA_WIDTH-1:0] wr_data, + input wire rd_en, + input wire wr_en, + + output wire VGA_HS, // horizontal sync output + output wire VGA_VS, // vertical sync output + output wire [3:0] VGA_R, // 4-bit VGA red output + output wire [3:0] VGA_G, // 4-bit VGA green output + output wire [3:0] VGA_B // 4-bit VGA blue output + ); + + localparam BITS_PER_PIXEL = 4; localparam MAX_SHIFT_COUNT = 7; + localparam REG_RD_ADDR = 0; localparam REG_WR_ADDR = 1; localparam REG_VMEM = 2; + localparam REG_PAL_SLOT = 3; localparam REG_PAL_DATA = 4; + localparam REG_CTL = 5; + + localparam COLOR_WIDTH = 12; + localparam PALETTE_WIDTH = 4; + + // Display Clocks + wire pix_clk = CLK; // pixel clock + wire clk_lock = 1; // clock locked? + + wire vmem_rd_en; + wire vmem_wr_en; + wire [VMEM_DATA_WIDTH-1:0] vmem_rd_data; + reg [VMEM_ADDR_WIDTH-1:0] cpu_rd_addr; + reg [VMEM_ADDR_WIDTH-1:0] cpu_wr_addr; + reg [VMEM_ADDR_WIDTH-1:0] pix_addr; + wire [VMEM_DATA_WIDTH-1:0] pix_data; + wire pix_rd; + wire [VMEM_DATA_WIDTH-1:0] status; + + assign vmem_rd_en = rd_en; + assign vmem_wr_en = (reg_sel == REG_VMEM) && wr_en; + assign rd_data = (reg_sel == REG_VMEM) ? vmem_rd_data : + (reg_sel == REG_RD_ADDR) ? cpu_rd_addr : + (reg_sel == REG_WR_ADDR) ? cpu_wr_addr : + (reg_sel == REG_CTL) ? status : + 32'hFFFFFFFF; + + wire [VMEM_ADDR_WIDTH-1:0] cpu_addr = vmem_wr_en ? cpu_wr_addr : cpu_rd_addr; + + bram_tdp #(.DATA(VMEM_DATA_WIDTH),.ADDR(VMEM_ADDR_WIDTH)) vram0 ( + .a_rd(vmem_rd_en), .a_clk(cpu_clk), + .a_wr(vmem_wr_en), .a_addr(cpu_addr), .a_din(wr_data), + .a_dout(vmem_rd_data), + .b_clk(pix_clk), .b_addr(pix_addr), .b_dout(pix_data), + .b_rd(pix_rd) + ); + + wire palette_wr_en = (reg_sel == REG_PAL_DATA) && wr_en; + reg [PALETTE_WIDTH-1:0] palette_wr_slot; + wire [COLOR_WIDTH-1:0] color_data; + + palette palette0(.wr_clk(cpu_clk), .rd_clk(pix_clk), .wr_en(palette_wr_en), + .wr_slot(palette_wr_slot), .wr_data(wr_data[COLOR_WIDTH-1:0]), + .rd_slot(pixel[3:0]), .rd_data(color_data)); + + // Display Timings + wire signed [15:0] sx; // horizontal screen position (signed) + wire signed [15:0] sy; // vertical screen position (signed) + wire h_sync; // horizontal sync + wire v_sync; // vertical sync + wire de; // display enable + wire frame; // frame start + wire scanline; // scanline start + wire vblank; // vertical blank + reg vblank_buf; // vertical blank in cpu clock domain + + display_timings #( // 640x480 800x600 1280x720 1920x1080 +`ifdef RES_1024_768 + .H_RES(1024), // 640 800 1280 1920 + .V_RES(768), // 480 600 720 1080 + .H_FP(24), // 16 40 110 88 + .H_SYNC(136), // 96 128 40 44 + .H_BP(160), // 48 88 220 148 + .V_FP(3), // 10 1 5 4 + .V_SYNC(6), // 2 4 5 5 + .V_BP(29), // 33 23 20 36 + .H_POL(0), // 0 1 1 1 + .V_POL(0) // 0 1 1 1 + `endif + `ifdef RES_640_400 + .H_RES(640), + .V_RES(400), + .H_FP(16), + .H_SYNC(96), + .H_BP(48), + .V_FP(12), + .V_SYNC(2), + .V_BP(35), + .H_POL(0), + .V_POL(1) + `endif + ) + display_timings_inst ( + .i_pix_clk(CLK), + .i_rst(!RST_BTN), + .o_hs(h_sync), + .o_vs(v_sync), + .o_de(de), + .o_frame(frame), + .o_scanline(scanline), + .o_vblank(vblank), + .o_sx(sx), + .o_sy(sy) + ); + + wire [7:0] red; + wire [7:0] green; + wire [7:0] blue; + + reg [VMEM_DATA_WIDTH-1:0] shifter; + reg [4:0] shift_count; + + // delayed frame signal for pix_rd + reg frame_d; + + assign pix_rd = frame_d || scanline || (shift_count == 2); + + assign status = { 4'b0001, {(VMEM_DATA_WIDTH-5){1'b0}}, vblank_buf}; + + wire [BITS_PER_PIXEL-1:0] pixel = shifter[VMEM_DATA_WIDTH-1:VMEM_DATA_WIDTH-BITS_PER_PIXEL]; + + always @(posedge pix_clk) frame_d <= frame; + + always @(posedge cpu_clk) vblank_buf <= vblank; + + always @(posedge cpu_clk) + begin + if(wr_en) + begin + case(reg_sel) + REG_RD_ADDR: cpu_rd_addr <= wr_data; + REG_WR_ADDR: cpu_wr_addr <= wr_data; + REG_VMEM: cpu_wr_addr <= cpu_wr_addr + 1; // auto-increment write addr on write + REG_PAL_SLOT: palette_wr_slot <= wr_data[3:0]; + endcase + end + else + if(rd_en && reg_sel == REG_VMEM) cpu_rd_addr <= cpu_rd_addr + 1; // auto-increment read addr on read + end + + always @(posedge pix_clk) + begin + if(scanline || shift_count == MAX_SHIFT_COUNT) // before start of a line + begin // or at the end of a word, reset shifter with pixel data + shift_count <= 0; + shifter <= pix_data; + end + else if(de) + begin + shift_count <= shift_count + 1; + shifter <= shifter << BITS_PER_PIXEL; + end + + if(frame) // at start of frame, reset pixel pointer + pix_addr <= 0; + else if(shift_count == 1) // after the first pixel, increment address + pix_addr <= pix_addr + 1; + end + +// Hard-Coded RGBI palette +// // Pixel = { red, green, blue, intensity } +// assign red = pixel[3] ? pixel[0] ? 255 : 127: 0; +// assign green = pixel[2] ? pixel[0] ? 255 : 127: 0; +// assign blue = pixel[1] ? pixel[0] ? 255 : 127: 0; + +// // VGA Output +// // VGA Pmod is 12-bit so we take the upper nibble of each colour +// assign VGA_HS = h_sync; +// assign VGA_VS = v_sync; +// assign VGA_R = de ? red[7:4] : 4'b0; +// assign VGA_G = de ? green[7:4] : 4'b0; +// assign VGA_B = de ? blue[7:4] : 4'b0; + + // 12 bit RGB palette + assign VGA_HS = h_sync; + assign VGA_VS = v_sync; + assign VGA_R = de ? color_data[11:8] : 4'b0; + assign VGA_G = de ? color_data[7:4] : 4'b0; + assign VGA_B = de ? color_data[3:0] : 4'b0; +endmodule