diff --git a/example_demo/qmtech_wukong/clk_wiz.v b/example_demo/qmtech_wukong/clk_wiz.v new file mode 100644 index 0000000..83e7173 --- /dev/null +++ b/example_demo/qmtech_wukong/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/qmtech_wukong/uart.v b/example_demo/qmtech_wukong/uart.v new file mode 100644 index 0000000..8739adc --- /dev/null +++ b/example_demo/qmtech_wukong/uart.v @@ -0,0 +1,113 @@ +/* + +Copyright (c) 2014-2017 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * AXI4-Stream UART + */ +module uart # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * AXI input + */ + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire s_axis_tvalid, + output wire s_axis_tready, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire m_axis_tvalid, + input wire m_axis_tready, + + /* + * UART interface + */ + input wire rxd, + output wire txd, + + /* + * Status + */ + output wire tx_busy, + output wire rx_busy, + output wire rx_overrun_error, + output wire rx_frame_error, + + /* + * Configuration + */ + input wire [15:0] prescale + +); + +uart_tx #( + .DATA_WIDTH(DATA_WIDTH) +) +uart_tx_inst ( + .clk(clk), + .rst(rst), + // axi input + .s_axis_tdata(s_axis_tdata), + .s_axis_tvalid(s_axis_tvalid), + .s_axis_tready(s_axis_tready), + // output + .txd(txd), + // status + .busy(tx_busy), + // configuration + .prescale(prescale) +); + +uart_rx #( + .DATA_WIDTH(DATA_WIDTH) +) +uart_rx_inst ( + .clk(clk), + .rst(rst), + // axi output + .m_axis_tdata(m_axis_tdata), + .m_axis_tvalid(m_axis_tvalid), + .m_axis_tready(m_axis_tready), + // input + .rxd(rxd), + // status + .busy(rx_busy), + .overrun_error(rx_overrun_error), + .frame_error(rx_frame_error), + // configuration + .prescale(prescale) +); + +endmodule diff --git a/example_demo/qmtech_wukong/uart_rx.v b/example_demo/qmtech_wukong/uart_rx.v new file mode 100644 index 0000000..9c7985d --- /dev/null +++ b/example_demo/qmtech_wukong/uart_rx.v @@ -0,0 +1,142 @@ +/* + +Copyright (c) 2014-2017 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * AXI4-Stream UART + */ +module uart_rx # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire m_axis_tvalid, + input wire m_axis_tready, + + /* + * UART interface + */ + input wire rxd, + + /* + * Status + */ + output wire busy, + output wire overrun_error, + output wire frame_error, + + /* + * Configuration + */ + input wire [15:0] prescale + +); + +reg [DATA_WIDTH-1:0] m_axis_tdata_reg = 0; +reg m_axis_tvalid_reg = 0; + +reg rxd_reg = 1; + +reg busy_reg = 0; +reg overrun_error_reg = 0; +reg frame_error_reg = 0; + +reg [DATA_WIDTH-1:0] data_reg = 0; +reg [18:0] prescale_reg = 0; +reg [3:0] bit_cnt = 0; + +assign m_axis_tdata = m_axis_tdata_reg; +assign m_axis_tvalid = m_axis_tvalid_reg; + +assign busy = busy_reg; +assign overrun_error = overrun_error_reg; +assign frame_error = frame_error_reg; + +always @(posedge clk) begin + if (rst) begin + m_axis_tdata_reg <= 0; + m_axis_tvalid_reg <= 0; + rxd_reg <= 1; + prescale_reg <= 0; + bit_cnt <= 0; + busy_reg <= 0; + overrun_error_reg <= 0; + frame_error_reg <= 0; + end else begin + rxd_reg <= rxd; + overrun_error_reg <= 0; + frame_error_reg <= 0; + + if (m_axis_tvalid && m_axis_tready) begin + m_axis_tvalid_reg <= 0; + end + + if (prescale_reg > 0) begin + prescale_reg <= prescale_reg - 1; + end else if (bit_cnt > 0) begin + if (bit_cnt > DATA_WIDTH+1) begin + if (!rxd_reg) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3)-1; + end else begin + bit_cnt <= 0; + prescale_reg <= 0; + end + end else if (bit_cnt > 1) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3)-1; + data_reg <= {rxd_reg, data_reg[DATA_WIDTH-1:1]}; + end else if (bit_cnt == 1) begin + bit_cnt <= bit_cnt - 1; + if (rxd_reg) begin + m_axis_tdata_reg <= data_reg; + m_axis_tvalid_reg <= 1; + overrun_error_reg <= m_axis_tvalid_reg; + end else begin + frame_error_reg <= 1; + end + end + end else begin + busy_reg <= 0; + if (!rxd_reg) begin + prescale_reg <= (prescale << 2)-2; + bit_cnt <= DATA_WIDTH+2; + data_reg <= 0; + busy_reg <= 1; + end + end + end +end + +endmodule diff --git a/example_demo/qmtech_wukong/uart_tx.v b/example_demo/qmtech_wukong/uart_tx.v new file mode 100644 index 0000000..518b6d3 --- /dev/null +++ b/example_demo/qmtech_wukong/uart_tx.v @@ -0,0 +1,115 @@ +/* + +Copyright (c) 2014-2017 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * AXI4-Stream UART + */ +module uart_tx # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * AXI input + */ + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire s_axis_tvalid, + output wire s_axis_tready, + + /* + * UART interface + */ + output wire txd, + + /* + * Status + */ + output wire busy, + + /* + * Configuration + */ + input wire [15:0] prescale +); + +reg s_axis_tready_reg = 0; + +reg txd_reg = 1; + +reg busy_reg = 0; + +reg [DATA_WIDTH:0] data_reg = 0; +reg [18:0] prescale_reg = 0; +reg [3:0] bit_cnt = 0; + +assign s_axis_tready = s_axis_tready_reg; +assign txd = txd_reg; + +assign busy = busy_reg; + +always @(posedge clk) begin + if (rst) begin + s_axis_tready_reg <= 0; + txd_reg <= 1; + prescale_reg <= 0; + bit_cnt <= 0; + busy_reg <= 0; + end else begin + if (prescale_reg > 0) begin + s_axis_tready_reg <= 0; + prescale_reg <= prescale_reg - 1; + end else if (bit_cnt == 0) begin + s_axis_tready_reg <= 1; + busy_reg <= 0; + + if (s_axis_tvalid) begin + s_axis_tready_reg <= !s_axis_tready_reg; + prescale_reg <= (prescale << 3)-1; + bit_cnt <= DATA_WIDTH+1; + data_reg <= {1'b1, s_axis_tdata}; + txd_reg <= 0; + busy_reg <= 1; + end + end else begin + if (bit_cnt > 1) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3)-1; + {data_reg, txd_reg} <= {1'b0, data_reg}; + end else if (bit_cnt == 1) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3); + txd_reg <= 1; + end + end + end +end + +endmodule diff --git a/example_demo/qmtech_wukong/wukong.xdc b/example_demo/qmtech_wukong/wukong.xdc new file mode 100755 index 0000000..bb328dd --- /dev/null +++ b/example_demo/qmtech_wukong/wukong.xdc @@ -0,0 +1,537 @@ +## Clock Signals +set_property -dict {PACKAGE_PIN M21 IOSTANDARD LVCMOS33} [get_ports i_clk] +create_clock -period 20.000 -name sys_clk_pin -waveform {0.000 10.000} -add [get_ports i_clk] + +## Reset +set_property -dict {PACKAGE_PIN H7 IOSTANDARD LVCMOS33} [get_ports i_rst_n] + +## LEDs +set_property -dict {PACKAGE_PIN G21 IOSTANDARD LVCMOS33} [get_ports {led[0]}] +set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports {led[1]}] + +## DDR3 +# PadFunction: IO_L18N_T2_16 + +set_property SLEW FAST [get_ports {ddr3_dq[0]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[0]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[0]}] + +set_property PACKAGE_PIN D21 [get_ports {ddr3_dq[0]}] + + + +# PadFunction: IO_L16P_T2_16 + +set_property SLEW FAST [get_ports {ddr3_dq[1]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[1]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[1]}] + +set_property PACKAGE_PIN C21 [get_ports {ddr3_dq[1]}] + + + +# PadFunction: IO_L17P_T2_16 + +set_property SLEW FAST [get_ports {ddr3_dq[2]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[2]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[2]}] + +set_property PACKAGE_PIN B22 [get_ports {ddr3_dq[2]}] + + + +# PadFunction: IO_L16N_T2_16 + +set_property SLEW FAST [get_ports {ddr3_dq[3]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[3]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[3]}] + +set_property PACKAGE_PIN B21 [get_ports {ddr3_dq[3]}] + + + +# PadFunction: IO_L13P_T2_MRCC_16 + +set_property SLEW FAST [get_ports {ddr3_dq[4]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[4]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[4]}] + +set_property PACKAGE_PIN D19 [get_ports {ddr3_dq[4]}] + + + +# PadFunction: IO_L14P_T2_SRCC_16 + +set_property SLEW FAST [get_ports {ddr3_dq[5]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[5]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[5]}] + +set_property PACKAGE_PIN E20 [get_ports {ddr3_dq[5]}] + + + +# PadFunction: IO_L13N_T2_MRCC_16 + +set_property SLEW FAST [get_ports {ddr3_dq[6]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[6]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[6]}] + +set_property PACKAGE_PIN C19 [get_ports {ddr3_dq[6]}] + + + +# PadFunction: IO_L14N_T2_SRCC_16 + +set_property SLEW FAST [get_ports {ddr3_dq[7]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[7]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[7]}] + +set_property PACKAGE_PIN D20 [get_ports {ddr3_dq[7]}] + + + +# PadFunction: IO_L19N_T3_VREF_16 + +set_property SLEW FAST [get_ports {ddr3_dq[8]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[8]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[8]}] + +set_property PACKAGE_PIN C23 [get_ports {ddr3_dq[8]}] + + + +# PadFunction: IO_L24P_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dq[9]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[9]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[9]}] + +set_property PACKAGE_PIN D23 [get_ports {ddr3_dq[9]}] + + + +# PadFunction: IO_L23N_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dq[10]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[10]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[10]}] + +set_property PACKAGE_PIN B24 [get_ports {ddr3_dq[10]}] + + + +# PadFunction: IO_L20P_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dq[11]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[11]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[11]}] + +set_property PACKAGE_PIN B25 [get_ports {ddr3_dq[11]}] + + + +# PadFunction: IO_L23P_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dq[12]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[12]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[12]}] + +set_property PACKAGE_PIN C24 [get_ports {ddr3_dq[12]}] + + + +# PadFunction: IO_L22P_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dq[13]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[13]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[13]}] + +set_property PACKAGE_PIN C26 [get_ports {ddr3_dq[13]}] + + + +# PadFunction: IO_L20N_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dq[14]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[14]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[14]}] + +set_property PACKAGE_PIN A25 [get_ports {ddr3_dq[14]}] + + + +# PadFunction: IO_L22N_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dq[15]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dq[15]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[15]}] + +set_property PACKAGE_PIN B26 [get_ports {ddr3_dq[15]}] + + + +# PadFunction: IO_L4P_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[13]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[13]}] + +set_property PACKAGE_PIN G15 [get_ports {ddr3_addr[13]}] + + + +# PadFunction: IO_L12N_T1_MRCC_16 + +set_property SLEW FAST [get_ports {ddr3_addr[12]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[12]}] + +set_property PACKAGE_PIN C18 [get_ports {ddr3_addr[12]}] + + + +# PadFunction: IO_L1N_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[11]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[11]}] + +set_property PACKAGE_PIN H15 [get_ports {ddr3_addr[11]}] + + + +# PadFunction: IO_L5N_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[10]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[10]}] + +set_property PACKAGE_PIN F20 [get_ports {ddr3_addr[10]}] + + + +# PadFunction: IO_L4N_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[9]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[9]}] + +set_property PACKAGE_PIN F15 [get_ports {ddr3_addr[9]}] + + + +# PadFunction: IO_L1P_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[8]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[8]}] + +set_property PACKAGE_PIN H14 [get_ports {ddr3_addr[8]}] + + + +# PadFunction: IO_L8P_T1_16 + +set_property SLEW FAST [get_ports {ddr3_addr[7]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[7]}] + +set_property PACKAGE_PIN E16 [get_ports {ddr3_addr[7]}] + + + +# PadFunction: IO_L6P_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[6]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[6]}] + +set_property PACKAGE_PIN H16 [get_ports {ddr3_addr[6]}] + + + +# PadFunction: IO_L8N_T1_16 + +set_property SLEW FAST [get_ports {ddr3_addr[5]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[5]}] + +set_property PACKAGE_PIN D16 [get_ports {ddr3_addr[5]}] + + + +# PadFunction: IO_L6N_T0_VREF_16 + +set_property SLEW FAST [get_ports {ddr3_addr[4]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[4]}] + +set_property PACKAGE_PIN G16 [get_ports {ddr3_addr[4]}] + + + +# PadFunction: IO_L7P_T1_16 + +set_property SLEW FAST [get_ports {ddr3_addr[3]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[3]}] + +set_property PACKAGE_PIN C17 [get_ports {ddr3_addr[3]}] + + + +# PadFunction: IO_L2N_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[2]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[2]}] + +set_property PACKAGE_PIN F17 [get_ports {ddr3_addr[2]}] + + + +# PadFunction: IO_L2P_T0_16 + +set_property SLEW FAST [get_ports {ddr3_addr[1]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[1]}] + +set_property PACKAGE_PIN G17 [get_ports {ddr3_addr[1]}] + + + +# PadFunction: IO_L11P_T1_SRCC_16 + +set_property SLEW FAST [get_ports {ddr3_addr[0]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_addr[0]}] + +set_property PACKAGE_PIN E17 [get_ports {ddr3_addr[0]}] + + + +# PadFunction: IO_L9P_T1_DQS_16 + +set_property SLEW FAST [get_ports {ddr3_ba[2]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_ba[2]}] + +set_property PACKAGE_PIN A17 [get_ports {ddr3_ba[2]}] + + + +# PadFunction: IO_L12P_T1_MRCC_16 + +set_property SLEW FAST [get_ports {ddr3_ba[1]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_ba[1]}] + +set_property PACKAGE_PIN D18 [get_ports {ddr3_ba[1]}] + + + +# PadFunction: IO_L7N_T1_16 + +set_property SLEW FAST [get_ports {ddr3_ba[0]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_ba[0]}] + +set_property PACKAGE_PIN B17 [get_ports {ddr3_ba[0]}] + + + +# PadFunction: IO_L10N_T1_16 + +set_property SLEW FAST [get_ports ddr3_ras_n] + +set_property IOSTANDARD SSTL135 [get_ports ddr3_ras_n] + +set_property PACKAGE_PIN A19 [get_ports ddr3_ras_n] + + + +# PadFunction: IO_L10P_T1_16 + +set_property SLEW FAST [get_ports ddr3_cas_n] + +set_property IOSTANDARD SSTL135 [get_ports ddr3_cas_n] + +set_property PACKAGE_PIN B19 [get_ports ddr3_cas_n] + + + +# PadFunction: IO_L9N_T1_DQS_16 + +set_property SLEW FAST [get_ports ddr3_we_n] + +set_property IOSTANDARD SSTL135 [get_ports ddr3_we_n] + +set_property PACKAGE_PIN A18 [get_ports ddr3_we_n] + + + +# PadFunction: IO_0_16 + +set_property SLEW FAST [get_ports ddr3_reset_n] + +set_property IOSTANDARD SSTL135 [get_ports ddr3_reset_n] + +set_property PACKAGE_PIN H17 [get_ports ddr3_reset_n] + + + +# PadFunction: IO_L11N_T1_SRCC_16 + +set_property SLEW FAST [get_ports ddr3_cke] + +set_property IOSTANDARD SSTL135 [get_ports ddr3_cke] + +set_property PACKAGE_PIN E18 [get_ports ddr3_cke] + + + +# PadFunction: IO_L5P_T0_16 + +set_property SLEW FAST [get_ports ddr3_odt] + +set_property IOSTANDARD SSTL135 [get_ports ddr3_odt] + +set_property PACKAGE_PIN G19 [get_ports ddr3_odt] + + + +# PadFunction: IO_L17N_T2_16 + +set_property SLEW FAST [get_ports {ddr3_dm[0]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dm[0]}] + +set_property PACKAGE_PIN A22 [get_ports {ddr3_dm[0]}] + + + +# PadFunction: IO_L19P_T3_16 + +set_property SLEW FAST [get_ports {ddr3_dm[1]}] + +set_property IOSTANDARD SSTL135 [get_ports {ddr3_dm[1]}] + +set_property PACKAGE_PIN C22 [get_ports {ddr3_dm[1]}] + + + +# PadFunction: IO_L15P_T2_DQS_16 + +set_property SLEW FAST [get_ports {ddr3_dqs_p[0]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dqs_p[0]}] + +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_dqs_p[0]}] + + + + +# PadFunction: IO_L15N_T2_DQS_16 + +set_property SLEW FAST [get_ports {ddr3_dqs_n[0]}] + +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddr3_dqs_n[0]}] + +set_property IOSTANDARD DIFF_SSTL135 [get_ports {ddr3_dqs_n[0]}] + +set_property PACKAGE_PIN B20 [get_ports {ddr3_dqs_p[0]}] +set_property PACKAGE_PIN A20 [get_ports {ddr3_dqs_n[0]}] + + + +# PadFunction: IO_L21P_T3_DQS_16 + +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_SSTL135 [get_ports {ddr3_dqs_p[1]}] + + + + +# PadFunction: IO_L21N_T3_DQS_16 + +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_SSTL135 [get_ports {ddr3_dqs_n[1]}] + +set_property PACKAGE_PIN A23 [get_ports {ddr3_dqs_p[1]}] +set_property PACKAGE_PIN A24 [get_ports {ddr3_dqs_n[1]}] + + + +# PadFunction: IO_L3P_T0_DQS_16 + +set_property SLEW FAST [get_ports ddr3_clk_p] + +set_property IOSTANDARD DIFF_SSTL135 [get_ports ddr3_clk_p] + + + + +# PadFunction: IO_L3N_T0_DQS_16 + +set_property SLEW FAST [get_ports ddr3_clk_n] + +set_property IOSTANDARD DIFF_SSTL135 [get_ports ddr3_clk_n] + +set_property PACKAGE_PIN F18 [get_ports ddr3_clk_p] +set_property PACKAGE_PIN F19 [get_ports ddr3_clk_n] + + + +## UART +set_property PACKAGE_PIN F3 [get_ports rx] +set_property IOSTANDARD LVCMOS33 [get_ports rx] +set_property PACKAGE_PIN E3 [get_ports tx] +set_property IOSTANDARD LVCMOS33 [get_ports tx] + + +set_property INTERNAL_VREF 0.675 [get_iobanks 16] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] + + +## Place the IOSERDES_train manually (else the tool will place this blocks which can block the route for CLKB0 (OBUFDS for ddr3_clk_p)) +set_property LOC OLOGIC_X0Y91 [get_cells {ddr3_top/ddr3_phy_inst/genblk5[1].OSERDESE2_train}] +set_property LOC ILOGIC_X0Y94 [get_cells {ddr3_top/ddr3_phy_inst/genblk5[0].ISERDESE2_train}] + diff --git a/example_demo/qmtech_wukong/wukong_ddr3.bit b/example_demo/qmtech_wukong/wukong_ddr3.bit new file mode 100644 index 0000000..81cf9dd Binary files /dev/null and b/example_demo/qmtech_wukong/wukong_ddr3.bit differ diff --git a/example_demo/qmtech_wukong/wukong_ddr3.v b/example_demo/qmtech_wukong/wukong_ddr3.v new file mode 100644 index 0000000..d101c92 --- /dev/null +++ b/example_demo/qmtech_wukong/wukong_ddr3.v @@ -0,0 +1,202 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: wukong_ddr3.v +// Project: UberDDR3 - An Open Source DDR3 Controller +// +// Purpose: Example demo of UberDDR3 for QMTech Wukong (xc7a100tfgg676-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 +// +// 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 wukong_ddr3 + ( + input wire i_clk, + input wire i_rst_n, + // 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[1:0] 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[0] = !(o_debug1[4:0] == 23); //light up if at DONE_CALIBRATE + assign led[1] = !(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 + + (* 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(i_clk) + ); + + // UART module from https://github.com/alexforencich/verilog-uart + uart #(.DATA_WIDTH(8)) uart_m + ( + .clk(i_controller_clk), + .rst(!i_rst_n), + .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 (83.33MHz/(8*9600)) + ); + + // 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 + ( + //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 +