Merge pull request #26 from AngeloJacobo/openxc7_run
Now tested working on OpenXC7 toolchain
This commit is contained in:
commit
a34a5369ec
|
|
@ -25,8 +25,7 @@ TOP_VERILOG ?= ${TOP}.v
|
|||
|
||||
PNR_DEBUG ?= # --verbose --debug
|
||||
|
||||
BOARD ?= UNKNOWN
|
||||
JTAG_LINK ?= --board ${BOARD}
|
||||
JTAG_LINK ?= -c digilent_hs2
|
||||
|
||||
XDC ?= ${PROJECT}.xdc
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -238,9 +238,7 @@
|
|||
.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()
|
||||
.o_debug1(o_debug1)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ TOP_VERILOG ?= ${TOP}.v
|
|||
PNR_DEBUG ?= # --verbose --debug
|
||||
|
||||
BOARD ?= UNKNOWN
|
||||
JTAG_LINK ?= --board ${BOARD}
|
||||
JTAG_LINK ?= -c digilent_hs2
|
||||
|
||||
XDC ?= ${PROJECT}.xdc
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -85,10 +85,10 @@
|
|||
//assign ddr3_cs_n[1] = 1'b1;
|
||||
|
||||
//===========================================================================
|
||||
//Differentia system clock to single end clock
|
||||
//Differential system clock to single end clock
|
||||
//===========================================================================
|
||||
wire sys_clk; // 200MHz
|
||||
IBUFGDS u_ibufg_sys_clk
|
||||
IBUFDS u_ibufg_sys_clk
|
||||
(
|
||||
.I (sys_clk_p),
|
||||
.IB (sys_clk_n),
|
||||
|
|
@ -132,22 +132,36 @@
|
|||
.clk_in1(sys_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.3333MHz/(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
|
||||
ddr3_top #(
|
||||
.CONTROLLER_CLK_PERIOD(12_000), //ps, clock period of the controller interface
|
||||
|
|
@ -213,9 +227,7 @@
|
|||
.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()
|
||||
.o_debug1(o_debug1)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -260,8 +260,6 @@ set_property CONFIG_MODE SPIx4 [current_design]
|
|||
## be set to enable an internal VREF for BANK 34. Since a 1.35v supply is being
|
||||
## used the internal reference is set to half that value (i.e. 0.675v). Note that
|
||||
## this property must be set even if SW3 is not used in the design.
|
||||
|
||||
## COMMENT THIS OUT IF RUNNING IN OPENXC7 (OTHERWISE UNCOMMENT THIS)
|
||||
# set_property INTERNAL_VREF 0.675 [get_iobanks 34]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,16 @@ module clk_wiz
|
|||
output clk_out1,
|
||||
output clk_out2,
|
||||
output clk_out3,
|
||||
output clk_out4,
|
||||
output clk_out5,
|
||||
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 clk_out5_clk_wiz_0;
|
||||
|
||||
wire clkfbout;
|
||||
|
||||
|
|
@ -20,17 +24,23 @@ module clk_wiz
|
|||
.COMPENSATION ("INTERNAL"),
|
||||
.STARTUP_WAIT ("FALSE"),
|
||||
.DIVCLK_DIVIDE (1),
|
||||
.CLKFBOUT_MULT (10), // 200 MHz * 10 = 2000 MHz
|
||||
.CLKFBOUT_MULT (5), // 200 MHz * 5 = 1000 MHz
|
||||
.CLKFBOUT_PHASE (0.000),
|
||||
.CLKOUT0_DIVIDE (12), // 2000 MHz / 12 = 166.67 MHz
|
||||
.CLKOUT0_DIVIDE (12), // 1000 MHz / 12 = 83.333 MHz
|
||||
.CLKOUT0_PHASE (0.000),
|
||||
.CLKOUT0_DUTY_CYCLE (0.500),
|
||||
.CLKOUT1_DIVIDE (3), // 2000 MHz / 3 = 666.67 MHz
|
||||
.CLKOUT1_DIVIDE (3), // 1000 MHz / 3 = 333.333 MHz
|
||||
.CLKOUT1_PHASE (0.000),
|
||||
.CLKOUT1_DUTY_CYCLE (0.500),
|
||||
.CLKOUT2_DIVIDE (10), // 2000 MHz / 10 = 200 MHz
|
||||
.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),
|
||||
// .CLKOUT4_DIVIDE (3), // 1000 MHz / 3 = 333.333 MHz, 180 phase
|
||||
// .CLKOUT4_PHASE (180),
|
||||
// .CLKOUT4_DUTY_CYCLE (0.500),
|
||||
.CLKIN1_PERIOD (5) // 200 MHz input
|
||||
)
|
||||
plle2_adv_inst
|
||||
|
|
@ -39,6 +49,8 @@ module clk_wiz
|
|||
.CLKOUT0 (clk_out1_clk_wiz_0),
|
||||
.CLKOUT1 (clk_out2_clk_wiz_0),
|
||||
.CLKOUT2 (clk_out3_clk_wiz_0),
|
||||
// .CLKOUT3 (clk_out4_clk_wiz_0),
|
||||
// .CLKOUT4 (clk_out5_clk_wiz_0),
|
||||
.CLKFBIN (clkfbout),
|
||||
.CLKIN1 (clk_in1),
|
||||
.LOCKED (locked),
|
||||
|
|
@ -53,5 +65,10 @@ module clk_wiz
|
|||
BUFG clkout3_buf
|
||||
(.O (clk_out3),
|
||||
.I (clk_out3_clk_wiz_0));
|
||||
|
||||
// BUFG clkout4_buf
|
||||
// (.O (clk_out4),
|
||||
// .I (clk_out4_clk_wiz_0));
|
||||
// BUFG clkout5_buf
|
||||
// (.O (clk_out5),
|
||||
// .I (clk_out5_clk_wiz_0));
|
||||
endmodule
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -111,39 +111,39 @@
|
|||
|
||||
wire clk_locked;
|
||||
// PLL
|
||||
// clk_wiz clk_wiz_inst
|
||||
// (
|
||||
// // Clock out ports
|
||||
// .clk_out1(i_controller_clk), // 166 Mhz
|
||||
// .clk_out2(i_ddr3_clk), // 1333 MHz
|
||||
// .clk_out3(i_ref_clk), // 200 MHz
|
||||
// // Status and control signals
|
||||
// .reset(!i_rst_n),
|
||||
// .locked(clk_locked),
|
||||
// // Clock in ports
|
||||
// .clk_in1(sys_clk_200MHz)
|
||||
// );
|
||||
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), // 200 MHz
|
||||
// Status and control signals
|
||||
.reset(!i_rst_n),
|
||||
.locked(clk_locked),
|
||||
// Clock in ports
|
||||
.clk_in1(sys_clk_200MHz)
|
||||
);
|
||||
|
||||
// Clock Wizard
|
||||
wire clkfb_out;
|
||||
clk_wiz_0 clk_wiz_inst
|
||||
(
|
||||
// Clock out ports
|
||||
.controller_clk(i_controller_clk),
|
||||
.ddr3_clk(i_ddr3_clk),
|
||||
.ref200_clk(i_ref_clk),
|
||||
// Status and control signals
|
||||
.reset(!i_rst_n),
|
||||
.locked(clk_locked),
|
||||
// Clock in ports
|
||||
.clk_in1(sys_clk_200MHz)
|
||||
);
|
||||
// wire clkfb_out;
|
||||
// clk_wiz_0 clk_wiz_inst
|
||||
// (
|
||||
// // Clock out ports
|
||||
// .controller_clk(i_controller_clk),
|
||||
// .ddr3_clk(i_ddr3_clk),
|
||||
// .ref200_clk(i_ref_clk),
|
||||
// // Status and control signals
|
||||
// .reset(!i_rst_n),
|
||||
// .locked(clk_locked),
|
||||
// // Clock in ports
|
||||
// .clk_in1(sys_clk_200MHz)
|
||||
// );
|
||||
|
||||
|
||||
// UART TX/RX module from https://github.com/ben-marshall/uart
|
||||
uart_tx #(
|
||||
.BIT_RATE(9600),
|
||||
.CLK_HZ(200_000_000),
|
||||
.CLK_HZ(83_333_333),
|
||||
.PAYLOAD_BITS(8),
|
||||
.STOP_BITS(1)
|
||||
) uart_tx_inst (
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
);
|
||||
uart_rx #(
|
||||
.BIT_RATE(9600),
|
||||
.CLK_HZ(200_000_000),
|
||||
.CLK_HZ(83_333_333),
|
||||
.PAYLOAD_BITS(8),
|
||||
.STOP_BITS(1)
|
||||
) uart_rx_inst (
|
||||
|
|
@ -188,8 +188,8 @@
|
|||
|
||||
// DDR3 Controller
|
||||
ddr3_top #(
|
||||
.CONTROLLER_CLK_PERIOD(5_000), //ps, clock period of the controller interface
|
||||
.DDR3_CLK_PERIOD(1_250), //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD)
|
||||
.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(15), //width of row address
|
||||
.COL_BITS(10), //width of column address
|
||||
.BA_BITS(3), //width of bank address
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# cpu_reset_n:0
|
||||
set_property PACKAGE_PIN C22 [get_ports i_rst_n]
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports i_rst_n]
|
||||
set_property -dict {PACKAGE_PIN AD23 IOSTANDARD LVCMOS18} [get_ports btn]
|
||||
# set_property -dict {PACKAGE_PIN AD23 IOSTANDARD LVCMOS18} [get_ports btn]
|
||||
|
||||
# clk200:0.p
|
||||
set_property IOSTANDARD LVDS [get_ports i_clk200_p]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
PROJECT = qmtech_kintex7_ddr3
|
||||
FAMILY = kintex7
|
||||
PART = xc7k325tffg676-1
|
||||
CHIPDB = ${KINTEX7_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 ?= -c digilent_hs2
|
||||
|
||||
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
|
||||
|
|
@ -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
|
||||
Binary file not shown.
|
|
@ -0,0 +1,209 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Filename: qmtech_kintex7_ddr3.v
|
||||
// Project: UberDDR3 - An Open Source DDR3 Controller
|
||||
//
|
||||
// Purpose: Example demo of UberDDR3 for QMTech Kintex-7 (xc7k325tffg676-1). Mechanism:
|
||||
// - Two LEDs will light up once UberDDR3 is done calibrating
|
||||
// - UART line is not available
|
||||
//
|
||||
// Engineer: Angelo C. Jacobo
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023-2025 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 <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module qmtech_kintex7_ddr3
|
||||
(
|
||||
input wire i_clk,
|
||||
input wire i_rst_n,
|
||||
// DDR3 I/O Interface
|
||||
output wire[0:0] ddr3_ck_p, ddr3_ck_n,
|
||||
output wire ddr3_reset_n,
|
||||
output wire[0:0] 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 (No UART line)
|
||||
// input wire rx,
|
||||
// output wire tx,
|
||||
//Debug LEDs
|
||||
output wire[2: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 not at DONE_CALIBRATE
|
||||
assign led[2] = !(o_debug1[4:0] == 23); //light up if not 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 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
|
||||
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(1), //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_ck_p),
|
||||
.o_ddr3_clk_n(ddr3_ck_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)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
## Clock Signals
|
||||
set_property -dict {PACKAGE_PIN F22 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 U26 IOSTANDARD LVCMOS33} [get_ports i_rst_n]
|
||||
|
||||
## LEDs
|
||||
set_property -dict {PACKAGE_PIN R26 IOSTANDARD LVCMOS33} [get_ports {led[0]}]
|
||||
set_property -dict {PACKAGE_PIN P26 IOSTANDARD LVCMOS33} [get_ports {led[1]}]
|
||||
set_property -dict {PACKAGE_PIN N26 IOSTANDARD LVCMOS33} [get_ports {led[2]}]
|
||||
|
||||
## DDR3
|
||||
|
||||
# PadFunction: IO_L10P_T1_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[0]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[0]}]
|
||||
set_property PACKAGE_PIN W1 [get_ports {ddr3_dq[0]}]
|
||||
|
||||
# PadFunction: IO_L8P_T1_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[1]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[1]}]
|
||||
set_property PACKAGE_PIN V2 [get_ports {ddr3_dq[1]}]
|
||||
|
||||
# PadFunction: IO_L10N_T1_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[2]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[2]}]
|
||||
set_property PACKAGE_PIN Y1 [get_ports {ddr3_dq[2]}]
|
||||
|
||||
# PadFunction: IO_L7P_T1_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[3]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[3]}]
|
||||
set_property PACKAGE_PIN Y3 [get_ports {ddr3_dq[3]}]
|
||||
|
||||
# PadFunction: IO_L11N_T1_SRCC_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[4]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[4]}]
|
||||
set_property PACKAGE_PIN AC2 [get_ports {ddr3_dq[4]}]
|
||||
|
||||
# PadFunction: IO_L7N_T1_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[5]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[5]}]
|
||||
set_property PACKAGE_PIN Y2 [get_ports {ddr3_dq[5]}]
|
||||
|
||||
# PadFunction: IO_L11P_T1_SRCC_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[6]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[6]}]
|
||||
set_property PACKAGE_PIN AB2 [get_ports {ddr3_dq[6]}]
|
||||
|
||||
# PadFunction: IO_L12P_T1_MRCC_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[7]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[7]}]
|
||||
set_property PACKAGE_PIN AA3 [get_ports {ddr3_dq[7]}]
|
||||
|
||||
# PadFunction: IO_L2N_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[8]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[8]}]
|
||||
set_property PACKAGE_PIN U1 [get_ports {ddr3_dq[8]}]
|
||||
|
||||
# PadFunction: IO_L6P_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[9]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[9]}]
|
||||
set_property PACKAGE_PIN V4 [get_ports {ddr3_dq[9]}]
|
||||
|
||||
# PadFunction: IO_L1P_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[10]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[10]}]
|
||||
set_property PACKAGE_PIN U6 [get_ports {ddr3_dq[10]}]
|
||||
|
||||
# PadFunction: IO_L4N_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[11]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[11]}]
|
||||
set_property PACKAGE_PIN W3 [get_ports {ddr3_dq[11]}]
|
||||
|
||||
# PadFunction: IO_L5N_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[12]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[12]}]
|
||||
set_property PACKAGE_PIN V6 [get_ports {ddr3_dq[12]}]
|
||||
|
||||
# PadFunction: IO_L2P_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[13]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[13]}]
|
||||
set_property PACKAGE_PIN U2 [get_ports {ddr3_dq[13]}]
|
||||
|
||||
# PadFunction: IO_L5P_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[14]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[14]}]
|
||||
set_property PACKAGE_PIN U7 [get_ports {ddr3_dq[14]}]
|
||||
|
||||
# PadFunction: IO_L1N_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dq[15]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[15]}]
|
||||
set_property PACKAGE_PIN U5 [get_ports {ddr3_dq[15]}]
|
||||
|
||||
# PadFunction: IO_L17P_T2_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[13]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[13]}]
|
||||
set_property PACKAGE_PIN Y6 [get_ports {ddr3_addr[13]}]
|
||||
|
||||
# PadFunction: IO_L13N_T2_MRCC_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[12]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[12]}]
|
||||
set_property PACKAGE_PIN AB4 [get_ports {ddr3_addr[12]}]
|
||||
|
||||
# PadFunction: IO_L18N_T2_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[11]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[11]}]
|
||||
set_property PACKAGE_PIN AD5 [get_ports {ddr3_addr[11]}]
|
||||
|
||||
# PadFunction: IO_L22P_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[10]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[10]}]
|
||||
set_property PACKAGE_PIN AE3 [get_ports {ddr3_addr[10]}]
|
||||
|
||||
# PadFunction: IO_L23P_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[9]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[9]}]
|
||||
set_property PACKAGE_PIN AE6 [get_ports {ddr3_addr[9]}]
|
||||
|
||||
# PadFunction: IO_L13P_T2_MRCC_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[8]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[8]}]
|
||||
set_property PACKAGE_PIN AA4 [get_ports {ddr3_addr[8]}]
|
||||
|
||||
# PadFunction: IO_L17N_T2_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[7]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[7]}]
|
||||
set_property PACKAGE_PIN Y5 [get_ports {ddr3_addr[7]}]
|
||||
|
||||
# PadFunction: IO_L22N_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[6]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[6]}]
|
||||
set_property PACKAGE_PIN AE2 [get_ports {ddr3_addr[6]}]
|
||||
|
||||
# PadFunction: IO_L16P_T2_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[5]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[5]}]
|
||||
set_property PACKAGE_PIN AB6 [get_ports {ddr3_addr[5]}]
|
||||
|
||||
# PadFunction: IO_L19P_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[4]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[4]}]
|
||||
set_property PACKAGE_PIN AD4 [get_ports {ddr3_addr[4]}]
|
||||
|
||||
# PadFunction: IO_L16N_T2_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[3]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[3]}]
|
||||
set_property PACKAGE_PIN AC6 [get_ports {ddr3_addr[3]}]
|
||||
|
||||
# PadFunction: IO_L18P_T2_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[2]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[2]}]
|
||||
set_property PACKAGE_PIN AD6 [get_ports {ddr3_addr[2]}]
|
||||
|
||||
# PadFunction: IO_L24N_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[1]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[1]}]
|
||||
set_property PACKAGE_PIN AF2 [get_ports {ddr3_addr[1]}]
|
||||
|
||||
# PadFunction: IO_L21P_T3_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_addr[0]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_addr[0]}]
|
||||
set_property PACKAGE_PIN AF5 [get_ports {ddr3_addr[0]}]
|
||||
|
||||
# PadFunction: IO_L23N_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_ba[2]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[2]}]
|
||||
set_property PACKAGE_PIN AE5 [get_ports {ddr3_ba[2]}]
|
||||
|
||||
# PadFunction: IO_L20N_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_ba[1]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[1]}]
|
||||
set_property PACKAGE_PIN AE1 [get_ports {ddr3_ba[1]}]
|
||||
|
||||
# PadFunction: IO_L19N_T3_VREF_34
|
||||
set_property SLEW FAST [get_ports {ddr3_ba[0]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_ba[0]}]
|
||||
set_property PACKAGE_PIN AD3 [get_ports {ddr3_ba[0]}]
|
||||
|
||||
# PadFunction: IO_L14N_T2_SRCC_34
|
||||
set_property SLEW FAST [get_ports {ddr3_ras_n}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_ras_n}]
|
||||
set_property PACKAGE_PIN AC3 [get_ports {ddr3_ras_n}]
|
||||
|
||||
# PadFunction: IO_L14P_T2_SRCC_34
|
||||
set_property SLEW FAST [get_ports {ddr3_cas_n}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_cas_n}]
|
||||
set_property PACKAGE_PIN AC4 [get_ports {ddr3_cas_n}]
|
||||
|
||||
# PadFunction: IO_L21N_T3_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_we_n}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_we_n}]
|
||||
set_property PACKAGE_PIN AF4 [get_ports {ddr3_we_n}]
|
||||
|
||||
# PadFunction: IO_L6N_T0_VREF_34
|
||||
set_property SLEW FAST [get_ports {ddr3_reset_n}]
|
||||
set_property IOSTANDARD LVCMOS15 [get_ports {ddr3_reset_n}]
|
||||
set_property PACKAGE_PIN W4 [get_ports {ddr3_reset_n}]
|
||||
|
||||
# PadFunction: IO_L20P_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_cke}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_cke}]
|
||||
set_property PACKAGE_PIN AD1 [get_ports {ddr3_cke}]
|
||||
|
||||
# PadFunction: IO_L24P_T3_34
|
||||
set_property SLEW FAST [get_ports {ddr3_odt}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_odt}]
|
||||
set_property PACKAGE_PIN AF3 [get_ports {ddr3_odt}]
|
||||
|
||||
# PadFunction: IO_L8N_T1_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dm[0]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[0]}]
|
||||
set_property PACKAGE_PIN V1 [get_ports {ddr3_dm[0]}]
|
||||
|
||||
# PadFunction: IO_L4P_T0_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dm[1]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dm[1]}]
|
||||
set_property PACKAGE_PIN V3 [get_ports {ddr3_dm[1]}]
|
||||
|
||||
# PadFunction: IO_L9P_T1_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dqs_p[0]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dqs_p[0]}]
|
||||
set_property PACKAGE_PIN AB1 [get_ports {ddr3_dqs_p[0]}]
|
||||
|
||||
# PadFunction: IO_L9N_T1_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dqs_n[0]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dqs_n[0]}]
|
||||
set_property PACKAGE_PIN AC1 [get_ports {ddr3_dqs_n[0]}]
|
||||
|
||||
# PadFunction: IO_L3P_T0_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dqs_p[1]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dqs_p[1]}]
|
||||
set_property PACKAGE_PIN W6 [get_ports {ddr3_dqs_p[1]}]
|
||||
|
||||
# PadFunction: IO_L3N_T0_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_dqs_n[1]}]
|
||||
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dqs_n[1]}]
|
||||
set_property PACKAGE_PIN W5 [get_ports {ddr3_dqs_n[1]}]
|
||||
|
||||
# PadFunction: IO_L15P_T2_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_ck_p}]
|
||||
set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_ck_p}]
|
||||
set_property PACKAGE_PIN AA5 [get_ports {ddr3_ck_p}]
|
||||
|
||||
# PadFunction: IO_L15N_T2_DQS_34
|
||||
set_property SLEW FAST [get_ports {ddr3_ck_n}]
|
||||
set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddr3_ck_n}]
|
||||
set_property PACKAGE_PIN AB5 [get_ports {ddr3_ck_n}]
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -27,7 +27,7 @@ TOP_VERILOG ?= ${TOP}.v
|
|||
PNR_DEBUG ?= # --verbose --debug
|
||||
|
||||
BOARD ?= UNKNOWN
|
||||
JTAG_LINK ?= --board ${BOARD}
|
||||
JTAG_LINK ?= -c digilent_hs2
|
||||
|
||||
XDC ?= ${PROJECT}.xdc
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -206,9 +206,7 @@
|
|||
.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()
|
||||
.o_debug1(o_debug1)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -46,6 +46,19 @@
|
|||
//`define DDR3_1333_9_9_9
|
||||
//`define DDR3_1066_7_7_7
|
||||
//
|
||||
// Choose which debug message will be displayed via UART:
|
||||
// `define UART_DEBUG_READ_LEVEL
|
||||
// `define UART_DEBUG_WRITE_LEVEL
|
||||
// `define UART_DEBUG_ALIGN
|
||||
|
||||
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
`define UART_DEBUG
|
||||
`elsif UART_DEBUG_WRITE_LEVEL
|
||||
`define UART_DEBUG
|
||||
`elsif UART_DEBUG_ALIGN
|
||||
`define UART_DEBUG
|
||||
`endif
|
||||
|
||||
module ddr3_controller #(
|
||||
parameter integer CONTROLLER_CLK_PERIOD = 10_000, //ps, clock period of the controller interface
|
||||
|
|
@ -143,7 +156,9 @@ module ddr3_controller #(
|
|||
// output wire [31:0] o_debug2,
|
||||
// output wire [31:0] o_debug3
|
||||
// User enabled self-refresh
|
||||
input wire i_user_self_refresh
|
||||
input wire i_user_self_refresh,
|
||||
// Display debug messages via UART
|
||||
output wire uart_tx
|
||||
);
|
||||
|
||||
|
||||
|
|
@ -609,7 +624,24 @@ module ddr3_controller #(
|
|||
wire db_err_o;
|
||||
wire[wb_data_bits - 1:0] o_wb_data_q_decoded;
|
||||
reg user_self_refresh_q; // registered i_user_self_refresh
|
||||
|
||||
reg[$clog2(wb_sel_bits)-1:0] write_by_byte_counter = 0;
|
||||
`ifdef UART_DEBUG
|
||||
// uart interface logic for displaying debug messages
|
||||
wire uart_tx_busy;
|
||||
reg uart_tx_en;
|
||||
reg[7:0] uart_tx_data;
|
||||
reg[100*8-1:0] uart_text; // max of 100 chars
|
||||
reg[2:0] state_uart_send;
|
||||
reg uart_start_send;
|
||||
reg[9:0] uart_text_length_index;
|
||||
reg uart_send_busy;
|
||||
localparam UART_FSM_IDLE = 0,
|
||||
UART_FSM_SEND_BYTE = 1,
|
||||
UART_FSM_WAIT_SEND = 2,
|
||||
WAIT_UART = 24;
|
||||
reg[3:0] track_report = 0;
|
||||
reg[$clog2(DONE_CALIBRATE)-1:0] state_calibrate_next;
|
||||
`endif
|
||||
// initial block for all regs
|
||||
initial begin
|
||||
o_wb_stall = 1;
|
||||
|
|
@ -1212,8 +1244,9 @@ module ddr3_controller #(
|
|||
stage2_data_unaligned[((DQ_BITS*LANES)*5 + 8*index) +: 8], stage2_data_unaligned[((DQ_BITS*LANES)*4 + 8*index) +: 8],
|
||||
stage2_data_unaligned[((DQ_BITS*LANES)*3 + 8*index) +: 8], stage2_data_unaligned[((DQ_BITS*LANES)*2 + 8*index) +: 8],
|
||||
stage2_data_unaligned[((DQ_BITS*LANES)*1 + 8*index) +: 8], stage2_data_unaligned[((DQ_BITS*LANES)*0 + 8*index) +: 8] }
|
||||
<< data_start_index[index]) | unaligned_data[index];
|
||||
|
||||
<< {data_start_index[index][$clog2(64):1], 1'b0} ) | unaligned_data[index];
|
||||
// data_start_index is set to 1 so this if statement will pass, but shift left is zero (lsb of data_start_index is removed) which means
|
||||
// DQ is 1 whole controller cycle early (happens in Kintex-7 with OpenXC7)
|
||||
{unaligned_dm[index], {
|
||||
stage2_dm[1][LANES*7 + index], stage2_dm[1][LANES*6 + index],
|
||||
stage2_dm[1][LANES*5 + index], stage2_dm[1][LANES*4 + index],
|
||||
|
|
@ -2157,7 +2190,6 @@ module ddr3_controller #(
|
|||
|
||||
|
||||
/******************************************************* Read/Write Calibration Sequence *******************************************************/
|
||||
reg[$clog2(wb_sel_bits)-1:0] write_by_byte_counter = 0;
|
||||
always @(posedge i_controller_clk) begin
|
||||
if(sync_rst_controller) begin
|
||||
state_calibrate <= IDLE;
|
||||
|
|
@ -2208,6 +2240,12 @@ module ddr3_controller #(
|
|||
reset_after_rank_1 <= 1'b0;
|
||||
lane_write_dq_late <= 0;
|
||||
lane_read_dq_early <= 0;
|
||||
`ifdef UART_DEBUG
|
||||
uart_start_send <= 0;
|
||||
uart_text <= 0;
|
||||
track_report <= 0;
|
||||
state_calibrate_next <= IDLE;
|
||||
`endif
|
||||
for(index = 0; index < LANES; index = index + 1) begin
|
||||
added_read_pipe[index] <= 0;
|
||||
data_start_index[index] <= 0;
|
||||
|
|
@ -2287,6 +2325,12 @@ module ddr3_controller #(
|
|||
o_phy_write_leveling_calib <= 0;
|
||||
initial_calibration_done <= 1'b0;
|
||||
final_calibration_done <= 1'b0;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=IDLE",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= BITSLIP_DQS_TRAIN_1;
|
||||
`endif
|
||||
end
|
||||
else if(instruction_address == 13) begin
|
||||
pause_counter <= 1; //pause instruction address @13 until read calibration finishes
|
||||
|
|
@ -2305,6 +2349,12 @@ module ddr3_controller #(
|
|||
initial_dqs <= 1;
|
||||
dqs_start_index_repeat <= 0;
|
||||
dqs_start_index_stored <= 0;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=BITSLIP_DQS_TRAIN_1",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= MPR_READ;
|
||||
`endif
|
||||
end
|
||||
else begin
|
||||
o_phy_bitslip[lane] <= 1;
|
||||
|
|
@ -2337,7 +2387,30 @@ module ddr3_controller #(
|
|||
dqs_start_index_stored <= dqs_start_index;
|
||||
// start the index from zero since this will be incremented until we pinpoint the real
|
||||
// starting bit of dqs_store (dictated by the pattern 10'b01_01_01_01_00)
|
||||
dqs_start_index <= 0;
|
||||
dqs_start_index <= 0;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
// show dqs_store in binary form
|
||||
uart_text <= {8'h0a,"state=COLLECT_DQS, lane=",hex_to_ascii(lane),", dqs_store= ",
|
||||
hex_to_ascii(dqs_store[39]), hex_to_ascii(dqs_store[38]),
|
||||
hex_to_ascii(dqs_store[37]), hex_to_ascii(dqs_store[36]),
|
||||
hex_to_ascii(dqs_store[35]), hex_to_ascii(dqs_store[34]),
|
||||
hex_to_ascii(dqs_store[33]), hex_to_ascii(dqs_store[32]), "_" ,
|
||||
hex_to_ascii(dqs_store[31]), hex_to_ascii(dqs_store[30]),
|
||||
hex_to_ascii(dqs_store[29]), hex_to_ascii(dqs_store[28]),
|
||||
hex_to_ascii(dqs_store[27]), hex_to_ascii(dqs_store[26]),
|
||||
hex_to_ascii(dqs_store[25]), hex_to_ascii(dqs_store[24]), "_" ,
|
||||
hex_to_ascii(dqs_store[23]), hex_to_ascii(dqs_store[22]),
|
||||
hex_to_ascii(dqs_store[21]), hex_to_ascii(dqs_store[20]),
|
||||
hex_to_ascii(dqs_store[19]), hex_to_ascii(dqs_store[18]),
|
||||
hex_to_ascii(dqs_store[17]), hex_to_ascii(dqs_store[16]), "_" ,
|
||||
hex_to_ascii(dqs_store[15]), hex_to_ascii(dqs_store[14]),
|
||||
hex_to_ascii(dqs_store[13]), hex_to_ascii(dqs_store[12]),
|
||||
hex_to_ascii(dqs_store[11]), hex_to_ascii(dqs_store[10]),
|
||||
hex_to_ascii(dqs_store[9]), hex_to_ascii(dqs_store[8]), 8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ANALYZE_DQS;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
// find the bit where the DQS starts to be issued (by finding when the pattern 10'b01_01_01_01_00 starts)
|
||||
|
|
@ -2352,9 +2425,23 @@ module ddr3_controller #(
|
|||
initial_dqs <= 0;
|
||||
dqs_start_index_repeat <= 0;
|
||||
state_calibrate <= CALIBRATE_DQS;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DQS, REPEAT_DQS_ANALYZE == dqs_start_index_repeat:",hex_to_ascii(dqs_start_index_repeat),
|
||||
", final dqs_start_index=0x", hex_to_ascii(dqs_start_index[5:4]), hex_to_ascii(dqs_start_index[3:0]), 8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= CALIBRATE_DQS;
|
||||
`endif
|
||||
end
|
||||
else begin
|
||||
state_calibrate <= MPR_READ;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DQS, REPEAT_DQS_ANALYZE != dqs_start_index_repeat:", hex_to_ascii(dqs_start_index_repeat),
|
||||
", final dqs_start_index=0x", hex_to_ascii(dqs_start_index[5:4]), hex_to_ascii(dqs_start_index[3:0]), 8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= MPR_READ;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
else begin
|
||||
|
|
@ -2363,9 +2450,21 @@ module ddr3_controller #(
|
|||
o_phy_idelay_dqs_ld[lane] <= 1;
|
||||
state_calibrate <= MPR_READ;
|
||||
delay_before_read_data <= 10; //wait for sometime to make sure idelay load settles
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DQS, Glitch: Reached End", 8'h0a,"----------------------",8'h0a,8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= MPR_READ;
|
||||
`endif
|
||||
end
|
||||
else begin
|
||||
dqs_start_index <= dqs_start_index + 1;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DQS, dqs_start_index=0x", hex_to_ascii(dqs_start_index[5:4]), hex_to_ascii(dqs_start_index[3:0]), 8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ANALYZE_DQS;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
// check if the index when the dqs starts is the same as the target index which is aligned to the ddr3_clk
|
||||
|
|
@ -2383,6 +2482,13 @@ module ddr3_controller #(
|
|||
// expected bitslip arrangement of 8'b0111_1000 will not be followed anymore, so here we form the bitslip
|
||||
// arrangement pattern so incoming dqs (and thus DQ) is arranged in the proper way (first bute firs, last byte last)
|
||||
state_calibrate <= BITSLIP_DQS_TRAIN_2;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {8'h0a,"state=CALIBRATE_DQS, REACHED dqs_target_index=0x", hex_to_ascii(dqs_target_index[5:4]),
|
||||
hex_to_ascii(dqs_target_index[3:0]), 8'h0a,"----------------------",8'h0a,8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= BITSLIP_DQS_TRAIN_2;
|
||||
`endif
|
||||
end
|
||||
else begin
|
||||
// if we have not yet reached the target index then increment IDELAY
|
||||
|
|
@ -2394,6 +2500,15 @@ module ddr3_controller #(
|
|||
o_phy_idelay_dqs_ld[lane] <= 1;
|
||||
state_calibrate <= MPR_READ;
|
||||
delay_before_read_data <= 10; //wait for sometime to make sure idelay load settles
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {8'h0a,"state=CALIBRATE_DQS, stored(0x", hex_to_ascii(dqs_start_index_stored[5:4]),hex_to_ascii(dqs_start_index_stored[3:0]),
|
||||
") != target(0x", hex_to_ascii(dqs_target_index[5:4]), hex_to_ascii(dqs_target_index[3:0]), "), o_phy_idelay_data_cntvaluein=0x",
|
||||
hex_to_ascii(o_phy_idelay_data_cntvaluein[4]), hex_to_ascii(o_phy_idelay_data_cntvaluein[3:0]),
|
||||
8'h0a,"------------",8'h0a,8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= MPR_READ;
|
||||
`endif
|
||||
end
|
||||
//the dqs is delayed (to move starting bit to next odd number) so this means the original
|
||||
// expected bitslip arrangement of 8'b0111_1000 will not be followed anymore, so here the bitslip
|
||||
|
|
@ -2404,7 +2519,6 @@ module ddr3_controller #(
|
|||
// this is the end of training and calibration for a single lane, so proceed to next lane
|
||||
if(lane == LANES - 1) begin
|
||||
/* verilator lint_on WIDTH */
|
||||
pause_counter <= 0; //read calibration now complete so continue the reset instruction sequence
|
||||
lane <= 0;
|
||||
odelay_cntvalue_halfway <= 0;
|
||||
prev_write_level_feedback <= 1'b1;
|
||||
|
|
@ -2412,10 +2526,24 @@ module ddr3_controller #(
|
|||
stored_write_level_feedback <= 0;
|
||||
o_phy_write_leveling_calib <= 1;
|
||||
state_calibrate <= START_WRITE_LEVEL;
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=BITSLIP_DQS_TRAIN_2, Done All Lanes",8'h0a,
|
||||
"--------------------------------------------------", 8'h0a, 8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= START_WRITE_LEVEL;
|
||||
`endif
|
||||
end
|
||||
else begin
|
||||
lane <= lane + 1;
|
||||
state_calibrate <= BITSLIP_DQS_TRAIN_1;// current lane is done so go back to BITSLIP_DQS_TRAIN_1 to train next lane
|
||||
`ifdef UART_DEBUG_READ_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=BITSLIP_DQS_TRAIN_2, Done lane=", hex_to_ascii(lane),8'h0a,
|
||||
"--------------------------------------------------", 8'h0a, 8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= BITSLIP_DQS_TRAIN_1;
|
||||
`endif
|
||||
end
|
||||
// stores the highest value of added_read_pipe among the lanes since all lanes (except the lane with highest
|
||||
// added_read_pipe) will be delayed to align with the lane with highest added_read_pipe. This alignment
|
||||
|
|
@ -2428,20 +2556,23 @@ module ddr3_controller #(
|
|||
end
|
||||
end
|
||||
// CONTINUE COMMENT HERE (once blog is done)
|
||||
START_WRITE_LEVEL: if(!ODELAY_SUPPORTED) begin //skip write levelling if ODELAY is not supported
|
||||
START_WRITE_LEVEL: if(!ODELAY_SUPPORTED) begin //skip write levelling if ODELAY is not supported
|
||||
pause_counter <= 0;
|
||||
lane <= 0;
|
||||
state_calibrate <= ISSUE_WRITE_1;
|
||||
write_calib_odt <= 0;
|
||||
o_phy_write_leveling_calib <= 0;
|
||||
end
|
||||
else if(instruction_address == 17) begin
|
||||
end
|
||||
else if(instruction_address == 17) begin
|
||||
write_calib_dqs <= 1'b1;
|
||||
write_calib_odt <= 1'b1;
|
||||
delay_before_write_level_feedback <= DELAY_BEFORE_WRITE_LEVEL_FEEDBACK[$clog2(DELAY_BEFORE_WRITE_LEVEL_FEEDBACK):0];
|
||||
state_calibrate <= WAIT_FOR_FEEDBACK;
|
||||
pause_counter <= 1; // pause instruction address @17 until write calibration finishes
|
||||
end
|
||||
end
|
||||
else begin // read calibration done so continue instruction address counter
|
||||
pause_counter <= 0;
|
||||
end
|
||||
|
||||
WAIT_FOR_FEEDBACK: if(delay_before_write_level_feedback == 0) begin
|
||||
/* verilator lint_off WIDTH */ //_verilator warning: Bit extraction of var[511:0] requires 9 bit index, not 3 bits (but [lane<<3] is much simpler and cleaner)
|
||||
|
|
@ -2461,6 +2592,12 @@ module ddr3_controller #(
|
|||
lane <= 0;
|
||||
o_phy_write_leveling_calib <= 0;
|
||||
state_calibrate <= ISSUE_WRITE_1;
|
||||
`ifdef UART_DEBUG_WRITE_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=WAIT_FOR_FEEDBACK, All Lanes Done",8'h0a,"----------------------",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ISSUE_WRITE_1;
|
||||
`endif
|
||||
end
|
||||
else begin
|
||||
lane <= lane + 1;
|
||||
|
|
@ -2468,6 +2605,12 @@ module ddr3_controller #(
|
|||
prev_write_level_feedback <= 1'b1;
|
||||
sample_clk_repeat <= 0;
|
||||
state_calibrate <= START_WRITE_LEVEL;
|
||||
`ifdef UART_DEBUG_WRITE_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=WAIT_FOR_FEEDBACK, Done lane=",hex_to_ascii(lane),8'h0a,"----------------------",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= START_WRITE_LEVEL;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
else begin
|
||||
|
|
@ -2479,8 +2622,24 @@ module ddr3_controller #(
|
|||
// odelay_dqs_cntvaluein[lane] <= DQS_INITIAL_ODELAY_TAP[4:0];
|
||||
// end
|
||||
state_calibrate <= START_WRITE_LEVEL;
|
||||
`ifdef UART_DEBUG_WRITE_LEVEL
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=WAIT_FOR_FEEDBACK, lane=",hex_to_ascii(lane), ", {prev,stored}=", hex_to_ascii(prev_write_level_feedback),
|
||||
hex_to_ascii(stored_write_level_feedback), ", o_phy_odelay_data_cntvaluein=0x", hex_to_ascii(o_phy_odelay_data_cntvaluein[4]),
|
||||
hex_to_ascii(o_phy_odelay_data_cntvaluein[3:0]), 8'h0a,8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= START_WRITE_LEVEL;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
`ifdef UART_DEBUG_WRITE_LEVEL
|
||||
else begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=WAIT_FOR_FEEDBACK, sample_clk_repeat=",hex_to_ascii(sample_clk_repeat),8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= START_WRITE_LEVEL;
|
||||
end
|
||||
`endif
|
||||
end
|
||||
|
||||
ISSUE_WRITE_1: if(instruction_address == 22 && !o_wb_stall_calib) begin
|
||||
|
|
@ -2544,6 +2703,22 @@ module ddr3_controller #(
|
|||
//0x01b79fa4ebe2587b
|
||||
//0x22ee5319a15aa382
|
||||
write_pattern <= 128'h80dbcfd275f12c3d_9177298cd0ad51c1;
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
// display o_wb_data_uncalibrated of current lane
|
||||
// uart_text <= {8'h0a,8'h0a,"state=READ_DATA, read_data_store[lane]= 0x",
|
||||
// hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*7 + 8*lane) +: 8]), hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*6 + 8*lane) +: 8]),
|
||||
// hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*5 + 8*lane) +: 8]), hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*4 + 8*lane) +: 8]),
|
||||
// hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*3 + 8*lane) +: 8]), hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*2 + 8*lane) +: 8]),
|
||||
// hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*1 + 8*lane) +: 8]), hex8_to_ascii(o_wb_data_uncalibrated[((DQ_BITS*LANES)*0 + 8*lane) +: 8]), 8'h0a};
|
||||
//
|
||||
// view o_wb_data_uncalibrated in raw form (view in Hex form)
|
||||
uart_text <= {8'h0a,8'h0a, o_wb_data_uncalibrated,
|
||||
8'h0a,8'h0a
|
||||
};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ANALYZE_DATA;
|
||||
`endif
|
||||
end
|
||||
else if(!o_wb_stall_calib) begin
|
||||
calib_stb <= 0;
|
||||
|
|
@ -2563,10 +2738,22 @@ module ddr3_controller #(
|
|||
/* verilator lint_on WIDTH */
|
||||
state_calibrate <= BIST_MODE == 0? FINISH_READ : BURST_WRITE; // go straight to FINISH_READ if BIST_MODE == 0
|
||||
initial_calibration_done <= 1'b1;
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DATA, Done All Lanes",8'h0a,"-----------------",8'h0a,8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= BIST_MODE == 0? FINISH_READ : BURST_WRITE;
|
||||
`endif
|
||||
end
|
||||
else begin
|
||||
lane <= lane + 1;
|
||||
data_start_index[lane+1] <= 0;
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DATA, Done lane=",hex_to_ascii(lane),8'h0a,"-----------------",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ANALYZE_DATA;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
else begin
|
||||
|
|
@ -2579,6 +2766,12 @@ module ddr3_controller #(
|
|||
data_start_index[lane] <= 0; // set delay to outgoing stage2_data back to zero
|
||||
if(data_start_index[lane] == 0) begin // if already set to zero then we already did write-read with default zero data_start_index, so we go to CHECK_STARTING_DATA to try second assumtpion
|
||||
state_calibrate <= CHECK_STARTING_DATA;
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DATA, lane=",hex_to_ascii(lane), ", First Assumption wrong, Start second assumption: Read too early",8'h0a,8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= CHECK_STARTING_DATA;
|
||||
`endif
|
||||
end
|
||||
else begin // if not yet zero then we have to write-read again
|
||||
state_calibrate <= ISSUE_WRITE_1;
|
||||
|
|
@ -2589,7 +2782,22 @@ module ddr3_controller #(
|
|||
data_start_index[lane] <= 0;
|
||||
start_index_check <= 0;
|
||||
state_calibrate <= CHECK_STARTING_DATA;
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DATA, lane=",hex_to_ascii(lane), ", Reached end",8'h0a,8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= CHECK_STARTING_DATA;
|
||||
`endif
|
||||
end
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
else begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=ANALYZE_DATA, lane=",hex_to_ascii(lane), ", data_start_index[lane]=0x",
|
||||
hex_to_ascii(data_start_index[lane][6:4]),hex_to_ascii(data_start_index[lane][3:0]),8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ANALYZE_DATA;
|
||||
end
|
||||
`endif
|
||||
end
|
||||
|
||||
// check when the 4 MSB of write_pattern {d0ad51c1} starts on read_lane_data (read_lane_data is just the concatenation of read_data_store of a specific lane)
|
||||
|
|
@ -2603,6 +2811,12 @@ module ddr3_controller #(
|
|||
state_calibrate <= ISSUE_WRITE_1; // start writing again (the next write should fix the late DQ for this current lane)
|
||||
data_start_index[lane] <= 64 - start_index_check; // stage2_data_unaligned is forwarded to stage[1] so we are now 8-bursts early, so we subtract from 64 so the burst we will be forwarded to the tip of stage2_data
|
||||
lane_write_dq_late[lane] <= 1'b1;
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=CHECK_STARTING_DATA, start_index_check=0x",hex8_to_ascii(start_index_check), ", Ongoing First Assumption",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ISSUE_WRITE_1;
|
||||
`endif
|
||||
end
|
||||
// if first assumption is not the fix then second assmption: controller reads the DQ too early (THUS WE NEED TO CALIBRATE INCOMING DQ SIGNAL starting from bitslip training)
|
||||
else begin
|
||||
|
|
@ -2611,14 +2825,42 @@ module ddr3_controller #(
|
|||
added_read_pipe[lane] <= { {( 4 - ($clog2(STORED_DQS_SIZE*8) - (3+1)) ){1'b0}} , dq_target_index[lane][$clog2(STORED_DQS_SIZE*8)-1:(3+1)] }
|
||||
+ { 3'b0 , (dq_target_index[lane][3:0] >= (5+8)) };
|
||||
dqs_bitslip_arrangement <= 16'b0011_1100_0011_1100 >> dq_target_index[lane][2:0];
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=CHECK_STARTING_DATA, start_index_check=0x",hex8_to_ascii(start_index_check), ", Ongoing Second Assumption",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= BITSLIP_DQS_TRAIN_3;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
else begin
|
||||
start_index_check <= start_index_check + 16; // plus 16, we assume here that DQ will be late BY 1 DDR3 CLK CYCLE (if only +8, then it will be late by half DDR3 cycle, that should NOT happen)
|
||||
dq_target_index[lane] <= dq_target_index[lane] + 2;
|
||||
if(start_index_check == 48)begin //if value is too high, we are outside the possible values so we need to reset now
|
||||
reset_from_calibrate <= 1;
|
||||
if(start_index_check == 48)begin // start_index_check is now outside the possible values
|
||||
// first assumption: controller DQ is 1 CONTROLLER CYCLE late WHEN WRITING (data is written to address 1 and not address 0)
|
||||
if(!lane_write_dq_late[lane]) begin // lane_write_dq_late is not yet set so we know this first assunmption is not yet tested
|
||||
state_calibrate <= ISSUE_WRITE_1; // start writing again (the next write should fix the late DQ for this current lane)
|
||||
data_start_index[lane] <= 1; // stage2_data_unaligned is forwarded to stage[1] so we are now 8-bursts early, since assumption is we are 1 controller cycle early then data_start_index is 64
|
||||
lane_write_dq_late[lane] <= 1'b1;
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=CHECK_STARTING_DATA, Reached end, First Assumption: Write is 1 Controller cycle early",8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= ISSUE_WRITE_1;
|
||||
`endif
|
||||
end
|
||||
else begin // if first assumption is wrong and start_index_check is still outside of possible values then reset
|
||||
reset_from_calibrate <= 1;
|
||||
end
|
||||
end
|
||||
`ifdef UART_DEBUG_ALIGN
|
||||
else begin
|
||||
uart_start_send <= 1'b1;
|
||||
uart_text <= {"state=CHECK_STARTING_DATA, start_index_check=", hex_to_ascii(start_index_check[5:4]), hex_to_ascii(start_index_check[3:0]),8'h0a};
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= CHECK_STARTING_DATA;
|
||||
end
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -2809,8 +3051,16 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
|
|||
pause_counter <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
endcase
|
||||
`ifdef UART_DEBUG
|
||||
WAIT_UART: if(!uart_send_busy && !uart_start_send) begin // wait here until UART is finished
|
||||
state_calibrate <= state_calibrate_next;
|
||||
end
|
||||
else if(uart_send_busy) begin // if already busy then uart_start_send can be deasserted
|
||||
uart_start_send <= 0;
|
||||
end
|
||||
`endif
|
||||
endcase
|
||||
|
||||
`ifdef FORMAL_COVER
|
||||
state_calibrate <= DONE_CALIBRATE;
|
||||
`endif
|
||||
|
|
@ -2836,8 +3086,145 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
|
|||
read_test_address_counter <= 0;
|
||||
write_test_address_counter <= 0;
|
||||
end
|
||||
`ifdef UART_DEBUG
|
||||
if(wrong_read_data != 0 && !uart_send_busy && !uart_start_send) begin
|
||||
uart_start_send <= 1'b1;
|
||||
track_report <= track_report + 1;
|
||||
case(track_report)
|
||||
0: uart_text <= {"RESET, # correct(ascii)=0x",
|
||||
hex8_to_ascii(correct_read_data[7:0]),
|
||||
hex8_to_ascii(correct_read_data[15:8]),
|
||||
hex8_to_ascii(correct_read_data[23:16]),
|
||||
8'h0a, 8'h0a, wrong_data, 8'h0a, 8'h0a
|
||||
};
|
||||
1: uart_text <= {"RESET, #correct(raw)=0x",8'h0a,8'h0a,
|
||||
correct_read_data, 8'h0a,8'h0a,
|
||||
", #wrong(raw)=0x", 8'h0a,8'h0a,
|
||||
wrong_read_data, 8'h0a,8'h0a
|
||||
};
|
||||
2: uart_text <= {"RESET, wrong_data(raw)=0x",8'h0a,8'h0a,
|
||||
wrong_data, 8'h0a,8'h0a
|
||||
};
|
||||
3: uart_text <= {"RESET, correct_data(raw)=0x",8'h0a,8'h0a,
|
||||
expected_data, 8'h0a,8'h0a
|
||||
};
|
||||
endcase
|
||||
state_calibrate <= WAIT_UART;
|
||||
state_calibrate_next <= WAIT_UART;
|
||||
end
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
//------------------------------------- START OF UART SERIALIZER----------------------------------------------------------------//
|
||||
`ifdef UART_DEBUG
|
||||
reg[19:0] uart_idle_timer = 0;
|
||||
// FSM for uart
|
||||
// uart_text = "Hello" , uart_text_length = 5
|
||||
// [5<<3-1 (39):4<<3 (32)] = "H" , [4<<3-1 (31):3<<3(24)] = "e" , [3<<3-1(23):2<<3(16)] = "l" , [2<<3-1(15):1<<3(8)] = "l" , [1<<3-1(7):0<<3(0)] = "o"
|
||||
always @(posedge i_controller_clk, negedge i_rst_n) begin
|
||||
if(!i_rst_n) begin
|
||||
state_uart_send <= UART_FSM_IDLE;
|
||||
uart_text_length_index <= 0;
|
||||
uart_tx_en <= 0;
|
||||
uart_send_busy <= 0;
|
||||
uart_tx_data <= 0;
|
||||
uart_idle_timer <= 0;
|
||||
end
|
||||
else begin
|
||||
case(state_uart_send)
|
||||
UART_FSM_IDLE: if (uart_start_send) begin // if receive request to send via uart
|
||||
state_uart_send <= UART_FSM_SEND_BYTE;
|
||||
uart_text_length_index <= count_chars(uart_text)+5;
|
||||
uart_send_busy <= 1;
|
||||
uart_idle_timer <= MICRON_SIM? {5{1'b1}} : {20{1'b1}}; // set to all 1s for idle time
|
||||
end
|
||||
else begin
|
||||
uart_tx_en <= 1'b0;
|
||||
uart_send_busy <= 1'b0;
|
||||
end
|
||||
|
||||
UART_FSM_SEND_BYTE: if(!uart_tx_busy) begin // if uart tx is not busy, send character
|
||||
uart_tx_en <= 1'b1;
|
||||
uart_tx_data <= uart_text[((uart_text_length_index)<<3) +: 8];
|
||||
end
|
||||
else begin // once busy, go to wait state
|
||||
state_uart_send <= UART_FSM_WAIT_SEND;
|
||||
uart_tx_en <= 1'b0;
|
||||
end
|
||||
|
||||
UART_FSM_WAIT_SEND: if(!uart_tx_busy) begin // if not busy again, then uart is done sending
|
||||
if(uart_text_length_index != 0) begin // if not yet at 0, go to next character
|
||||
uart_text_length_index <= uart_text_length_index - 1;
|
||||
state_uart_send <= UART_FSM_SEND_BYTE;
|
||||
end
|
||||
else if(uart_idle_timer == 0) begin // if not busy anymore, all characters sent, and timer done
|
||||
state_uart_send <= UART_FSM_IDLE;
|
||||
end
|
||||
else begin // if not busy anymore, all characters sent, but uart_idle_timer not yet at zero
|
||||
uart_idle_timer <= uart_idle_timer - 1;
|
||||
end
|
||||
end
|
||||
default: state_uart_send <= UART_FSM_IDLE;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Function to convert hex to ASCII
|
||||
function [7:0] hex_to_ascii;
|
||||
input [3:0] hex;
|
||||
begin
|
||||
if (hex < 4'd10)
|
||||
hex_to_ascii = hex + 8'd48; // ASCII for '0'-'9'
|
||||
else
|
||||
hex_to_ascii = hex + 8'd55; // ASCII for 'A'-'F'
|
||||
end
|
||||
endfunction
|
||||
|
||||
// Function to convert 8-bit hex to two ASCII characters
|
||||
function [15:0] hex8_to_ascii;
|
||||
input [7:0] hex;
|
||||
begin
|
||||
hex8_to_ascii[15:8] = (hex[7:4] < 4'd10) ? (hex[7:4] + 8'd48) : (hex[7:4] + 8'd55);
|
||||
hex8_to_ascii[7:0] = (hex[3:0] < 4'd10) ? (hex[3:0] + 8'd48) : (hex[3:0] + 8'd55);
|
||||
end
|
||||
endfunction
|
||||
|
||||
uart_tx #(
|
||||
.BIT_RATE(MICRON_SIM? (((1_000_000/CONTROLLER_CLK_PERIOD) * 1_000_000)/1) : 9600),
|
||||
.CLK_HZ( (1_000_000/CONTROLLER_CLK_PERIOD) * 1_000_000),
|
||||
.PAYLOAD_BITS(8),
|
||||
.STOP_BITS(1)
|
||||
) uart_tx_inst (
|
||||
.clk(i_controller_clk), // Top level system clock input
|
||||
.resetn(i_rst_n), // Asynchronous active low reset.
|
||||
.uart_txd(uart_tx) , // UART transmit pin.
|
||||
.uart_tx_busy(uart_tx_busy), // Module busy sending previous item.
|
||||
.uart_tx_en(uart_tx_en), // Send the data on uart_tx_data
|
||||
.uart_tx_data(uart_tx_data) // The data to be sent
|
||||
);
|
||||
|
||||
function integer count_chars;
|
||||
input [8*256-1:0] str;
|
||||
integer i;
|
||||
begin
|
||||
count_chars = 0;
|
||||
begin : loop_block
|
||||
for (i = 0; i < 256; i = i + 1) begin
|
||||
if (str[8*i +: 8] !== 8'h00 && str[8*i +: 8] !== 8'hFF) begin // Avoid garbage values
|
||||
count_chars = count_chars + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
count_chars = count_chars + 1; // Include \n at the end
|
||||
end
|
||||
endfunction
|
||||
|
||||
`else
|
||||
assign uart_tx = 1; // tx constant 1 when UART not used
|
||||
`endif
|
||||
//------------------------------------- END OF UART SERIALIZER----------------------------------------------------------------//
|
||||
|
||||
// generate calib_data for BIST
|
||||
// Uses different operations (XOR, addition, subtraction, bit rotation) to generate different values per byte.
|
||||
// When MICRON_SIM=1, then we use the relevant bits (7:0 will be zero since during simulation the increment is a large number)
|
||||
|
|
@ -2879,7 +3266,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
|
|||
/*********************************************************************************************************************************************/
|
||||
|
||||
/******************************************************* Calibration Test Receiver *******************************************************/
|
||||
reg[wb_data_bits-1:0] wrong_data = 0;
|
||||
reg[wb_data_bits-1:0] wrong_data = 0, expected_data=0;
|
||||
wire[wb_data_bits-1:0] correct_data;
|
||||
|
||||
generate
|
||||
|
|
@ -2945,6 +3332,7 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
|
|||
else begin
|
||||
wrong_read_data <= wrong_read_data + 1;
|
||||
wrong_data <= o_wb_data;
|
||||
expected_data <= correct_data;
|
||||
reset_from_test <= !final_calibration_done; //reset controller when a wrong data is received (only when calibration is not yet done)
|
||||
end
|
||||
/* verilator lint_off WIDTHEXPAND */
|
||||
|
|
@ -3209,10 +3597,10 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
|
|||
// Find the correct value for CL based on ddr3 clock period
|
||||
function[3:0] CL_generator(input integer ddr3_clk_period);
|
||||
begin
|
||||
if(ddr3_clk_period <= 3_300 && ddr3_clk_period >= 3_000) begin
|
||||
if(/*ddr3_clk_period <= 3_300 &&*/ ddr3_clk_period >= 3_000) begin // cover ddr3 clk periods > 3.3ns
|
||||
CL_generator = 4'd5;
|
||||
end
|
||||
else if(ddr3_clk_period <= 3_300 && ddr3_clk_period >= 2_500) begin
|
||||
else if(/*ddr3_clk_period <= 3_300 &&*/ ddr3_clk_period >= 2_500) begin
|
||||
CL_generator = 4'd6;
|
||||
end
|
||||
else if(ddr3_clk_period <= 2_500 && ddr3_clk_period >= 1_875) begin
|
||||
|
|
@ -3230,10 +3618,10 @@ ALTERNATE_WRITE_READ: if(!o_wb_stall_calib) begin
|
|||
// Find the correct value for CWL based on ddr3 clock period
|
||||
function[3:0] CWL_generator(input integer ddr3_clk_period);
|
||||
begin
|
||||
if(ddr3_clk_period <= 3_300 && ddr3_clk_period >= 3_000) begin
|
||||
if(/*ddr3_clk_period <= 3_300 &&*/ ddr3_clk_period >= 3_000) begin
|
||||
CWL_generator = 4'd5;
|
||||
end
|
||||
else if(ddr3_clk_period <= 3_300 && ddr3_clk_period >= 2_500) begin
|
||||
else if(/*ddr3_clk_period <= 3_300 &&*/ ddr3_clk_period >= 2_500) begin
|
||||
CWL_generator = 4'd5;
|
||||
end
|
||||
else if(ddr3_clk_period <= 2_500 && ddr3_clk_period >= 1_875) begin
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ module ddr3_top #(
|
|||
// output wire[(DQ_BITS*BYTE_LANES)/8-1:0] o_ddr3_debug_read_dqs_n
|
||||
//
|
||||
// User enabled self-refresh
|
||||
input wire i_user_self_refresh
|
||||
input wire i_user_self_refresh,
|
||||
output wire uart_tx
|
||||
);
|
||||
|
||||
// Instantiation Template (DEFAULT VALUE IS FOR ARTY S7)
|
||||
|
|
@ -326,7 +327,8 @@ ddr3_top #(
|
|||
// .o_debug2(o_debug2),
|
||||
// .o_debug3(o_debug3)
|
||||
// User enabled self-refresh
|
||||
.i_user_self_refresh(user_self_refresh)
|
||||
.i_user_self_refresh(user_self_refresh),
|
||||
.uart_tx(uart_tx)
|
||||
);
|
||||
|
||||
ddr3_phy #(
|
||||
|
|
|
|||
|
|
@ -48,22 +48,23 @@ module ddr3_dimm_micron_sim;
|
|||
|
||||
`ifdef TWO_LANES_x8
|
||||
localparam BYTE_LANES = 2,
|
||||
ODELAY_SUPPORTED = 1;
|
||||
ODELAY_SUPPORTED = 0;
|
||||
`endif
|
||||
|
||||
`ifdef EIGHT_LANES_x8
|
||||
localparam BYTE_LANES = 8,
|
||||
ODELAY_SUPPORTED = 1;
|
||||
ODELAY_SUPPORTED = 0;
|
||||
`endif
|
||||
|
||||
|
||||
localparam CONTROLLER_CLK_PERIOD = 12_000, //ps, period of clock input to this DDR3 controller module
|
||||
DDR3_CLK_PERIOD = 3_000, //ps, period of clock input to DDR3 RAM device
|
||||
localparam CONTROLLER_CLK_PERIOD = 5_000, //ps, period of clock input to this DDR3 controller module
|
||||
DDR3_CLK_PERIOD = 1_250, //ps, period of clock input to DDR3 RAM device
|
||||
AUX_WIDTH = 16, // AUX lines
|
||||
ECC_ENABLE = 0, // ECC enable
|
||||
SELF_REFRESH = 2'b00,
|
||||
DUAL_RANK_DIMM = 0,
|
||||
TEST_SELF_REFRESH = 0,
|
||||
SECOND_WISHBONE = 0,
|
||||
BIST_MODE = 1; // 0 = No BIST, 1 = run through all address space ONCE , 2 = run through all address space for every test (burst w/r, random w/r, alternating r/w)
|
||||
|
||||
|
||||
|
|
@ -165,7 +166,7 @@ ddr3_top #(
|
|||
.AUX_WIDTH(AUX_WIDTH), //width of aux line (must be >= 4)
|
||||
.MICRON_SIM(1), //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW)
|
||||
.ODELAY_SUPPORTED(ODELAY_SUPPORTED), //set to 1 if ODELAYE2 is supported
|
||||
.SECOND_WISHBONE(0), //set to 1 if 2nd wishbone for debugging is needed
|
||||
.SECOND_WISHBONE(SECOND_WISHBONE), //set to 1 if 2nd wishbone for debugging is needed
|
||||
.ECC_ENABLE(ECC_ENABLE), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC )
|
||||
.WB_ERROR(1), // set to 1 to support Wishbone error (asserts at ECC double bit error)
|
||||
.BIST_MODE(BIST_MODE), // 0 = No BIST, 1 = run through all address space ONCE , 2 = run through all address space for every test (burst w/r, random w/r, alternating r/w)
|
||||
|
|
@ -678,60 +679,62 @@ ddr3_top #(
|
|||
|
||||
// Test 3: Read from wishbone 2 (PHY)
|
||||
// Wishbone 2
|
||||
i_wb2_cyc <= 0; //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
|
||||
i_wb2_stb <= 0; //request a transfer
|
||||
i_wb2_we <= 0; //write-enable (1 = write, 0 = read)
|
||||
i_wb2_addr <= 0; //memory-mapped register to be accessed
|
||||
i_wb2_data <= 0; //write data
|
||||
i_wb2_sel <= 0;
|
||||
address <= 0;
|
||||
address_inner <= 0;
|
||||
#1; //just to make sure the non-blocking are assignments are all over
|
||||
while(address < 9 ) begin
|
||||
if(address <= 3) begin
|
||||
while(address_inner < 7) begin
|
||||
if(SECOND_WISHBONE) begin
|
||||
i_wb2_cyc <= 0; //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled)
|
||||
i_wb2_stb <= 0; //request a transfer
|
||||
i_wb2_we <= 0; //write-enable (1 = write, 0 = read)
|
||||
i_wb2_addr <= 0; //memory-mapped register to be accessed
|
||||
i_wb2_data <= 0; //write data
|
||||
i_wb2_sel <= 0;
|
||||
address <= 0;
|
||||
address_inner <= 0;
|
||||
#1; //just to make sure the non-blocking are assignments are all over
|
||||
while(address < 9 ) begin
|
||||
if(address <= 3) begin
|
||||
while(address_inner < 7) begin
|
||||
@(posedge i_controller_clk) begin
|
||||
if(!i_wb2_stb || !o_wb2_stall) begin
|
||||
i_wb2_cyc <= 1;
|
||||
i_wb2_stb <= 1; //0,1,2,3,4,5,6,7,8
|
||||
i_wb2_we <= 0;
|
||||
i_wb2_addr <= address | address_inner << 4;
|
||||
address_inner <= address_inner + 1;
|
||||
end
|
||||
end
|
||||
#1;
|
||||
end //end of while
|
||||
|
||||
@(posedge i_controller_clk) begin
|
||||
if(!i_wb2_stb || !o_wb2_stall) begin
|
||||
i_wb2_cyc <= 1;
|
||||
i_wb2_stb <= 1; //0,1,2,3,4,5,6,7,8
|
||||
i_wb2_we <= 0;
|
||||
i_wb2_addr <= address | address_inner << 4;
|
||||
address_inner <= address_inner + 1;
|
||||
address <= address + 1;
|
||||
address_inner <= 0;
|
||||
end
|
||||
end //end of @posedge
|
||||
end //end of if(address <= 3)
|
||||
|
||||
else begin
|
||||
@(posedge i_controller_clk) begin
|
||||
if(!i_wb2_stb || !o_wb2_stall) begin
|
||||
i_wb2_cyc <= 1;
|
||||
i_wb2_stb <= 1;
|
||||
i_wb2_we <= 0;
|
||||
i_wb2_addr <= address;
|
||||
address <= address + 1;
|
||||
end
|
||||
end
|
||||
#1;
|
||||
end //end of while
|
||||
|
||||
@(posedge i_controller_clk) begin
|
||||
if(!i_wb2_stb || !o_wb2_stall) begin
|
||||
i_wb2_cyc <= 1;
|
||||
i_wb2_stb <= 1; //0,1,2,3,4,5,6,7,8
|
||||
i_wb2_we <= 0;
|
||||
i_wb2_addr <= address | address_inner << 4;
|
||||
address <= address + 1;
|
||||
address_inner <= 0;
|
||||
end
|
||||
end //end of @posedge
|
||||
end //end of if(address <= 3)
|
||||
|
||||
else begin
|
||||
@(posedge i_controller_clk) begin
|
||||
if(!i_wb2_stb || !o_wb2_stall) begin
|
||||
i_wb2_cyc <= 1;
|
||||
i_wb2_stb <= 1;
|
||||
i_wb2_we <= 0;
|
||||
i_wb2_addr <= address;
|
||||
address <= address + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#1; //just to make sure the non-blocking are assignments are all over
|
||||
end
|
||||
while(i_wb2_stb) begin
|
||||
@(posedge i_controller_clk) begin
|
||||
if (!o_wb2_stall) i_wb2_stb <= 1'b0;
|
||||
end
|
||||
#1; //just to make sure the non-blocking are assignments are all over
|
||||
end
|
||||
while(i_wb2_stb) begin
|
||||
@(posedge i_controller_clk) begin
|
||||
if (!o_wb2_stall) i_wb2_stb <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#1000_000; //rest here
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// Define either TWO_LANES_x8 or EIGHT_LANES_x8
|
||||
//`define TWO_LANES_x8
|
||||
`define EIGHT_LANES_x8
|
||||
`define TWO_LANES_x8
|
||||
//`define EIGHT_LANES_x8
|
||||
|
||||
`ifdef EIGHT_LANES_x8
|
||||
`ifdef TWO_LANES_x8
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue