Merge pull request #26 from AngeloJacobo/openxc7_run

Now tested working on OpenXC7 toolchain
This commit is contained in:
Angelo Jacobo 2025-03-21 20:33:19 +08:00 committed by GitHub
commit a34a5369ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
47 changed files with 321925 additions and 203656 deletions

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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]

View File

@ -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.

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -0,0 +1,66 @@
`timescale 1ps/1ps
module clk_wiz
(
input clk_in1,
output clk_out1,
output clk_out2,
output clk_out3,
output clk_out4,
input reset,
output locked
);
wire clk_out1_clk_wiz_0;
wire clk_out2_clk_wiz_0;
wire clk_out3_clk_wiz_0;
wire clk_out4_clk_wiz_0;
wire clkfbout;
PLLE2_ADV
#(.BANDWIDTH ("OPTIMIZED"),
.COMPENSATION ("INTERNAL"),
.STARTUP_WAIT ("FALSE"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT (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.

View File

@ -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

View File

@ -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}]

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 #(

View File

@ -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

View File

@ -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