diff --git a/example_demo/qmtech_wukong/Makefile b/example_demo/qmtech_wukong/Makefile new file mode 100644 index 0000000..5bee141 --- /dev/null +++ b/example_demo/qmtech_wukong/Makefile @@ -0,0 +1,70 @@ +PROJECT = wukong_ddr3 +FAMILY = artix7 +PART = xc7a100tfgg676-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 *.bit + @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/qmtech_wukong/uart.v b/example_demo/qmtech_wukong/uart.v deleted file mode 100644 index 8739adc..0000000 --- a/example_demo/qmtech_wukong/uart.v +++ /dev/null @@ -1,113 +0,0 @@ -/* - -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 index 9c7985d..1cb2ead 100644 --- a/example_demo/qmtech_wukong/uart_rx.v +++ b/example_demo/qmtech_wukong/uart_rx.v @@ -1,142 +1,207 @@ -/* -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 +// +// 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. ); -reg [DATA_WIDTH-1:0] m_axis_tdata_reg = 0; -reg m_axis_tvalid_reg = 0; +// --------------------------------------------------------------------------- +// External parameters. +// -reg rxd_reg = 1; +// +// Input bit rate of the UART line. +parameter BIT_RATE = 9600; // bits / sec +localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds -reg busy_reg = 0; -reg overrun_error_reg = 0; -reg frame_error_reg = 0; +// +// Clock frequency in hertz. +parameter CLK_HZ = 50_000_000; +localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds -reg [DATA_WIDTH-1:0] data_reg = 0; -reg [18:0] prescale_reg = 0; -reg [3:0] bit_cnt = 0; +// +// Number of data bits recieved per UART packet. +parameter PAYLOAD_BITS = 8; -assign m_axis_tdata = m_axis_tdata_reg; -assign m_axis_tvalid = m_axis_tvalid_reg; +// +// Number of stop bits indicating the end of a packet. +parameter STOP_BITS = 1; -assign busy = busy_reg; -assign overrun_error = overrun_error_reg; -assign frame_error = frame_error_reg; +// -------------------------------------------------------------------------- +// 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 (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(!resetn) begin + uart_rx_data <= {PAYLOAD_BITS{1'b0}}; + end else if (fsm_state == FSM_STOP) begin + uart_rx_data <= recieved_data; + end +end - if (m_axis_tvalid && m_axis_tready) begin - m_axis_tvalid_reg <= 0; - end +// --------------------------------------------------------------------------- +// FSM next state selection. +// - 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 +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/qmtech_wukong/uart_tx.v b/example_demo/qmtech_wukong/uart_tx.v index 518b6d3..89906d6 100644 --- a/example_demo/qmtech_wukong/uart_tx.v +++ b/example_demo/qmtech_wukong/uart_tx.v @@ -1,115 +1,187 @@ -/* -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: +// +// Module: uart_tx +// +// Notes: +// - UART transmitter module. +// -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 +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 ); -reg s_axis_tready_reg = 0; +// --------------------------------------------------------------------------- +// External parameters. +// -reg txd_reg = 1; +// +// Input bit rate of the UART line. +parameter BIT_RATE = 9600; // bits / sec +localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds -reg busy_reg = 0; +// +// Clock frequency in hertz. +parameter CLK_HZ = 50_000_000; +localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds -reg [DATA_WIDTH:0] data_reg = 0; -reg [18:0] prescale_reg = 0; -reg [3:0] bit_cnt = 0; +// +// Number of data bits recieved per UART packet. +parameter PAYLOAD_BITS = 8; -assign s_axis_tready = s_axis_tready_reg; -assign txd = txd_reg; +// +// Number of stop bits indicating the end of a packet. +parameter STOP_BITS = 1; -assign busy = busy_reg; +// --------------------------------------------------------------------------- +// Internal parameters. +// -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; +// +// Number of clock cycles per uart bit. +localparam CYCLES_PER_BIT = BIT_P / CLK_P; - 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 +// +// 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 diff --git a/example_demo/qmtech_wukong/wukong_ddr3.bit b/example_demo/qmtech_wukong/wukong_ddr3.bit deleted file mode 100644 index 81cf9dd..0000000 Binary files a/example_demo/qmtech_wukong/wukong_ddr3.bit and /dev/null differ diff --git a/example_demo/qmtech_wukong/wukong_ddr3.v b/example_demo/qmtech_wukong/wukong_ddr3.v index d101c92..df9ddf5 100644 --- a/example_demo/qmtech_wukong/wukong_ddr3.v +++ b/example_demo/qmtech_wukong/wukong_ddr3.v @@ -75,7 +75,7 @@ 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 + assign led[1] = (o_debug1[4:0] == 23); //light up if not at DONE_CALIBRATE always @(posedge i_controller_clk) begin begin @@ -114,20 +114,33 @@ .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)) + // UART TX/RX module 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 diff --git a/example_demo/qmtech_wukong/wukong_ddr3.xdc b/example_demo/qmtech_wukong/wukong_ddr3.xdc new file mode 100755 index 0000000..9550768 --- /dev/null +++ b/example_demo/qmtech_wukong/wukong_ddr3.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}] +