diff --git a/example_demo/sechzig_mx2/Makefile b/example_demo/sechzig_mx2/Makefile new file mode 100644 index 0000000..d2c367f --- /dev/null +++ b/example_demo/sechzig_mx2/Makefile @@ -0,0 +1,69 @@ +PROJECT = sechzig_mx2_ddr3 +FAMILY = artix7 +PART = xc7a35tftg256-2 +CHIPDB = ${ARTIX7_CHIPDB} +ADDITIONAL_SOURCES = ../../rtl/ddr3_controller.v ../../rtl/ddr3_phy.v ../../rtl/ddr3_top.v uart_rx.v uart_tx.v clk_wiz.v + +############################################################################################# +NEXTPNR_XILINX_DIR ?= /snap/openxc7/current/opt/nextpnr-xilinx +NEXTPNR_XILINX_PYTHON_DIR ?= ${NEXTPNR_XILINX_DIR}/python +PRJXRAY_DB_DIR ?= ${NEXTPNR_XILINX_DIR}/external/prjxray-db + +DBPART = $(shell echo ${PART} | sed -e 's/-[0-9]//g') +SPEEDGRADE = $(shell echo ${PART} | sed -e 's/.*\-\([0-9]\)/\1/g') + +CHIPDB ?= ./ +ifeq ($(CHIPDB),) +CHIPDB = ./ +endif + +PYPY3 ?= pypy3 + +TOP ?= ${PROJECT} +TOP_MODULE ?= ${TOP} +TOP_VERILOG ?= ${TOP}.v + +PNR_DEBUG ?= # --verbose --debug + +BOARD ?= UNKNOWN +JTAG_LINK ?= --board ${BOARD} + +XDC ?= ${PROJECT}.xdc + +.PHONY: all +all: ${PROJECT}.bit + +.PHONY: program +program: ${PROJECT}.bit + openFPGALoader ${JTAG_LINK} --bitstream $< + +${PROJECT}.json: ${TOP_VERILOG} ${ADDITIONAL_SOURCES} + yosys -p "synth_xilinx -flatten -abc9 ${SYNTH_OPTS} -arch xc7 -top ${TOP_MODULE}; write_json ${PROJECT}.json" $< ${ADDITIONAL_SOURCES} + +# The chip database only needs to be generated once +# that is why we don't clean it with make clean +${CHIPDB}/${DBPART}.bin: + ${PYPY3} ${NEXTPNR_XILINX_PYTHON_DIR}/bbaexport.py --device ${PART} --bba ${DBPART}.bba + bbasm -l ${DBPART}.bba ${CHIPDB}/${DBPART}.bin + rm -f ${DBPART}.bba + +${PROJECT}.fasm: ${PROJECT}.json ${CHIPDB}/${DBPART}.bin ${XDC} + nextpnr-xilinx --chipdb ${CHIPDB}/${DBPART}.bin --xdc ${XDC} --json ${PROJECT}.json --fasm $@ ${PNR_ARGS} ${PNR_DEBUG} + +${PROJECT}.frames: ${PROJECT}.fasm + fasm2frames --part ${PART} --db-root ${PRJXRAY_DB_DIR}/${FAMILY} $< > $@ + +${PROJECT}.bit: ${PROJECT}.frames + xc7frames2bit --part_file ${PRJXRAY_DB_DIR}/${FAMILY}/${PART}/part.yaml --part_name ${PART} --frm_file $< --output_file $@ + +.PHONY: clean +clean: + @rm -f *.frames + @rm -f *.fasm + @rm -f *.json + @rm -f *.bin + @rm -f *.bba + +.PHONY: pnrclean +pnrclean: + rm *.fasm *.frames *.bit \ No newline at end of file diff --git a/example_demo/sechzig_mx2/clk_wiz.v b/example_demo/sechzig_mx2/clk_wiz.v new file mode 100644 index 0000000..83e7173 --- /dev/null +++ b/example_demo/sechzig_mx2/clk_wiz.v @@ -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 (20), // 50 MHz * 20 = 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 (20.000) // 50 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 diff --git a/example_demo/sechzig_mx2/sechzig_mx2_ddr3.v b/example_demo/sechzig_mx2/sechzig_mx2_ddr3.v new file mode 100644 index 0000000..de857b6 --- /dev/null +++ b/example_demo/sechzig_mx2/sechzig_mx2_ddr3.v @@ -0,0 +1,216 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: sechzig_mx2_ddr3.v +// Project: UberDDR3 - An Open Source DDR3 Controller +// +// Purpose: Example demo of UberDDR3 for Machdyne Sechzig MX2 (xc7a35tftg256-2). Mechanism: +// - two LEDs will light up once UberDDR3 is done calibrating +// - if UART (9600 Baud Rate)receives small letter ASCII (a-z), this value will be written to DDR3 +// - if UART receives capital letter ASCII (A-Z), the small letter equivalent will be retrieved from DDR3 by doing +// - a read request, once read data is available this will be sent to UART to be streamed out. +// THUS: +// - Sendng "abcdefg" to the UART terminal will store that small latter to DDR3 +// - Then sending "ABCDEFG" to the UART terminal will return the small letter equivalent: "abcdefg" +// +// Engineer: Angelo C. Jacobo +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023-2024 Angelo Jacobo +// Copyright (C) 2024 Lone Dynamics Corporation +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +//////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + + module sechzig_mx2_ddr3 + ( + input wire clk50, + // 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, // no 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[2-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 wire led + ); + + 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; + reg[7:0] i_wb_data; + reg[7:0] i_wb_addr; + // o_debug1 taps on value of state_calibrate (can be traced inside ddr3_controller module) + assign led = !(o_debug1[4:0] == 23); //light up if at DONE_CALIBRATE + + 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 + + reg i_rst_n = 1; + + (* 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_n), + .locked(clk_locked), + // Clock in ports + .clk_in1(clk50) + ); + + // UART TX/RXmodule from https://github.com/ben-marshall/uart + uart_tx #( + .BIT_RATE(9600), + .CLK_HZ(83_333_333), + .PAYLOAD_BITS(8), + .STOP_BITS(1) + ) uart_tx_inst ( + .clk(i_controller_clk), // Top level system clock input. + .resetn(i_rst_n && clk_locked && o_debug1[4:0] == 23), // Asynchronous active low reset. + .uart_txd(tx), // UART transmit pin. + .uart_tx_busy(), // Module busy sending previous item. + .uart_tx_en(o_wb_ack), // Send the data on uart_tx_data + .uart_tx_data(o_wb_data) // The data to be sent + ); + uart_rx #( + .BIT_RATE(9600), + .CLK_HZ(83_333_333), + .PAYLOAD_BITS(8), + .STOP_BITS(1) + ) uart_rx_inst ( + .clk(i_controller_clk), // Top level system clock input. + .resetn(i_rst_n && clk_locked && o_debug1[4:0] == 23), // Asynchronous active low reset. + .uart_rxd(rx), // UART Recieve pin. + .uart_rx_en(o_debug1[4:0] == 23), // Recieve enable + .uart_rx_break(), // Did we get a BREAK message? + .uart_rx_valid(m_axis_tvalid), // Valid data recieved/available. + .uart_rx_data(rd_data) // The recieved data. + ); + + // DDR3 Controller + ddr3_top #( + .CONTROLLER_CLK_PERIOD(12_000), //ps, clock period of the controller interface + .DDR3_CLK_PERIOD(3_000), //ps, 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 + .BYTE_LANES(2), //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_n && 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(), // 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_debug3() + ); + +endmodule + diff --git a/example_demo/sechzig_mx2/sechzig_mx2_ddr3.xdc b/example_demo/sechzig_mx2/sechzig_mx2_ddr3.xdc new file mode 100644 index 0000000..79845d1 --- /dev/null +++ b/example_demo/sechzig_mx2/sechzig_mx2_ddr3.xdc @@ -0,0 +1,276 @@ +################################################################################ +# IO constraints +################################################################################ +# clk48:0 +set_property LOC F5 [get_ports {clk48}] +set_property IOSTANDARD LVCMOS33 [get_ports {clk48}] + +# clk50:0 +set_property LOC D4 [get_ports {clk50}] +set_property IOSTANDARD LVCMOS33 [get_ports {clk50}] + +# led +set_property LOC R16 [get_ports {led}] +set_property IOSTANDARD LVCMOS33 [get_ports {led}] + +# led (n/c) +set_property LOC T14 [get_ports {led[1]}] +set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] + +# serial:0.tx +set_property LOC L2 [get_ports {tx}] +set_property IOSTANDARD LVCMOS33 [get_ports {tx}] + +# serial:0.rx +set_property LOC L3 [get_ports {rx}] +set_property IOSTANDARD LVCMOS33 [get_ports {rx}] + +# ddr3:0.a +set_property LOC F12 [get_ports {ddr3_addr[0]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[0]}] + +# ddr3:0.a +set_property LOC D15 [get_ports {ddr3_addr[1]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[1]}] + +# ddr3:0.a +set_property LOC J15 [get_ports {ddr3_addr[2]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[2]}] + +# ddr3:0.a +set_property LOC E16 [get_ports {ddr3_addr[3]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[3]}] + +# ddr3:0.a +set_property LOC G11 [get_ports {ddr3_addr[4]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[4]}] + +# ddr3:0.a +set_property LOC F15 [get_ports {ddr3_addr[5]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[5]}] + +# ddr3:0.a +set_property LOC H13 [get_ports {ddr3_addr[6]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[6]}] + +# ddr3:0.a +set_property LOC G15 [get_ports {ddr3_addr[7]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[7]}] + +# ddr3:0.a +set_property LOC H12 [get_ports {ddr3_addr[8]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[8]}] + +# ddr3:0.a +set_property LOC H16 [get_ports {ddr3_addr[9]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[9]}] + +# ddr3:0.a +set_property LOC H11 [get_ports {ddr3_addr[10]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[10]}] + +# ddr3:0.a +set_property LOC H14 [get_ports {ddr3_addr[11]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[11]}] + +# ddr3:0.a +set_property LOC E12 [get_ports {ddr3_addr[12]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[12]}] + +# ddr3:0.a +set_property LOC G16 [get_ports {ddr3_addr[13]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[13]}] + +# ddr3:0.a +set_property LOC J16 [get_ports {ddr3_addr[14]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[14]}] + +# ddr3:0.ba +set_property LOC E15 [get_ports {ddr3_ba[0]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_ba[0]}] + +# ddr3:0.ba +set_property LOC D11 [get_ports {ddr3_ba[1]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_ba[1]}] + +# ddr3:0.ba +set_property LOC F13 [get_ports {ddr3_ba[2]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_ba[2]}] + +# ddr3:0.ras_n +set_property LOC D14 [get_ports {ddr3_ras_n}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_ras_n}] + +# ddr3:0.cas_n +set_property LOC E13 [get_ports {ddr3_cas_n}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_cas_n}] + +# ddr3:0.we_n +set_property LOC G12 [get_ports {ddr3_we_n}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_we_n}] + +# ddr3:0.dm +set_property LOC A13 [get_ports {ddr3_dm[0]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dm[0]}] + +# ddr3:0.dm +set_property LOC D9 [get_ports {ddr3_dm[1]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dm[1]}] + +# ddr3:0.dq +set_property LOC A14 [get_ports {ddr3_dq[0]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[0]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[0]}] + +# ddr3:0.dq +set_property LOC C12 [get_ports {ddr3_dq[1]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[1]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[1]}] + +# ddr3:0.dq +set_property LOC B14 [get_ports {ddr3_dq[2]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[2]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[2]}] + +# ddr3:0.dq +set_property LOC D13 [get_ports {ddr3_dq[3]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[3]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[3]}] + +# ddr3:0.dq +set_property LOC B16 [get_ports {ddr3_dq[4]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[4]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[4]}] + +# ddr3:0.dq +set_property LOC C11 [get_ports {ddr3_dq[5]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[5]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[5]}] + +# ddr3:0.dq +set_property LOC C16 [get_ports {ddr3_dq[6]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[6]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[6]}] + +# ddr3:0.dq +set_property LOC C14 [get_ports {ddr3_dq[7]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[7]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[7]}] + +# ddr3:0.dq +set_property LOC A9 [get_ports {ddr3_dq[8]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[8]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[8]}] + +# ddr3:0.dq +set_property LOC B10 [get_ports {ddr3_dq[9]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[9]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[9]}] + +# ddr3:0.dq +set_property LOC C8 [get_ports {ddr3_dq[10]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[10]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[10]}] + +# ddr3:0.dq +set_property LOC B12 [get_ports {ddr3_dq[11]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[11]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[11]}] + +# ddr3:0.dq +set_property LOC A8 [get_ports {ddr3_dq[12]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[12]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[12]}] + +# ddr3:0.dq +set_property LOC A12 [get_ports {ddr3_dq[13]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[13]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[13]}] + +# ddr3:0.dq +set_property LOC C9 [get_ports {ddr3_dq[14]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[14]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[14]}] + +# ddr3:0.dq +set_property LOC B11 [get_ports {ddr3_dq[15]}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[15]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dq[15]}] + +# ddr3:0.dqs_p +set_property LOC B15 [get_ports {ddr3_dqs_p[0]}] +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_dqs_p[0]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dqs_p[0]}] + +# ddr3:0.dqs_p +set_property LOC B9 [get_ports {ddr3_dqs_p[1]}] +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_dqs_p[1]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dqs_p[1]}] + +# ddr3:0.dqs_n +set_property LOC A15 [get_ports {ddr3_dqs_n[0]}] +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_dqs_n[0]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dqs_n[0]}] + +# ddr3:0.dqs_n +set_property LOC A10 [get_ports {ddr3_dqs_n[1]}] +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_dqs_n[1]}] +set_property IN_TERM UNTUNED_SPLIT_60 [get_ports {ddr3_dqs_n[1]}] + +# ddr3:0.clk_p +set_property LOC G14 [get_ports {ddr3_clk_p}] +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_clk_p}] + +# ddr3:0.clk_n +set_property LOC F14 [get_ports {ddr3_clk_n}] +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_clk_n}] + +# ddr3:0.cke +set_property LOC E11 [get_ports {ddr3_cke}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_cke}] + +# ddr3:0.odt +set_property LOC D16 [get_ports {ddr3_odt}] +set_property IOSTANDARD SSTL135 [get_ports {ddr3_odt}] + +# ddr3:0.reset_n +set_property LOC M16 [get_ports {ddr3_reset_n}] +set_property IOSTANDARD LVCMOS33 [get_ports {ddr3_reset_n}] + +################################################################################ +# Design constraints +################################################################################ + +# set_property INTERNAL_VREF 0.675 [get_iobanks 34] + +# set_property INTERNAL_VREF 0.675 [get_iobanks 15] + +################################################################################ +# Clock constraints +################################################################################ + + +# create_clock -name clk48 -period 20.833 [get_ports clk48] + +# create_clock -name clk50 -period 20.0 [get_ports clk50] + +# create_clock -name eth_rx_clk -period 20.0 [get_nets eth_rx_clk] + +# create_clock -name eth_tx_clk -period 20.0 [get_nets eth_tx_clk] + +# set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -asynchronous + +# set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous + +# set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous + +# ################################################################################ +# # False path constraints +# ################################################################################ + + +# set_false_path -quiet -through [get_nets -hierarchical -filter {mr_ff == TRUE}] + +# set_false_path -quiet -to [get_pins -filter {REF_PIN_NAME == PRE} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]] + +# set_max_delay 2 -quiet -from [get_pins -filter {REF_PIN_NAME == C} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE}]] -to [get_pins -filter {REF_PIN_NAME == D} -of_objects [get_cells -hierarchical -filter {ars_ff2 == TRUE}]] diff --git a/example_demo/sechzig_mx2/sechzig_mx2_ddr3_OPENXC7.bit b/example_demo/sechzig_mx2/sechzig_mx2_ddr3_OPENXC7.bit new file mode 100644 index 0000000..08a3976 Binary files /dev/null and b/example_demo/sechzig_mx2/sechzig_mx2_ddr3_OPENXC7.bit differ diff --git a/example_demo/sechzig_mx2/sechzig_mx2_ddr3_VIVADO.bit b/example_demo/sechzig_mx2/sechzig_mx2_ddr3_VIVADO.bit new file mode 100644 index 0000000..c8930ca Binary files /dev/null and b/example_demo/sechzig_mx2/sechzig_mx2_ddr3_VIVADO.bit differ diff --git a/example_demo/sechzig_mx2/uart_rx.v b/example_demo/sechzig_mx2/uart_rx.v new file mode 100644 index 0000000..1cb2ead --- /dev/null +++ b/example_demo/sechzig_mx2/uart_rx.v @@ -0,0 +1,207 @@ + +// +// Module: uart_rx +// +// Notes: +// - UART reciever module. +// + +module uart_rx( +input wire clk , // Top level system clock input. +input wire resetn , // Asynchronous active low reset. +input wire uart_rxd , // UART Recieve pin. +input wire uart_rx_en , // Recieve enable +output wire uart_rx_break, // Did we get a BREAK message? +output wire uart_rx_valid, // Valid data recieved and available. +output reg [PAYLOAD_BITS-1:0] uart_rx_data // The recieved data. +); + +// --------------------------------------------------------------------------- +// External parameters. +// + +// +// Input bit rate of the UART line. +parameter BIT_RATE = 9600; // bits / sec +localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds + +// +// Clock frequency in hertz. +parameter CLK_HZ = 50_000_000; +localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds + +// +// Number of data bits recieved per UART packet. +parameter PAYLOAD_BITS = 8; + +// +// Number of stop bits indicating the end of a packet. +parameter STOP_BITS = 1; + +// -------------------------------------------------------------------------- +// Internal parameters. +// + +// +// Number of clock cycles per uart bit. +localparam CYCLES_PER_BIT = BIT_P / CLK_P; + +// +// Size of the registers which store sample counts and bit durations. +localparam COUNT_REG_LEN = 1+$clog2(CYCLES_PER_BIT); + +// -------------------------------------------------------------------------- +// Internal registers. +// + +// +// Internally latched value of the uart_rxd line. Helps break long timing +// paths from input pins into the logic. +reg rxd_reg; +reg rxd_reg_0; + +// +// Storage for the recieved serial data. +reg [PAYLOAD_BITS-1:0] recieved_data; + +// +// Counter for the number of cycles over a packet bit. +reg [COUNT_REG_LEN-1:0] cycle_counter; + +// +// Counter for the number of recieved bits of the packet. +reg [3:0] bit_counter; + +// +// Sample of the UART input line whenever we are in the middle of a bit frame. +reg bit_sample; + +// +// Current and next states of the internal FSM. +reg [2:0] fsm_state; +reg [2:0] n_fsm_state; + +localparam FSM_IDLE = 0; +localparam FSM_START= 1; +localparam FSM_RECV = 2; +localparam FSM_STOP = 3; + +// --------------------------------------------------------------------------- +// Output assignment +// + +assign uart_rx_break = uart_rx_valid && ~|recieved_data; +assign uart_rx_valid = fsm_state == FSM_STOP && n_fsm_state == FSM_IDLE; + +always @(posedge clk) begin + if(!resetn) begin + uart_rx_data <= {PAYLOAD_BITS{1'b0}}; + end else if (fsm_state == FSM_STOP) begin + uart_rx_data <= recieved_data; + end +end + +// --------------------------------------------------------------------------- +// FSM next state selection. +// + +wire next_bit = cycle_counter == CYCLES_PER_BIT || + fsm_state == FSM_STOP && + cycle_counter == CYCLES_PER_BIT/2; +wire payload_done = bit_counter == PAYLOAD_BITS ; + +// +// Handle picking the next state. +always @(*) begin : p_n_fsm_state + case(fsm_state) + FSM_IDLE : n_fsm_state = rxd_reg ? FSM_IDLE : FSM_START; + FSM_START: n_fsm_state = next_bit ? FSM_RECV : FSM_START; + FSM_RECV : n_fsm_state = payload_done ? FSM_STOP : FSM_RECV ; + FSM_STOP : n_fsm_state = next_bit ? FSM_IDLE : FSM_STOP ; + default : n_fsm_state = FSM_IDLE; + endcase +end + +// --------------------------------------------------------------------------- +// Internal register setting and re-setting. +// + +// +// Handle updates to the recieved data register. +integer i = 0; +always @(posedge clk) begin : p_recieved_data + if(!resetn) begin + recieved_data <= {PAYLOAD_BITS{1'b0}}; + end else if(fsm_state == FSM_IDLE ) begin + recieved_data <= {PAYLOAD_BITS{1'b0}}; + end else if(fsm_state == FSM_RECV && next_bit ) begin + recieved_data[PAYLOAD_BITS-1] <= bit_sample; + for ( i = PAYLOAD_BITS-2; i >= 0; i = i - 1) begin + recieved_data[i] <= recieved_data[i+1]; + end + end +end + +// +// Increments the bit counter when recieving. +always @(posedge clk) begin : p_bit_counter + if(!resetn) begin + bit_counter <= 4'b0; + end else if(fsm_state != FSM_RECV) begin + bit_counter <= {COUNT_REG_LEN{1'b0}}; + end else if(fsm_state == FSM_RECV && next_bit) begin + bit_counter <= bit_counter + 1'b1; + end +end + +// +// Sample the recieved bit when in the middle of a bit frame. +always @(posedge clk) begin : p_bit_sample + if(!resetn) begin + bit_sample <= 1'b0; + end else if (cycle_counter == CYCLES_PER_BIT/2) begin + bit_sample <= rxd_reg; + end +end + + +// +// Increments the cycle counter when recieving. +always @(posedge clk) begin : p_cycle_counter + if(!resetn) begin + cycle_counter <= {COUNT_REG_LEN{1'b0}}; + end else if(next_bit) begin + cycle_counter <= {COUNT_REG_LEN{1'b0}}; + end else if(fsm_state == FSM_START || + fsm_state == FSM_RECV || + fsm_state == FSM_STOP ) begin + cycle_counter <= cycle_counter + 1'b1; + end +end + + +// +// Progresses the next FSM state. +always @(posedge clk) begin : p_fsm_state + if(!resetn) begin + fsm_state <= FSM_IDLE; + end else begin + fsm_state <= n_fsm_state; + end +end + + +// +// Responsible for updating the internal value of the rxd_reg. +always @(posedge clk) begin : p_rxd_reg + if(!resetn) begin + rxd_reg <= 1'b1; + rxd_reg_0 <= 1'b1; + end else if(uart_rx_en) begin + rxd_reg <= rxd_reg_0; + rxd_reg_0 <= uart_rxd; + end +end + + +endmodule diff --git a/example_demo/sechzig_mx2/uart_tx.v b/example_demo/sechzig_mx2/uart_tx.v new file mode 100644 index 0000000..89906d6 --- /dev/null +++ b/example_demo/sechzig_mx2/uart_tx.v @@ -0,0 +1,187 @@ + + +// +// Module: uart_tx +// +// Notes: +// - UART transmitter module. +// + +module uart_tx( +input wire clk , // Top level system clock input. +input wire resetn , // Asynchronous active low reset. +output wire uart_txd , // UART transmit pin. +output wire uart_tx_busy, // Module busy sending previous item. +input wire uart_tx_en , // Send the data on uart_tx_data +input wire [PAYLOAD_BITS-1:0] uart_tx_data // The data to be sent +); + +// --------------------------------------------------------------------------- +// External parameters. +// + +// +// Input bit rate of the UART line. +parameter BIT_RATE = 9600; // bits / sec +localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds + +// +// Clock frequency in hertz. +parameter CLK_HZ = 50_000_000; +localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds + +// +// Number of data bits recieved per UART packet. +parameter PAYLOAD_BITS = 8; + +// +// Number of stop bits indicating the end of a packet. +parameter STOP_BITS = 1; + +// --------------------------------------------------------------------------- +// Internal parameters. +// + +// +// Number of clock cycles per uart bit. +localparam CYCLES_PER_BIT = BIT_P / CLK_P; + +// +// Size of the registers which store sample counts and bit durations. +localparam COUNT_REG_LEN = 1+$clog2(CYCLES_PER_BIT); + +// --------------------------------------------------------------------------- +// Internal registers. +// + +// +// Internally latched value of the uart_txd line. Helps break long timing +// paths from the logic to the output pins. +reg txd_reg; + +// +// Storage for the serial data to be sent. +reg [PAYLOAD_BITS-1:0] data_to_send; + +// +// Counter for the number of cycles over a packet bit. +reg [COUNT_REG_LEN-1:0] cycle_counter; + +// +// Counter for the number of sent bits of the packet. +reg [3:0] bit_counter; + +// +// Current and next states of the internal FSM. +reg [2:0] fsm_state; +reg [2:0] n_fsm_state; + +localparam FSM_IDLE = 0; +localparam FSM_START= 1; +localparam FSM_SEND = 2; +localparam FSM_STOP = 3; + + +// --------------------------------------------------------------------------- +// FSM next state selection. +// + +assign uart_tx_busy = fsm_state != FSM_IDLE; +assign uart_txd = txd_reg; + +wire next_bit = cycle_counter == CYCLES_PER_BIT; +wire payload_done = bit_counter == PAYLOAD_BITS ; +wire stop_done = bit_counter == STOP_BITS && fsm_state == FSM_STOP; + +// +// Handle picking the next state. +always @(*) begin : p_n_fsm_state + case(fsm_state) + FSM_IDLE : n_fsm_state = uart_tx_en ? FSM_START: FSM_IDLE ; + FSM_START: n_fsm_state = next_bit ? FSM_SEND : FSM_START; + FSM_SEND : n_fsm_state = payload_done ? FSM_STOP : FSM_SEND ; + FSM_STOP : n_fsm_state = stop_done ? FSM_IDLE : FSM_STOP ; + default : n_fsm_state = FSM_IDLE; + endcase +end + +// --------------------------------------------------------------------------- +// Internal register setting and re-setting. +// + +// +// Handle updates to the sent data register. +integer i = 0; +always @(posedge clk) begin : p_data_to_send + if(!resetn) begin + data_to_send <= {PAYLOAD_BITS{1'b0}}; + end else if(fsm_state == FSM_IDLE && uart_tx_en) begin + data_to_send <= uart_tx_data; + end else if(fsm_state == FSM_SEND && next_bit ) begin + for ( i = PAYLOAD_BITS-2; i >= 0; i = i - 1) begin + data_to_send[i] <= data_to_send[i+1]; + end + end +end + + +// +// Increments the bit counter each time a new bit frame is sent. +always @(posedge clk) begin : p_bit_counter + if(!resetn) begin + bit_counter <= 4'b0; + end else if(fsm_state != FSM_SEND && fsm_state != FSM_STOP) begin + bit_counter <= {COUNT_REG_LEN{1'b0}}; + end else if(fsm_state == FSM_SEND && n_fsm_state == FSM_STOP) begin + bit_counter <= {COUNT_REG_LEN{1'b0}}; + end else if(fsm_state == FSM_STOP&& next_bit) begin + bit_counter <= bit_counter + 1'b1; + end else if(fsm_state == FSM_SEND && next_bit) begin + bit_counter <= bit_counter + 1'b1; + end +end + + +// +// Increments the cycle counter when sending. +always @(posedge clk) begin : p_cycle_counter + if(!resetn) begin + cycle_counter <= {COUNT_REG_LEN{1'b0}}; + end else if(next_bit) begin + cycle_counter <= {COUNT_REG_LEN{1'b0}}; + end else if(fsm_state == FSM_START || + fsm_state == FSM_SEND || + fsm_state == FSM_STOP ) begin + cycle_counter <= cycle_counter + 1'b1; + end +end + + +// +// Progresses the next FSM state. +always @(posedge clk) begin : p_fsm_state + if(!resetn) begin + fsm_state <= FSM_IDLE; + end else begin + fsm_state <= n_fsm_state; + end +end + + +// +// Responsible for updating the internal value of the txd_reg. +always @(posedge clk) begin : p_txd_reg + if(!resetn) begin + txd_reg <= 1'b1; + end else if(fsm_state == FSM_IDLE) begin + txd_reg <= 1'b1; + end else if(fsm_state == FSM_START) begin + txd_reg <= 1'b0; + end else if(fsm_state == FSM_SEND) begin + txd_reg <= data_to_send[0]; + end else if(fsm_state == FSM_STOP) begin + txd_reg <= 1'b1; + end +end + +endmodule