Added Nexys Video Vivado/OpenXC7 support

This commit is contained in:
regymm 2024-06-02 20:50:12 +09:00
parent eaa45f01d5
commit 7c196bf595
9 changed files with 652 additions and 0 deletions

View File

@ -194,6 +194,15 @@ The summary under `TEST CALIBRATION` are the results from the **internal** read/
This will run the DDR3 controller at 333 MHz (3 ns clock period) which is the [maximum clock period for Arty-S7](https://digilent.com/reference/programmable-logic/arty-s7/reference-manual). Upload the bitstream to Arty-S7, after around 2 seconds the 4 LEDS should light up.
- The [Nexys Video](./nexys_video) project utilizes the DDR3 chip on the Digilent Nexys Video board with xc7a200t. Only one lane is used for simplicity. Supports OpenXC7 toolchain. Makefiles have been included for quick start, just run the following command in the root directory of repo:
- Vivado compilation: `source /opt/Xilinx/Vivado/2019.1/settings64.sh` then `make -C nexys_video -f Makefile.vivado`
- OpenXC7 compilation (using toolchain in Docker): `docker run --rm -v .:/mnt -v /chipdb:/chipdb regymm/openxc7 make -C /mnt/nexys_video -f Makefile.openxc7`
The bitstream will be compiled as `nexys_video/build/top.bit`.
- Board test: after programming bitstream, the 8 LEDs will show some pattern, then become all lit up after calibration. When pressing BTND(D22), LD7/LD6 will show a blinky, and LD5-LD0 will show 101110 after successful calibration. BTNC(B22) resets the controller, and calibration will be redone. 9600 baud UART will be the same as the Arty-S7 case: type small `abcd` to write to memory, and type capital `ABCD` to read back. For example, type `abcd` then `ABCDEFGH` will show `abcd<63><64><EFBFBD><EFBFBD>` (because EFGH memory locations are not written yet).
- The [10Gb Ethernet Switch](https://github.com/ZipCPU/eth10g) project utilizes this DDR3 controller for accessing a single-rank DDR3 module (8 lanes of x8 DDR3) at DDR3-800 (100 MHz controller and 400 MHz PHY).
# Other Open-Sourced DDR3 Controllers

View File

@ -0,0 +1,50 @@
# Generated by https://github.com/FPGAOL-CE/caas-wizard
DB_DIR = /nextpnr-xilinx/xilinx/external/prjxray-db
CHIPDB = /chipdb
BUILDDIR := ${CURDIR}/build
TOP := nexysvideo_ddr3
#SOURCES := $(wildcard *.v) $(wildcard ../rtl/*.v) $(wildcard ../arty_s7/verilog-uart/rtl/*.v)
XDC := $(wildcard $(wildcard Nexys-video.xdc) )
CHIPFAM := artix7
PART := xc7a200tsbg484-1
LOGFILE := ${BUILDDIR}/top.log
all: ${CHIPDB} ${BUILDDIR} ${BUILDDIR}/top.bit
${BUILDDIR}:
mkdir -m 777 -p ${BUILDDIR} && chown -R nobody ${BUILDDIR} | true
${CHIPDB}:
mkdir -m 777 -p ${CHIPDB} && chown -R nobody ${CHIPDB} | true
# we run this in parent directory to seeminglessly import user source files
# otherwise have to parse user pattern and add ../
${BUILDDIR}/top.json: $(wildcard *.v) $(wildcard ../rtl/*.v) $(wildcard ../arty_s7/verilog-uart/rtl/*.v)
yosys -p "synth_xilinx -flatten -abc9 -arch xc7 -top ${TOP}; write_json ${BUILDDIR}/top.json" $^ >> ${LOGFILE} 2>&1
# The chip database only needs to be generated once
# that is why we don't clean it with make clean
${CHIPDB}/${PART}.bin:
pypy3 /nextpnr-xilinx/xilinx/python/bbaexport.py --device ${PART} --bba ${PART}.bba
bbasm -l ${PART}.bba ${CHIPDB}/${PART}.bin
rm -f ${PART}.bba
${BUILDDIR}/top.fasm: ${BUILDDIR}/top.json ${CHIPDB}/${PART}.bin
nextpnr-xilinx --chipdb ${CHIPDB}/${PART}.bin --xdc ${XDC} --json ${BUILDDIR}/top.json --pre-place constraints.py --pre-route show_bels.py --fasm $@ >> ${LOGFILE} 2>&1
#nextpnr-xilinx --chipdb ${CHIPDB}/${PART}.bin --xdc ${XDC} --json ${BUILDDIR}/top.json --fasm $@ >> ${LOGFILE} 2>&1
${BUILDDIR}/top.frames: ${BUILDDIR}/top.fasm
fasm2frames --part ${PART} --db-root ${DB_DIR}/${CHIPFAM} $< > $@
${BUILDDIR}/top.bit: ${BUILDDIR}/top.frames
xc7frames2bit --part_file ${DB_DIR}/${CHIPFAM}/${PART}/part.yaml --part_name ${PART} --frm_file $< --output_file $@ >> ${LOGFILE} 2>&1
.PHONY: clean
clean:
@rm -f *.bit
@rm -f *.frames
@rm -f *.fasm
@rm -f *.json

View File

@ -0,0 +1,44 @@
# Generated by https://github.com/FPGAOL-CE/caas-wizard
BUILDDIR := ${CURDIR}/build
# TOP := nexysvideo_ddr3
# SOURCES := $(wildcard *.v ../rtl/ddr3*.v ../arty_s7/verilog-uart/rtl/*.v)
# XDC := $(wildcard $(wildcard Nexys-video.xdc) $(wildcard Nexys-video-vivado.xdc) )
# PART := xc7a200tsbg484-1
LOGFILE := ${BUILDDIR}/top.log
# Build design
all: ${BUILDDIR}/top.bit
${BUILDDIR}:
mkdir -m 777 -p ${BUILDDIR} && chown -R nobody ${BUILDDIR} | true
.ONESHELL:
${BUILDDIR}/vivado.tcl: ${BUILDDIR}
cat << EOF > $@
# vivado.tcl generated for caas
# can be launched from any directory
cd ${BUILDDIR}
create_project -part xc7a200tsbg484-1 -force v_proj
set_property target_language Verilog [current_project]
cd ..
read_verilog [glob *.v ../rtl/ddr3*.v ../arty_s7/verilog-uart/rtl/*.v]
read_xdc [glob $(wildcard Nexys-video.xdc) $(wildcard Nexys-video-vivado.xdc) ]
cd build
synth_design -top nexysvideo_ddr3
opt_design
place_design
phys_opt_design
route_design
write_bitstream -verbose -force top.bit
# report_utilization -file util.rpt
# report_timing_summary -file timing.rpt
EOF
${BUILDDIR}/top.bit: ${BUILDDIR}/vivado.tcl
cd ${BUILDDIR} && vivado -mode batch -source $< > ${LOGFILE} 2>&1
.PHONY: clean
clean:
rm -rf ${BUILDDIR}

View File

@ -0,0 +1,3 @@
set_property INTERNAL_VREF 0.75 [get_iobanks 35]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

242
nexys_video/Nexys-video.xdc Normal file
View File

@ -0,0 +1,242 @@
set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports i_clk]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports i_clk]
set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {led[0]}]
set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {led[1]}]
set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {led[2]}]
set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS33} [get_ports {led[3]}]
set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {led[4]}]
set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports {led[5]}]
set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {led[6]}]
set_property -dict {PACKAGE_PIN Y13 IOSTANDARD LVCMOS33} [get_ports {led[7]}]
set_property -dict {PACKAGE_PIN B22 IOSTANDARD LVCMOS33} [get_ports i_rst]
set_property -dict {PACKAGE_PIN D22 IOSTANDARD LVCMOS33} [get_ports {btn[0]}]
set_property -dict {PACKAGE_PIN C22 IOSTANDARD LVCMOS33} [get_ports {btn[1]}]
set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS33} [get_ports {btn[2]}]
set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS33} [get_ports {btn[3]}]
set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports tx]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports rx]
set_property SLEW FAST [get_ports {ddr3_dq[0]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[0]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[0]}]
set_property PACKAGE_PIN G2 [get_ports {ddr3_dq[0]}]
set_property SLEW FAST [get_ports {ddr3_dq[1]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[1]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[1]}]
set_property PACKAGE_PIN H4 [get_ports {ddr3_dq[1]}]
set_property SLEW FAST [get_ports {ddr3_dq[2]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[2]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[2]}]
set_property PACKAGE_PIN H5 [get_ports {ddr3_dq[2]}]
set_property SLEW FAST [get_ports {ddr3_dq[3]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[3]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[3]}]
set_property PACKAGE_PIN J1 [get_ports {ddr3_dq[3]}]
set_property SLEW FAST [get_ports {ddr3_dq[4]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[4]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[4]}]
set_property PACKAGE_PIN K1 [get_ports {ddr3_dq[4]}]
set_property SLEW FAST [get_ports {ddr3_dq[5]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[5]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[5]}]
set_property PACKAGE_PIN H3 [get_ports {ddr3_dq[5]}]
set_property SLEW FAST [get_ports {ddr3_dq[6]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[6]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[6]}]
set_property PACKAGE_PIN H2 [get_ports {ddr3_dq[6]}]
set_property SLEW FAST [get_ports {ddr3_dq[7]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[7]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[7]}]
set_property PACKAGE_PIN J5 [get_ports {ddr3_dq[7]}]
set_property SLEW FAST [get_ports {ddr3_dq[8]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[8]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[8]}]
set_property PACKAGE_PIN E3 [get_ports {ddr3_dq[8]}]
set_property SLEW FAST [get_ports {ddr3_dq[9]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[9]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[9]}]
set_property PACKAGE_PIN B2 [get_ports {ddr3_dq[9]}]
set_property SLEW FAST [get_ports {ddr3_dq[10]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[10]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[10]}]
set_property PACKAGE_PIN F3 [get_ports {ddr3_dq[10]}]
set_property SLEW FAST [get_ports {ddr3_dq[11]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[11]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[11]}]
set_property PACKAGE_PIN D2 [get_ports {ddr3_dq[11]}]
set_property SLEW FAST [get_ports {ddr3_dq[12]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[12]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[12]}]
set_property PACKAGE_PIN C2 [get_ports {ddr3_dq[12]}]
set_property SLEW FAST [get_ports {ddr3_dq[13]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[13]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[13]}]
set_property PACKAGE_PIN A1 [get_ports {ddr3_dq[13]}]
set_property SLEW FAST [get_ports {ddr3_dq[14]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[14]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[14]}]
set_property PACKAGE_PIN E2 [get_ports {ddr3_dq[14]}]
set_property SLEW FAST [get_ports {ddr3_dq[15]}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[15]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[15]}]
set_property PACKAGE_PIN B1 [get_ports {ddr3_dq[15]}]
set_property SLEW FAST [get_ports {ddr3_addr[14]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[14]}]
set_property PACKAGE_PIN P6 [get_ports {ddr3_addr[14]}]
set_property SLEW FAST [get_ports {ddr3_addr[13]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[13]}]
set_property PACKAGE_PIN P2 [get_ports {ddr3_addr[13]}]
set_property SLEW FAST [get_ports {ddr3_addr[12]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[12]}]
set_property PACKAGE_PIN N4 [get_ports {ddr3_addr[12]}]
set_property SLEW FAST [get_ports {ddr3_addr[11]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[11]}]
set_property PACKAGE_PIN N5 [get_ports {ddr3_addr[11]}]
set_property SLEW FAST [get_ports {ddr3_addr[10]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[10]}]
set_property PACKAGE_PIN L5 [get_ports {ddr3_addr[10]}]
set_property SLEW FAST [get_ports {ddr3_addr[9]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[9]}]
set_property PACKAGE_PIN R1 [get_ports {ddr3_addr[9]}]
set_property SLEW FAST [get_ports {ddr3_addr[8]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[8]}]
set_property PACKAGE_PIN M6 [get_ports {ddr3_addr[8]}]
set_property SLEW FAST [get_ports {ddr3_addr[7]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[7]}]
set_property PACKAGE_PIN N2 [get_ports {ddr3_addr[7]}]
set_property SLEW FAST [get_ports {ddr3_addr[6]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[6]}]
set_property PACKAGE_PIN N3 [get_ports {ddr3_addr[6]}]
set_property SLEW FAST [get_ports {ddr3_addr[5]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[5]}]
set_property PACKAGE_PIN P1 [get_ports {ddr3_addr[5]}]
set_property SLEW FAST [get_ports {ddr3_addr[4]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[4]}]
set_property PACKAGE_PIN L6 [get_ports {ddr3_addr[4]}]
set_property SLEW FAST [get_ports {ddr3_addr[3]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[3]}]
set_property PACKAGE_PIN M1 [get_ports {ddr3_addr[3]}]
set_property SLEW FAST [get_ports {ddr3_addr[2]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[2]}]
set_property PACKAGE_PIN M3 [get_ports {ddr3_addr[2]}]
set_property SLEW FAST [get_ports {ddr3_addr[1]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[1]}]
set_property PACKAGE_PIN M5 [get_ports {ddr3_addr[1]}]
set_property SLEW FAST [get_ports {ddr3_addr[0]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[0]}]
set_property PACKAGE_PIN M2 [get_ports {ddr3_addr[0]}]
set_property SLEW FAST [get_ports {ddr3_ba[2]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[2]}]
set_property PACKAGE_PIN L4 [get_ports {ddr3_ba[2]}]
set_property SLEW FAST [get_ports {ddr3_ba[1]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[1]}]
set_property PACKAGE_PIN K6 [get_ports {ddr3_ba[1]}]
set_property SLEW FAST [get_ports {ddr3_ba[0]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[0]}]
set_property PACKAGE_PIN L3 [get_ports {ddr3_ba[0]}]
set_property SLEW FAST [get_ports ddr3_ras_n]
set_property IOSTANDARD SSTL15 [get_ports ddr3_ras_n]
set_property PACKAGE_PIN J4 [get_ports ddr3_ras_n]
set_property SLEW FAST [get_ports ddr3_cas_n]
set_property IOSTANDARD SSTL15 [get_ports ddr3_cas_n]
set_property PACKAGE_PIN K3 [get_ports ddr3_cas_n]
set_property SLEW FAST [get_ports ddr3_we_n]
set_property IOSTANDARD SSTL15 [get_ports ddr3_we_n]
set_property PACKAGE_PIN L1 [get_ports ddr3_we_n]
set_property SLEW FAST [get_ports ddr3_reset_n]
set_property IOSTANDARD SSTL15 [get_ports ddr3_reset_n]
set_property PACKAGE_PIN G1 [get_ports ddr3_reset_n]
set_property SLEW FAST [get_ports ddr3_cke]
set_property IOSTANDARD SSTL15 [get_ports ddr3_cke]
set_property PACKAGE_PIN J6 [get_ports ddr3_cke]
set_property SLEW FAST [get_ports ddr3_odt]
set_property IOSTANDARD SSTL15 [get_ports ddr3_odt]
set_property PACKAGE_PIN K4 [get_ports ddr3_odt]
set_property SLEW FAST [get_ports ddr3_cs_n]
set_property IOSTANDARD LVCMOS33 [get_ports ddr3_cs_n]
set_property PACKAGE_PIN R3 [get_ports ddr3_cs_n]
set_property SLEW FAST [get_ports {ddr3_dm[0]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[0]}]
set_property PACKAGE_PIN G3 [get_ports {ddr3_dm[0]}]
set_property SLEW FAST [get_ports {ddr3_dm[1]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[1]}]
set_property PACKAGE_PIN F1 [get_ports {ddr3_dm[1]}]
set_property SLEW FAST [get_ports {ddr3_dqs_p}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dqs_p}]
set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_dqs_p}]
set_property SLEW FAST [get_ports {ddr3_dqs_n}]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dqs_n}]
set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_dqs_n}]
set_property PACKAGE_PIN K2 [get_ports {ddr3_dqs_p}]
set_property PACKAGE_PIN J2 [get_ports {ddr3_dqs_n}]
#set_property SLEW FAST [get_ports {ddr3_dqs_p[1]}]
#set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dqs_p[1]}]
#set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_dqs_p[1]}]
#set_property SLEW FAST [get_ports {ddr3_dqs_n[1]}]
#set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dqs_n[1]}]
#set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_dqs_n[1]}]
#set_property PACKAGE_PIN E1 [get_ports {ddr3_dqs_p[1]}]
#set_property PACKAGE_PIN D1 [get_ports {ddr3_dqs_n[1]}]
set_property SLEW FAST [get_ports ddr3_clk_p]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddr3_clk_p]
set_property SLEW FAST [get_ports ddr3_clk_n]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddr3_clk_n]
set_property PACKAGE_PIN P5 [get_ports ddr3_clk_p]
set_property PACKAGE_PIN P4 [get_ports ddr3_clk_n]
#set_property INTERNAL_VREF 0.75 [get_iobanks 35]
#set_property CONFIG_VOLTAGE 3.3 [current_design]
#set_property CFGBVS VCCO [current_design]

66
nexys_video/clk_wiz.v Normal file
View File

@ -0,0 +1,66 @@
`timescale 1ps/1ps
module clk_wiz
(
input clk_in1,
output clk_out1,
output clk_out2,
output clk_out3,
output clk_out4,
input reset,
output locked
);
wire clk_out1_clk_wiz_0;
wire clk_out2_clk_wiz_0;
wire clk_out3_clk_wiz_0;
wire clk_out4_clk_wiz_0;
wire clkfbout;
PLLE2_ADV
#(.BANDWIDTH ("OPTIMIZED"),
.COMPENSATION ("INTERNAL"),
.STARTUP_WAIT ("FALSE"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT (10), // 100 MHz * 10 = 1000 MHz
.CLKFBOUT_PHASE (0.000),
.CLKOUT0_DIVIDE (12), // 1000 MHz / 12 = 83.333 MHz
.CLKOUT0_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.500),
.CLKOUT1_DIVIDE (3), // 1000 MHz / 3 = 333.333 MHz
.CLKOUT1_PHASE (0.000),
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT2_DIVIDE (5), // 1000 MHz / 5 = 200 MHz
.CLKOUT2_PHASE (0.000),
.CLKOUT2_DUTY_CYCLE (0.500),
.CLKOUT3_DIVIDE (3), // 1000 MHz / 3 = 333.333 MHz, 90 phase
.CLKOUT3_PHASE (90.000),
.CLKOUT3_DUTY_CYCLE (0.500),
.CLKIN1_PERIOD (10.000) // 100 MHz input
)
plle2_adv_inst
(
.CLKFBOUT (clkfbout),
.CLKOUT0 (clk_out1_clk_wiz_0),
.CLKOUT1 (clk_out2_clk_wiz_0),
.CLKOUT2 (clk_out3_clk_wiz_0),
.CLKOUT3 (clk_out4_clk_wiz_0),
.CLKFBIN (clkfbout),
.CLKIN1 (clk_in1),
.LOCKED (locked),
.RST (reset)
);
BUFG clkout1_buf
(.O (clk_out1),
.I (clk_out1_clk_wiz_0));
BUFG clkout2_buf
(.O (clk_out2),
.I (clk_out2_clk_wiz_0));
BUFG clkout3_buf
(.O (clk_out3),
.I (clk_out3_clk_wiz_0));
BUFG clkout4_buf
(.O (clk_out4),
.I (clk_out4_clk_wiz_0));
endmodule

21
nexys_video/constraints.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
ddr3_name = 'ddr3_top_inst.ddr3_phy_inst'
def get_cells(name_part):
return list(map(lambda c: c.second, filter(lambda c: name_part in c.first, ctx.cells)))
def get_cell(name_part):
return get_cells(name_part)[0]
c1=get_cell(ddr3_name + '.genblk5[0].ISERDESE2_train')
c3=get_cell(ddr3_name + '.genblk5[0].OSERDESE2_train')
# c2=get_cell(ddr3_name + '.genblk5[1].ISERDESE2_train')
# c4=get_cell(ddr3_name + '.genblk5[1].OSERDESE2_train')
# Usually, nextpnr-xilinx would place these on X0Y149, but
# prjxray has missing PIPs on _SING tiles, so we need to
# place these on a non-SING tile to make it work
c1.setAttr('BEL', 'ILOGIC_X1Y193/ISERDESE2')
c3.setAttr('BEL', 'OLOGIC_X1Y193/OSERDESE2')
# c2.setAttr('BEL', 'ILOGIC_X0Y245/ISERDESE2')
# c4.setAttr('BEL', 'OLOGIC_X0Y245/OSERDESE2')

View File

@ -0,0 +1,195 @@
`timescale 1ns / 1ps
module nexysvideo_ddr3
(
input wire i_clk,
input wire i_rst,
// DDR3 I/O Interface
output wire ddr3_clk_p, ddr3_clk_n,
output wire ddr3_reset_n,
output wire ddr3_cke, // CKE
output wire ddr3_cs_n, // chip select signal
output wire ddr3_ras_n, // RAS#
output wire ddr3_cas_n, // CAS#
output wire ddr3_we_n, // WE#
output wire[14-1:0] ddr3_addr,
output wire[3-1:0] ddr3_ba,
inout wire[16-1:0] ddr3_dq,
inout wire[1-1:0] ddr3_dqs_p, ddr3_dqs_n,
output wire[2-1:0] ddr3_dm,
output wire ddr3_odt, // on-die termination
// UART line
input wire rx,
output wire tx,
//Debug LEDs
output reg[7:0] led,
input wire[3:0] btn
);
wire i_controller_clk, i_ddr3_clk, i_ref_clk, i_ddr3_clk_90;
wire m_axis_tvalid;
wire rx_empty;
wire tx_full;
wire o_wb_ack;
wire[7:0] o_wb_data;
wire o_aux;
wire[7:0] rd_data;
wire o_wb_stall;
reg i_wb_stb = 0, i_wb_we;
wire[63:0] o_debug1;
wire[31:0] o_debug2;
reg[7:0] i_wb_data;
reg[7:0] i_wb_addr;
assign ddr3_cs_n = 0; //tie cs_n to ground (same as disabling the chip-select)
reg [24:0]c;
always @ (posedge i_controller_clk) begin
if (!i_rst) c <= c + 1;
else c <= 0;
end
reg [4:0]od1_last;
reg bitt = 0;
always @ (posedge i_controller_clk) begin
od1_last <= o_debug1[4:0];
if (btn[1]) begin
if (od1_last != o_debug1[4:0]) bitt <= 1;
end else
bitt <= 0;
end
always @(*) begin
if (btn[0]) begin
led <= {c[24:23], o_debug1[4:0], bitt};
end else begin
if (!btn[2])
led <= o_debug2[7:0];
else
led <= {4'b0, o_debug2[11:8]};
end
end
always @(posedge i_controller_clk) begin
begin
i_wb_stb <= 0;
i_wb_we <= 0;
i_wb_addr <= 0;
i_wb_data <= 0;
if(!o_wb_stall && m_axis_tvalid) begin
if(rd_data >= 97 && rd_data <= 122) begin //write to DDR3 if ASCII is small letter
i_wb_stb <= 1;
i_wb_we <= 1;
i_wb_addr <= ~rd_data ;
i_wb_data <= rd_data;
end
else if(rd_data >= 65 && rd_data <= 90) begin //read from DDR3 if ASCII is capital letter
i_wb_stb <= 1; //make request
i_wb_we <= 0; //read
i_wb_addr <= ~(rd_data + 8'd32);
end
end
end
end
(* mark_debug = "true" *) wire clk_locked;
clk_wiz clk_wiz_inst
(
// Clock out ports
.clk_out1(i_controller_clk), //83.333 Mhz
.clk_out2(i_ddr3_clk), // 333.333 MHz
.clk_out3(i_ref_clk), //200MHz
.clk_out4(i_ddr3_clk_90), // 333.333 MHz with 90degree shift
// Status and control signals
.reset(i_rst),
.locked(clk_locked),
// Clock in ports
.clk_in1(i_clk)
);
// UART module from https://github.com/alexforencich/verilog-uart
uart #(.DATA_WIDTH(8)) uart_m
(
.clk(i_controller_clk),
.rst(i_rst),
.s_axis_tdata(o_wb_data),
.s_axis_tvalid(o_wb_ack),
.s_axis_tready(),
.m_axis_tdata(rd_data),
.m_axis_tvalid(m_axis_tvalid),
.m_axis_tready(1),
.rxd(rx),
.txd(tx),
.prescale(1085) //9600 Baud Rate
);
// DDR3 Controller
ddr3_top #(
.CONTROLLER_CLK_PERIOD(12_000), //12_000ps, clock period of the controller interface
.DDR3_CLK_PERIOD(3_000), //3_000ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD)
.ROW_BITS(14), //width of row address
.COL_BITS(10), //width of column address
.BA_BITS(3), //width of bank address
.DQ_BITS(8), //width of DQ
.BYTE_LANES(1), //number of DDR3 modules to be controlled
.AUX_WIDTH(4), //width of aux line (must be >= 4)
.WB2_ADDR_BITS(32), //width of 2nd wishbone address bus
.WB2_DATA_BITS(32), //width of 2nd wishbone data bus
.MICRON_SIM(0), //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
.ODELAY_SUPPORTED(0), //set to 1 when ODELAYE2 is supported
.SECOND_WISHBONE(0) //set to 1 if 2nd wishbone is needed
) ddr3_top_inst
(
//clock and reset
.i_controller_clk(i_controller_clk),
.i_ddr3_clk(i_ddr3_clk), //i_controller_clk has period of CONTROLLER_CLK_PERIOD, i_ddr3_clk has period of DDR3_CLK_PERIOD
.i_ref_clk(i_ref_clk),
.i_ddr3_clk_90(i_ddr3_clk_90),
.i_rst_n(!i_rst && clk_locked),
// Wishbone inputs
.i_wb_cyc(1), //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
.i_wb_stb(i_wb_stb), //request a transfer
.i_wb_we(i_wb_we), //write-enable (1 = write, 0 = read)
.i_wb_addr(i_wb_addr), //burst-addressable {row,bank,col}
.i_wb_data(i_wb_data), //write data, for a 4:1 controller data width is 8 times the number of pins on the device
.i_wb_sel(16'hffff), //byte strobe for write (1 = write the byte)
.i_aux(i_wb_we), //for AXI-interface compatibility (given upon strobe)
// Wishbone outputs
.o_wb_stall(o_wb_stall), //1 = busy, cannot accept requests
.o_wb_ack(o_wb_ack), //1 = read/write request has completed
.o_wb_data(o_wb_data), //read data, for a 4:1 controller data width is 8 times the number of pins on the device
.o_aux(o_aux),
// Wishbone 2 (PHY) inputs
.i_wb2_cyc(), //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
.i_wb2_stb(), //request a transfer
.i_wb2_we(), //write-enable (1 = write, 0 = read)
.i_wb2_addr(), //burst-addressable {row,bank,col}
.i_wb2_data(), //write data, for a 4:1 controller data width is 8 times the number of pins on the device
.i_wb2_sel(), //byte strobe for write (1 = write the byte)
// Wishbone 2 (Controller) outputs
.o_wb2_stall(), //1 = busy, cannot accept requests
.o_wb2_ack(), //1 = read/write request has completed
.o_wb2_data(), //read data, for a 4:1 controller data width is 8 times the number of pins on the device
// PHY Interface (to be added later)
// DDR3 I/O Interface
.o_ddr3_clk_p(ddr3_clk_p),
.o_ddr3_clk_n(ddr3_clk_n),
.o_ddr3_reset_n(ddr3_reset_n),
.o_ddr3_cke(ddr3_cke), // CKE
.o_ddr3_cs_n(/*ddr3_cs_n*/), // chip select signal (controls rank 1 only)
.o_ddr3_ras_n(ddr3_ras_n), // RAS#
.o_ddr3_cas_n(ddr3_cas_n), // CAS#
.o_ddr3_we_n(ddr3_we_n), // WE#
.o_ddr3_addr(ddr3_addr),
.o_ddr3_ba_addr(ddr3_ba),
.io_ddr3_dq(ddr3_dq),
.io_ddr3_dqs(ddr3_dqs_p),
.io_ddr3_dqs_n(ddr3_dqs_n),
.o_ddr3_dm(ddr3_dm),
.o_ddr3_odt(ddr3_odt), // on-die termination
.o_debug1(o_debug1),
.o_debug2(o_debug2),
.o_debug3()
);
endmodule

22
nexys_video/show_bels.py Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python3
ddr3_name = 'ddr3_top_inst.ddr3_phy_inst'
def get_cells(name_part):
return list(map(lambda c: c.second, filter(lambda c: name_part in c.first, ctx.cells)))
def get_cell(name_part):
return get_cells(name_part)[0]
c1_name = ddr3_name + '.genblk5[0].ISERDESE2_train'
# c2_name = ddr3_name + '.genblk5[1].ISERDESE2_train'
c3_name = ddr3_name + '.genblk5[0].OSERDESE2_train'
# c4_name = ddr3_name + '.genblk5[1].OSERDESE2_train'
c1=get_cell(c1_name)
# c2=get_cell(c2_name)
c3=get_cell(c3_name)
# c4=get_cell(c4_name)
print('show_bels: ' + c1_name + ": ", c1.bel)
# print('show_bels: ' + c2_name + ": ", c2.bel)
print('show_bels: ' + c3_name + ": ", c3.bel)
# print('show_bels: ' + c4_name + ": ", c4.bel)