Commit 58af885a authored by Federico Vaga's avatar Federico Vaga

Merge remote-tracking branch 'origin/develop' into develop

parents acb1c27d b00a1ee8
......@@ -2,6 +2,18 @@
Change Log
==========
[1.4.7] 2020-01-15
============
Added
-----
- [hdl] Add support for DDR5 bank to SVEC base
Fixed
-----
- [hdl] DDR constraints
- [hdl] DDR controller generic values are now properly capitalised
- [sw] Update svec-flasher to work with new type of flash memory used in newer SVEC boards
[1.4.6] 2019-12-16
==================
Changed
......
......@@ -35,7 +35,12 @@
@setchapternewpage off
@set update-month November 2014
@tex
\global\def\linkcolor{0.5 0.09 0.12}
\global\def\urlcolor{0.5 0.09 0.12}
@end tex
@set update-month January 2020
@include git_revision.in
@finalout
......@@ -52,7 +57,6 @@
@end iftex
@c ##########################################################################
@node Top
@chapter Introduction
This document describes the default bitstreams that come preloaded with every SVEC card. As there are two FPGAs on the SVEC, there are two default bitstreams:
......@@ -114,14 +118,14 @@ Programming the Application FPGA directly via VME involves the following steps:
@item Exit bootloader mode by writing 1 to @code{CSR.EXIT} bit.
@end itemize
A code example is available in the repository (@pxref{repo_link,,2}). Successful gateware download to the Application FPGA is indicated by turning on the ``AFPGA DONE'' LED in the middle of the PCB.
A code example is available in the repository (@pxref{repo_link,,3}). Successful gateware download to the Application FPGA is indicated by turning on the ``AFPGA DONE'' LED in the middle of the PCB.
@section Programming the Flash
The SFPGA also allows raw access to the Flash memory (M25P128) via the @code{FAR} register. The code below shows how to execute a single SPI transaction (command + N data bytes).
The SFPGA also allows raw access to the Flash memory (M25P128 or MT25QL128 in newer SVEC cards) via the @code{FAR} register. The code below shows how to execute a single SPI transaction (command + N data bytes).
Low-level details about programming M25Pxxx series Flash memories can be found in their datasheets (@pxref{m25p_datasheet,,1}). A simple VME flasher is provided in @code{software/vme-flasher} directory.
Low-level details about programming the Flash memories can be found in their datasheets (@pxref{m25p_datasheet,,1} and @pxref{mt25_datasheet,,2}). A simple VME flasher is provided in @code{software/vme-flasher} directory.
@b{Note 1:} It is advised to protect the region of the flash containing the system FPGA bitstream from being accidentally overwritten, as this will result in rendering the card unusable and will require re-programming the flash via JTAG. Details on memory protection can be found in the M25P series datasheet.
@b{Note 1:} It is advised to protect the region of the flash containing the system FPGA bitstream from being accidentally overwritten, as this will result in rendering the card unusable and will require re-programming the flash via JTAG. Details on memory protection can be found in the Flash memory datasheet.
@b{Note 2:} The freshly-programmed bitstreams will be loaded into the FPGAs after power-cycling the card. In order to avoid the power cycle, one can boot the Application FPGA directly using the same bitstream.
......@@ -134,7 +138,7 @@ The flash memory of the SVEC contains 16 Megabytes of data, that is 65536 pages
@item @code{0x601000 - 0xffffff}: Free space, foreseen for the AFPGA's private data storage.
@end itemize
An example script for building the default flash filesystem (containg the bootloader and golden bitstreams) is located in the @code{software/sdb-flash} subdirectory in the SVEC project's repository(@pxref{repo_link,,2}). Presence of the SDB descriptor table at @code{0x600000} is checked by the bootloader to prevent booting up from a corrupted or unprogrammed flash.
An example script for building the default flash filesystem (containg the bootloader and golden bitstreams) is located in the @code{software/sdb-flash} subdirectory in the SVEC project's repository(@pxref{repo_link,,3}). Presence of the SDB descriptor table at @code{0x600000} is checked by the bootloader to prevent booting up from a corrupted or unprogrammed flash.
@b{Note:} Both bitstreams must be in raw (@code{.bin} file extension) format. @code{.bit}, @code{.mcs}, @code{.xsvf} and other formats will not work.
......@@ -240,7 +244,7 @@ Certain older SVEC cards have been shipped with the first version of the bootloa
@item Open the right-click menu in the main work area and select ``Initialize chain'' or press Ctrl+I.
@item Right click on the ``SPI/BPI ?'' box above the ``xc6slx9'' FPGA and select ``Add SPI/BPI Flash''.
@item Pick the @code{svec-bootloader-[latest release].mcs} file.
@item Select flash type: SPI PROM, M25P128, data width: 1.
@item Select flash type: SPI PROM, M25P128 (or N25Q128 if you have a newer SVEC with a MT25QL128 Flash memory chip), data width: 1.
@item Right click on the ``FLASH'' chip above the ``xc6slx9'' and select ``Program''. Select the ``Verify'' option and click OK.
@item If everything went fine, ``Programming succeeded'' message will appear.
@item Reboot the VME crate to use the new bootloader.
......@@ -307,6 +311,8 @@ NET "flash_miso_i" IOSTANDARD = "LVCMOS33";
@enumerate
@anchor{m25p_datasheet}
@item @uref{http://www.micron.com/parts/nor-flash/serial-nor-flash/m25p128-vme6gb} - M25P series SPI Flash memory datasheet
@anchor{mt25_datasheet}
@item @uref{https://www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/mt25q/die-rev-a/mt25q_qlhs_l_128_aba_0.pdf} - MT25QL128ABA series SPI Flash memory datasheet
@anchor{repo_link}
@item @uref{http://www.ohwr.org/projects/svec/repository/} - Git repository containing this document's sources and revision history (@code{doc} subdirectory) and bootloading code examples (@code{software/sveclib} subdirectory).
@end enumerate
......
Subproject commit 5dde6da558083312cfd98d721e14b36a03e2a0bc
Subproject commit 75d51c0b92015b48b176374f9a387b2d25fa8198
......@@ -85,10 +85,29 @@ memory-map:
write-strobe: True
read-ack: True
write-ack: True
- reg:
name: ddr5_addr
description: address of data to read or to write
access: rw
width: 32
x-hdl:
type: wire
write-strobe: True
- reg:
name: ddr5_data
description: data to read or to write in ddr5
access: rw
width: 32
x-hdl:
type: wire
read-strobe: True
write-strobe: True
read-ack: True
write-ack: True
- submap:
name: therm_id
description: Thermometer and unique id
address: 0x70
address: 0x80
size: 0x10
interface: wb-32-be
x-hdl:
......@@ -96,7 +115,7 @@ memory-map:
- submap:
name: fmc_i2c
description: i2c controllers to the fmcs
address: 0x80
address: 0xa0
size: 0x20
interface: wb-32-be
x-hdl:
......@@ -104,7 +123,7 @@ memory-map:
- submap:
name: flash_spi
description: spi controller to the flash
address: 0xa0
address: 0xc0
size: 0x20
interface: wb-32-be
x-hdl:
......
......@@ -56,6 +56,19 @@ entity svec_base_regs is
csr_ddr4_data_wack_i : in std_logic;
csr_ddr4_data_rack_i : in std_logic;
-- address of data to read or to write
csr_ddr5_addr_i : in std_logic_vector(31 downto 0);
csr_ddr5_addr_o : out std_logic_vector(31 downto 0);
csr_ddr5_addr_wr_o : out std_logic;
-- data to read or to write in ddr5
csr_ddr5_data_i : in std_logic_vector(31 downto 0);
csr_ddr5_data_o : out std_logic_vector(31 downto 0);
csr_ddr5_data_wr_o : out std_logic;
csr_ddr5_data_rd_o : out std_logic;
csr_ddr5_data_wack_i : in std_logic;
csr_ddr5_data_rack_i : in std_logic;
-- Thermometer and unique id
therm_id_i : in t_wishbone_master_in;
therm_id_o : out t_wishbone_master_out;
......@@ -85,8 +98,8 @@ entity svec_base_regs is
end svec_base_regs;
architecture syn of svec_base_regs is
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_int : std_logic;
signal wr_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
......@@ -97,37 +110,25 @@ architecture syn of svec_base_regs is
signal metadata_re : std_logic;
signal csr_resets_global_reg : std_logic;
signal csr_resets_appl_reg : std_logic;
signal csr_resets_wreq : std_logic;
signal csr_resets_wack : std_logic;
signal csr_resets_rint : std_logic_vector(31 downto 0);
signal csr_unused0_rint : std_logic_vector(31 downto 0);
signal csr_ddr_status_rint : std_logic_vector(31 downto 0);
signal csr_pcb_rev_rint : std_logic_vector(31 downto 0);
signal csr_ddr4_addr_wreq : std_logic;
signal csr_ddr4_data_wreq : std_logic;
signal therm_id_re : std_logic;
signal therm_id_we : std_logic;
signal therm_id_wt : std_logic;
signal therm_id_rt : std_logic;
signal therm_id_tr : std_logic;
signal therm_id_wack : std_logic;
signal therm_id_rack : std_logic;
signal fmc_i2c_re : std_logic;
signal fmc_i2c_we : std_logic;
signal fmc_i2c_wt : std_logic;
signal fmc_i2c_rt : std_logic;
signal fmc_i2c_tr : std_logic;
signal fmc_i2c_wack : std_logic;
signal fmc_i2c_rack : std_logic;
signal flash_spi_re : std_logic;
signal flash_spi_we : std_logic;
signal flash_spi_wt : std_logic;
signal flash_spi_rt : std_logic;
signal flash_spi_tr : std_logic;
signal flash_spi_wack : std_logic;
signal flash_spi_rack : std_logic;
signal vic_re : std_logic;
signal vic_we : std_logic;
signal vic_wt : std_logic;
signal vic_rt : std_logic;
signal vic_tr : std_logic;
......@@ -136,17 +137,13 @@ architecture syn of svec_base_regs is
signal buildinfo_rack : std_logic;
signal buildinfo_re : std_logic;
signal wrc_regs_re : std_logic;
signal wrc_regs_we : std_logic;
signal wrc_regs_wt : std_logic;
signal wrc_regs_rt : std_logic;
signal wrc_regs_tr : std_logic;
signal wrc_regs_wack : std_logic;
signal wrc_regs_rack : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_adr_d0 : std_logic_vector(12 downto 2);
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal reg_rdat_int : std_logic_vector(31 downto 0);
signal rd_ack1_int : std_logic;
begin
-- WB decode signals
......@@ -161,7 +158,7 @@ begin
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_we_i) and not wb_rip;
rd_int <= (wb_en and not wb_we_i) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
......@@ -172,7 +169,7 @@ begin
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_we_i) and not wb_wip;
wr_int <= (wb_en and wb_we_i) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_ack_o <= ack_int;
......@@ -180,21 +177,7 @@ begin
wb_rty_o <= '0';
wb_err_o <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_dat_o <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_adr_d0 <= wb_adr_i;
wr_dat_d0 <= wb_dat_i;
end if;
end if;
end process;
-- Assign outputs
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
......@@ -204,54 +187,10 @@ begin
end if;
end if;
end process;
metadata_data_o <= wr_dat_d0;
metadata_addr_o <= wr_adr_d0(5 downto 2);
-- Register csr_app_offset
-- Register csr_resets
metadata_data_o <= wb_dat_i;
metadata_addr_o <= wb_adr_i(5 downto 2);
csr_resets_global_o <= csr_resets_global_reg;
csr_resets_appl_o <= csr_resets_appl_reg;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
csr_resets_global_reg <= '0';
csr_resets_appl_reg <= '0';
csr_resets_wack <= '0';
else
if csr_resets_wreq = '1' then
csr_resets_global_reg <= wr_dat_d0(0);
csr_resets_appl_reg <= wr_dat_d0(1);
end if;
csr_resets_wack <= csr_resets_wreq;
end if;
end if;
end process;
csr_resets_rint(0) <= csr_resets_global_reg;
csr_resets_rint(1) <= csr_resets_appl_reg;
csr_resets_rint(31 downto 2) <= (others => '0');
-- Register csr_fmc_presence
-- Register csr_unused0
csr_unused0_rint(31 downto 0) <= "00000000000000000000000000000000";
-- Register csr_ddr_status
csr_ddr_status_rint(0) <= csr_ddr_status_ddr4_calib_done_i;
csr_ddr_status_rint(1) <= csr_ddr_status_ddr5_calib_done_i;
csr_ddr_status_rint(31 downto 2) <= (others => '0');
-- Register csr_pcb_rev
csr_pcb_rev_rint(4 downto 0) <= csr_pcb_rev_rev_i;
csr_pcb_rev_rint(31 downto 5) <= (others => '0');
-- Register csr_ddr4_addr
csr_ddr4_addr_o <= wr_dat_d0;
csr_ddr4_addr_wr_o <= csr_ddr4_addr_wreq;
-- Register csr_ddr4_data
csr_ddr4_data_o <= wr_dat_d0;
csr_ddr4_data_wr_o <= csr_ddr4_data_wreq;
-- Assignments for submap therm_id
therm_id_tr <= therm_id_wt or therm_id_rt;
......@@ -259,10 +198,8 @@ begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
therm_id_rt <= '0';
therm_id_wt <= '0';
else
therm_id_rt <= (therm_id_rt or therm_id_re) and not therm_id_rack;
therm_id_wt <= (therm_id_wt or therm_id_we) and not therm_id_wack;
end if;
end if;
end process;
......@@ -273,7 +210,7 @@ begin
therm_id_o.adr <= ((27 downto 0 => '0') & wb_adr_i(3 downto 2)) & (1 downto 0 => '0');
therm_id_o.sel <= (others => '1');
therm_id_o.we <= therm_id_wt;
therm_id_o.dat <= wr_dat_d0;
therm_id_o.dat <= wb_dat_i;
-- Assignments for submap fmc_i2c
fmc_i2c_tr <= fmc_i2c_wt or fmc_i2c_rt;
......@@ -281,10 +218,8 @@ begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
fmc_i2c_rt <= '0';
fmc_i2c_wt <= '0';
else
fmc_i2c_rt <= (fmc_i2c_rt or fmc_i2c_re) and not fmc_i2c_rack;
fmc_i2c_wt <= (fmc_i2c_wt or fmc_i2c_we) and not fmc_i2c_wack;
end if;
end if;
end process;
......@@ -295,7 +230,7 @@ begin
fmc_i2c_o.adr <= ((26 downto 0 => '0') & wb_adr_i(4 downto 2)) & (1 downto 0 => '0');
fmc_i2c_o.sel <= (others => '1');
fmc_i2c_o.we <= fmc_i2c_wt;
fmc_i2c_o.dat <= wr_dat_d0;
fmc_i2c_o.dat <= wb_dat_i;
-- Assignments for submap flash_spi
flash_spi_tr <= flash_spi_wt or flash_spi_rt;
......@@ -303,10 +238,8 @@ begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
flash_spi_rt <= '0';
flash_spi_wt <= '0';
else
flash_spi_rt <= (flash_spi_rt or flash_spi_re) and not flash_spi_rack;
flash_spi_wt <= (flash_spi_wt or flash_spi_we) and not flash_spi_wack;
end if;
end if;
end process;
......@@ -317,7 +250,7 @@ begin
flash_spi_o.adr <= ((26 downto 0 => '0') & wb_adr_i(4 downto 2)) & (1 downto 0 => '0');
flash_spi_o.sel <= (others => '1');
flash_spi_o.we <= flash_spi_wt;
flash_spi_o.dat <= wr_dat_d0;
flash_spi_o.dat <= wb_dat_i;
-- Assignments for submap vic
vic_tr <= vic_wt or vic_rt;
......@@ -325,10 +258,8 @@ begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
vic_rt <= '0';
vic_wt <= '0';
else
vic_rt <= (vic_rt or vic_re) and not vic_rack;
vic_wt <= (vic_wt or vic_we) and not vic_wack;
end if;
end if;
end process;
......@@ -339,7 +270,7 @@ begin
vic_o.adr <= ((23 downto 0 => '0') & wb_adr_i(7 downto 2)) & (1 downto 0 => '0');
vic_o.sel <= (others => '1');
vic_o.we <= vic_wt;
vic_o.dat <= wr_dat_d0;
vic_o.dat <= wb_dat_i;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
......@@ -349,8 +280,8 @@ begin
end if;
end if;
end process;
buildinfo_data_o <= wr_dat_d0;
buildinfo_addr_o <= wr_adr_d0(7 downto 2);
buildinfo_data_o <= wb_dat_i;
buildinfo_addr_o <= wb_adr_i(7 downto 2);
-- Assignments for submap wrc_regs
wrc_regs_tr <= wrc_regs_wt or wrc_regs_rt;
......@@ -358,10 +289,8 @@ begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wrc_regs_rt <= '0';
wrc_regs_wt <= '0';
else
wrc_regs_rt <= (wrc_regs_rt or wrc_regs_re) and not wrc_regs_rack;
wrc_regs_wt <= (wrc_regs_wt or wrc_regs_we) and not wrc_regs_wack;
end if;
end if;
end process;
......@@ -372,117 +301,240 @@ begin
wrc_regs_o.adr <= ((19 downto 0 => '0') & wb_adr_i(11 downto 2)) & (1 downto 0 => '0');
wrc_regs_o.sel <= (others => '1');
wrc_regs_o.we <= wrc_regs_wt;
wrc_regs_o.dat <= wr_dat_d0;
wrc_regs_o.dat <= wb_dat_i;
-- Process for write requests.
process (wr_adr_d0, wr_req_d0, csr_resets_wack, csr_ddr4_data_wack_i, therm_id_wack, fmc_i2c_wack, flash_spi_wack, vic_wack, wrc_regs_wack) begin
metadata_wr_o <= '0';
csr_resets_wreq <= '0';
csr_ddr4_addr_wreq <= '0';
csr_ddr4_data_wreq <= '0';
therm_id_we <= '0';
fmc_i2c_we <= '0';
flash_spi_we <= '0';
vic_we <= '0';
buildinfo_wr_o <= '0';
wrc_regs_we <= '0';
case wr_adr_d0(12 downto 12) is
when "0" =>
case wr_adr_d0(11 downto 8) is
when "0000" =>
case wr_adr_d0(7 downto 6) is
when "00" =>
-- Submap metadata
metadata_wr_o <= wr_req_d0;
wr_ack_int <= wr_req_d0;
when "01" =>
case wr_adr_d0(5 downto 4) is
when "00" =>
case wr_adr_d0(3 downto 2) is
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wr_ack_int <= '0';
metadata_wr_o <= '0';
csr_resets_global_reg <= '0';
csr_resets_appl_reg <= '0';
csr_ddr4_addr_wr_o <= '0';
csr_ddr4_data_wr_o <= '0';
csr_ddr5_addr_wr_o <= '0';
csr_ddr5_data_wr_o <= '0';
therm_id_wt <= '0';
fmc_i2c_wt <= '0';
flash_spi_wt <= '0';
vic_wt <= '0';
buildinfo_wr_o <= '0';
wrc_regs_wt <= '0';
else
wr_ack_int <= '0';
metadata_wr_o <= '0';
csr_ddr4_addr_wr_o <= '0';
csr_ddr4_data_wr_o <= '0';
csr_ddr5_addr_wr_o <= '0';
csr_ddr5_data_wr_o <= '0';
therm_id_wt <= '0';
fmc_i2c_wt <= '0';
flash_spi_wt <= '0';
vic_wt <= '0';
buildinfo_wr_o <= '0';
wrc_regs_wt <= '0';
case wb_adr_i(12 downto 12) is
when "0" =>
case wb_adr_i(11 downto 8) is
when "0000" =>
case wb_adr_i(7 downto 6) is
when "00" =>
-- csr_app_offset
wr_ack_int <= wr_req_d0;
-- Submap metadata
metadata_wr_o <= wr_int;
wr_ack_int <= wr_int;
when "01" =>
-- csr_resets
csr_resets_wreq <= wr_req_d0;
wr_ack_int <= csr_resets_wack;
case wb_adr_i(5 downto 2) is
when "0000" =>
-- Register csr_app_offset
when "0001" =>
-- Register csr_resets
if wr_int = '1' then
csr_resets_global_reg <= wb_dat_i(0);
csr_resets_appl_reg <= wb_dat_i(1);
end if;
wr_ack_int <= wr_int;
when "0010" =>
-- Register csr_fmc_presence
when "0011" =>
-- Register csr_unused0
when "0100" =>
-- Register csr_ddr_status
when "0101" =>
-- Register csr_pcb_rev
when "0110" =>
-- Register csr_ddr4_addr
csr_ddr4_addr_wr_o <= wr_int;
if wr_int = '1' then
csr_ddr4_addr_o <= wb_dat_i;
end if;
wr_ack_int <= wr_int;
when "0111" =>
-- Register csr_ddr4_data
csr_ddr4_data_wr_o <= wr_int;
if wr_int = '1' then
csr_ddr4_data_o <= wb_dat_i;
end if;
wr_ack_int <= csr_ddr4_data_wack_i;
when "1000" =>
-- Register csr_ddr5_addr
csr_ddr5_addr_wr_o <= wr_int;
if wr_int = '1' then
csr_ddr5_addr_o <= wb_dat_i;
end if;
wr_ack_int <= wr_int;
when "1001" =>
-- Register csr_ddr5_data
csr_ddr5_data_wr_o <= wr_int;
if wr_int = '1' then
csr_ddr5_data_o <= wb_dat_i;
end if;
wr_ack_int <= csr_ddr5_data_wack_i;
when others =>
wr_ack_int <= wr_int;
end case;
when "10" =>
-- csr_fmc_presence
wr_ack_int <= wr_req_d0;
case wb_adr_i(5 downto 5) is
when "0" =>
-- Submap therm_id
therm_id_wt <= (therm_id_wt or wr_int) and not therm_id_wack;
wr_ack_int <= therm_id_wack;
when "1" =>
-- Submap fmc_i2c
fmc_i2c_wt <= (fmc_i2c_wt or wr_int) and not fmc_i2c_wack;
wr_ack_int <= fmc_i2c_wack;
when others =>
wr_ack_int <= wr_int;
end case;
when "11" =>
-- csr_unused0
wr_ack_int <= wr_req_d0;
-- Submap flash_spi
flash_spi_wt <= (flash_spi_wt or wr_int) and not flash_spi_wack;
wr_ack_int <= flash_spi_wack;
when others =>
wr_ack_int <= wr_req_d0;
wr_ack_int <= wr_int;
end case;
when "01" =>
case wr_adr_d0(3 downto 2) is
when "0001" =>
-- Submap vic
vic_wt <= (vic_wt or wr_int) and not vic_wack;
wr_ack_int <= vic_wack;
when "0010" =>
-- Submap buildinfo
buildinfo_wr_o <= wr_int;
wr_ack_int <= wr_int;
when others =>
wr_ack_int <= wr_int;
end case;
when "1" =>
-- Submap wrc_regs
wrc_regs_wt <= (wrc_regs_wt or wr_int) and not wrc_regs_wack;
wr_ack_int <= wrc_regs_wack;
when others =>
wr_ack_int <= wr_int;
end case;
end if;
end if;
end process;
-- Process for registers read.
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack1_int <= '0';
csr_ddr4_data_rd_o <= '0';
csr_ddr5_data_rd_o <= '0';
else
csr_ddr5_data_rd_o <= '0';
csr_ddr4_data_rd_o <= '0';
reg_rdat_int <= (others => '0');
case wb_adr_i(12 downto 12) is
when "0" =>
case wb_adr_i(11 downto 8) is
when "0000" =>
case wb_adr_i(7 downto 6) is
when "00" =>
-- csr_ddr_status
wr_ack_int <= wr_req_d0;
when "01" =>
-- csr_pcb_rev
wr_ack_int <= wr_req_d0;
case wb_adr_i(5 downto 2) is
when "0000" =>
-- csr_app_offset
reg_rdat_int <= csr_app_offset_i;
rd_ack1_int <= rd_int;
when "0001" =>
-- csr_resets
reg_rdat_int(0) <= csr_resets_global_reg;
reg_rdat_int(1) <= csr_resets_appl_reg;
rd_ack1_int <= rd_int;
when "0010" =>
-- csr_fmc_presence
reg_rdat_int <= csr_fmc_presence_i;
rd_ack1_int <= rd_int;
when "0011" =>
-- csr_unused0
reg_rdat_int <= "00000000000000000000000000000000";
rd_ack1_int <= rd_int;
when "0100" =>
-- csr_ddr_status
reg_rdat_int(0) <= csr_ddr_status_ddr4_calib_done_i;
reg_rdat_int(1) <= csr_ddr_status_ddr5_calib_done_i;
rd_ack1_int <= rd_int;
when "0101" =>
-- csr_pcb_rev
reg_rdat_int(4 downto 0) <= csr_pcb_rev_rev_i;
rd_ack1_int <= rd_int;
when "0110" =>
-- csr_ddr4_addr
reg_rdat_int <= csr_ddr4_addr_i;
rd_ack1_int <= rd_int;
when "0111" =>
-- csr_ddr4_data
reg_rdat_int <= csr_ddr4_data_i;
csr_ddr4_data_rd_o <= rd_int;
rd_ack1_int <= csr_ddr4_data_rack_i;
when "1000" =>
-- csr_ddr5_addr
reg_rdat_int <= csr_ddr5_addr_i;
rd_ack1_int <= rd_int;
when "1001" =>
-- csr_ddr5_data
reg_rdat_int <= csr_ddr5_data_i;
csr_ddr5_data_rd_o <= rd_int;
rd_ack1_int <= csr_ddr5_data_rack_i;
when others =>
reg_rdat_int <= (others => 'X');
rd_ack1_int <= rd_int;
end case;
when "10" =>
-- csr_ddr4_addr
csr_ddr4_addr_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0;
case wb_adr_i(5 downto 5) is
when "0" =>
when "1" =>
when others =>
reg_rdat_int <= (others => 'X');
rd_ack1_int <= rd_int;
end case;
when "11" =>
-- csr_ddr4_data
csr_ddr4_data_wreq <= wr_req_d0;
wr_ack_int <= csr_ddr4_data_wack_i;
when others =>
wr_ack_int <= wr_req_d0;
reg_rdat_int <= (others => 'X');
rd_ack1_int <= rd_int;
end case;
when "11" =>
-- Submap therm_id
therm_id_we <= wr_req_d0;
wr_ack_int <= therm_id_wack;
when others =>
wr_ack_int <= wr_req_d0;
end case;
when "10" =>
case wr_adr_d0(5 downto 5) is
when "0" =>
-- Submap fmc_i2c
fmc_i2c_we <= wr_req_d0;
wr_ack_int <= fmc_i2c_wack;
when "1" =>
-- Submap flash_spi
flash_spi_we <= wr_req_d0;
wr_ack_int <= flash_spi_wack;
when "0001" =>
when "0010" =>
when others =>
wr_ack_int <= wr_req_d0;
reg_rdat_int <= (others => 'X');
rd_ack1_int <= rd_int;
end case;
when "1" =>
when others =>
wr_ack_int <= wr_req_d0;
reg_rdat_int <= (others => 'X');
rd_ack1_int <= rd_int;
end case;
when "0001" =>
-- Submap vic
vic_we <= wr_req_d0;
wr_ack_int <= vic_wack;
when "0010" =>
-- Submap buildinfo
buildinfo_wr_o <= wr_req_d0;
wr_ack_int <= wr_req_d0;
when others =>
wr_ack_int <= wr_req_d0;
end case;
when "1" =>
-- Submap wrc_regs
wrc_regs_we <= wr_req_d0;
wr_ack_int <= wrc_regs_wack;
when others =>
wr_ack_int <= wr_req_d0;
end case;
end if;
end if;
end process;
-- Process for read requests.
process (wb_adr_i, rd_req_int, rd_req_int, metadata_data_i, metadata_rack, csr_app_offset_i, csr_resets_rint, csr_fmc_presence_i, csr_unused0_rint, csr_ddr_status_rint, csr_pcb_rev_rint, csr_ddr4_addr_i, csr_ddr4_data_rack_i, csr_ddr4_data_i, therm_id_i.dat, therm_id_rack, fmc_i2c_i.dat, fmc_i2c_rack, flash_spi_i.dat, flash_spi_rack, vic_i.dat, vic_rack, rd_req_int, buildinfo_data_i, buildinfo_rack, wrc_regs_i.dat, wrc_regs_rack) begin
process (wb_adr_i, reg_rdat_int, rd_ack1_int, rd_int, rd_int, metadata_data_i, metadata_rack, rd_int, therm_id_i.dat, therm_id_rack, therm_id_rt, rd_int, fmc_i2c_i.dat, fmc_i2c_rack, fmc_i2c_rt, rd_int, flash_spi_i.dat, flash_spi_rack, flash_spi_rt, rd_int, vic_i.dat, vic_rack, vic_rt, rd_int, buildinfo_data_i, buildinfo_rack, rd_int, wrc_regs_i.dat, wrc_regs_rack, wrc_regs_rt) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
wb_dat_o <= (others => '0');
metadata_re <= '0';
csr_ddr4_data_rd_o <= '0';
therm_id_re <= '0';
fmc_i2c_re <= '0';
flash_spi_re <= '0';
......@@ -496,100 +548,97 @@ begin
case wb_adr_i(7 downto 6) is
when "00" =>
-- Submap metadata
rd_dat_d0 <= metadata_data_i;
rd_ack_d0 <= metadata_rack;
metadata_re <= rd_req_int;
wb_dat_o <= metadata_data_i;
rd_ack_int <= metadata_rack;
metadata_re <= rd_int;
when "01" =>
case wb_adr_i(5 downto 4) is
when "00" =>
case wb_adr_i(3 downto 2) is
when "00" =>
-- csr_app_offset
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= csr_app_offset_i;
when "01" =>
-- csr_resets
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= csr_resets_rint;
when "10" =>
-- csr_fmc_presence
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= csr_fmc_presence_i;
when "11" =>
-- csr_unused0
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= csr_unused0_rint;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
when "01" =>
case wb_adr_i(3 downto 2) is
when "00" =>
-- csr_ddr_status
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= csr_ddr_status_rint;
when "01" =>
-- csr_pcb_rev
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= csr_pcb_rev_rint;
when "10" =>
-- csr_ddr4_addr
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= csr_ddr4_addr_i;
when "11" =>
-- csr_ddr4_data
csr_ddr4_data_rd_o <= rd_req_int;
rd_ack_d0 <= csr_ddr4_data_rack_i;
rd_dat_d0 <= csr_ddr4_data_i;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
when "11" =>
-- Submap therm_id
therm_id_re <= rd_req_int;
rd_dat_d0 <= therm_id_i.dat;
rd_ack_d0 <= therm_id_rack;
case wb_adr_i(5 downto 2) is
when "0000" =>
-- csr_app_offset
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "0001" =>
-- csr_resets
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "0010" =>
-- csr_fmc_presence
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "0011" =>
-- csr_unused0
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "0100" =>
-- csr_ddr_status
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "0101" =>
-- csr_pcb_rev
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "0110" =>
-- csr_ddr4_addr
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "0111" =>
-- csr_ddr4_data
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "1000" =>
-- csr_ddr5_addr
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when "1001" =>
-- csr_ddr5_data
wb_dat_o <= reg_rdat_int;
rd_ack_int <= rd_ack1_int;
when others =>
rd_ack_d0 <= rd_req_int;
rd_ack_int <= rd_int;
end case;
when "10" =>
case wb_adr_i(5 downto 5) is
when "0" =>
-- Submap fmc_i2c
fmc_i2c_re <= rd_req_int;
rd_dat_d0 <= fmc_i2c_i.dat;
rd_ack_d0 <= fmc_i2c_rack;
-- Submap therm_id
therm_id_re <= rd_int;
wb_dat_o <= therm_id_i.dat;
rd_ack_int <= therm_id_rack;
when "1" =>
-- Submap flash_spi
flash_spi_re <= rd_req_int;
rd_dat_d0 <= flash_spi_i.dat;
rd_ack_d0 <= flash_spi_rack;
-- Submap fmc_i2c
fmc_i2c_re <= rd_int;
wb_dat_o <= fmc_i2c_i.dat;
rd_ack_int <= fmc_i2c_rack;
when others =>
rd_ack_d0 <= rd_req_int;
rd_ack_int <= rd_int;
end case;
when "11" =>
-- Submap flash_spi
flash_spi_re <= rd_int;
wb_dat_o <= flash_spi_i.dat;
rd_ack_int <= flash_spi_rack;
when others =>
rd_ack_d0 <= rd_req_int;
rd_ack_int <= rd_int;
end case;
when "0001" =>
-- Submap vic
vic_re <= rd_req_int;
rd_dat_d0 <= vic_i.dat;
rd_ack_d0 <= vic_rack;
vic_re <= rd_int;
wb_dat_o <= vic_i.dat;
rd_ack_int <= vic_rack;
when "0010" =>
-- Submap buildinfo
rd_dat_d0 <= buildinfo_data_i;
rd_ack_d0 <= buildinfo_rack;
buildinfo_re <= rd_req_int;
wb_dat_o <= buildinfo_data_i;
rd_ack_int <= buildinfo_rack;
buildinfo_re <= rd_int;
when others =>
rd_ack_d0 <= rd_req_int;
rd_ack_int <= rd_int;
end case;
when "1" =>
-- Submap wrc_regs
wrc_regs_re <= rd_req_int;
rd_dat_d0 <= wrc_regs_i.dat;
rd_ack_d0 <= wrc_regs_rack;
wrc_regs_re <= rd_int;
wb_dat_o <= wrc_regs_i.dat;
rd_ack_int <= wrc_regs_rack;
when others =>
rd_ack_d0 <= rd_req_int;
rd_ack_int <= rd_int;
end case;
end process;
end syn;
......@@ -342,6 +342,7 @@ architecture top of svec_base_wr is
signal rst_ddr_333m_n : std_logic := '0';
signal ddr_rst : std_logic := '1';
signal ddr4_status : std_logic_vector(31 downto 0);
signal ddr5_status : std_logic_vector(31 downto 0);
signal ddr4_calib_done : std_logic;
signal ddr5_calib_done : std_logic;
......@@ -358,13 +359,30 @@ architecture top of svec_base_wr is
signal csr_ddr4_data_wack : std_logic;
signal csr_ddr4_data_rack : std_logic;
--
--
signal ddr4_read_ip : std_logic;
signal ddr4_write_ip : std_logic;
signal ddr4_wb_out : t_wishbone_master_out;
signal ddr4_wb_in : t_wishbone_master_in;
-- Address for ddr5.
signal csr_ddr5_addr_out : std_logic_vector(31 downto 0);
signal csr_ddr5_addr_wr : std_logic;
signal csr_ddr5_addr : std_logic_vector(31 downto 0);
-- data to read or to write in ddr5
signal csr_ddr5_data_in : std_logic_vector(31 downto 0);
signal csr_ddr5_data_out : std_logic_vector(31 downto 0);
signal csr_ddr5_data_wr : std_logic;
signal csr_ddr5_data_rd : std_logic;
signal csr_ddr5_data_wack : std_logic;
signal csr_ddr5_data_rack : std_logic;
--
signal ddr5_read_ip : std_logic;
signal ddr5_write_ip : std_logic;
signal ddr5_wb_out : t_wishbone_master_out;
signal ddr5_wb_in : t_wishbone_master_in;
......@@ -380,7 +398,7 @@ architecture top of svec_base_wr is
signal vme_ga : std_logic_vector(5 downto 0);
signal vme_berr_n : std_logic;
signal vme_irq_n : std_logic_vector(7 downto 1);
-- The wishbone bus to the carrier part.
signal carrier_wb_out : t_wishbone_slave_out;
signal carrier_wb_in : t_wishbone_slave_in;
......@@ -567,7 +585,7 @@ begin -- architecture top
csr_ddr4_addr_i => csr_ddr4_addr,
csr_ddr4_addr_o => csr_ddr4_addr_out,
csr_ddr4_addr_wr_o => csr_ddr4_addr_wr,
-- data to read or to write in ddr4
csr_ddr4_data_i => csr_ddr4_data_in,
csr_ddr4_data_o => csr_ddr4_data_out,
......@@ -575,7 +593,19 @@ begin -- architecture top
csr_ddr4_data_rd_o => csr_ddr4_data_rd,
csr_ddr4_data_wack_i => csr_ddr4_data_wack,
csr_ddr4_data_rack_i => csr_ddr4_data_rack,
csr_ddr5_addr_i => csr_ddr5_addr,
csr_ddr5_addr_o => csr_ddr5_addr_out,
csr_ddr5_addr_wr_o => csr_ddr5_addr_wr,
-- data to read or to write in ddr5
csr_ddr5_data_i => csr_ddr5_data_in,
csr_ddr5_data_o => csr_ddr5_data_out,
csr_ddr5_data_wr_o => csr_ddr5_data_wr,
csr_ddr5_data_rd_o => csr_ddr5_data_rd,
csr_ddr5_data_wack_i => csr_ddr5_data_wack,
csr_ddr5_data_rack_i => csr_ddr5_data_rack,
-- Thermometer and unique id
therm_id_i => therm_id_in,
therm_id_o => therm_id_out,
......@@ -1052,8 +1082,8 @@ begin -- architecture top
g_RST_ACT_LOW => 0, -- active high reset (simpler internal logic)
g_BANK_PORT_SELECT => "SVEC_BANK4_64B_32B",
g_MEMCLK_PERIOD => 3000,
g_SIMULATION => boolean'image(g_SIMULATION /= 0),
g_CALIB_SOFT_IP => boolean'image(g_SIMULATION = 0),
g_SIMULATION => to_upper(boolean'image(g_SIMULATION /= 0)),
g_CALIB_SOFT_IP => to_upper(boolean'image(g_SIMULATION = 0)),
g_P0_MASK_SIZE => 8,
g_P0_DATA_PORT_SIZE => 64,
g_P0_BYTE_ADDR_WIDTH => 30,
......@@ -1218,7 +1248,177 @@ begin -- architecture top
ddr4_wb_o.err <= '0';
ddr4_wb_o.rty <= '0';
-- TODO
ddr5_wb_out <= (adr => (others => 'X'), cyc => '0', stb => '0', sel => x"0", we => '0',
dat => (others => 'X'));
-- DDR3 controller
gen_with_ddr5: if g_WITH_DDR5 generate
cmp_ddr_ctrl_bank : entity work.ddr3_ctrl
generic map(
g_RST_ACT_LOW => 0, -- active high reset (simpler internal logic)
g_BANK_PORT_SELECT => "SVEC_BANK5_64B_32B",
g_MEMCLK_PERIOD => 3000,
g_SIMULATION => to_upper(boolean'image(g_SIMULATION /= 0)),
g_CALIB_SOFT_IP => to_upper(boolean'image(g_SIMULATION = 0)),
g_P0_MASK_SIZE => 8,
g_P0_DATA_PORT_SIZE => 64,
g_P0_BYTE_ADDR_WIDTH => 30,
g_P0_ADDR_GRANULARITY => WORD,
g_P1_MASK_SIZE => 4,
g_P1_DATA_PORT_SIZE => 32,
g_P1_BYTE_ADDR_WIDTH => 30,
g_P1_ADDR_GRANULARITY => BYTE)
port map (
clk_i => clk_ddr_333m,
rst_n_i => ddr_rst,
status_o => ddr5_status,
ddr3_dq_b => ddr5_dq_b,
ddr3_a_o => ddr5_a_o,
ddr3_ba_o => ddr5_ba_o(2 downto 0),
ddr3_ras_n_o => ddr5_ras_n_o,
ddr3_cas_n_o => ddr5_cas_n_o,
ddr3_we_n_o => ddr5_we_n_o,
ddr3_odt_o => ddr5_odt_o,
ddr3_rst_n_o => ddr5_reset_n_o,
ddr3_cke_o => ddr5_cke_o,
ddr3_dm_o => ddr5_ldm_o,
ddr3_udm_o => ddr5_udm_o,
ddr3_dqs_p_b => ddr5_ldqs_p_b,
ddr3_dqs_n_b => ddr5_ldqs_n_b,
ddr3_udqs_p_b => ddr5_udqs_p_b,
ddr3_udqs_n_b => ddr5_udqs_n_b,
ddr3_clk_p_o => ddr5_ck_p_o,
ddr3_clk_n_o => ddr5_ck_n_o,
ddr3_rzq_b => ddr5_rzq_b,
wb0_rst_n_i => ddr5_rst_n_i,
wb0_clk_i => ddr5_clk_i,
wb0_sel_i => ddr5_wb_i.sel,
wb0_cyc_i => ddr5_wb_i.cyc,
wb0_stb_i => ddr5_wb_i.stb,
wb0_we_i => ddr5_wb_i.we,
wb0_addr_i => ddr5_wb_i.adr,
wb0_data_i => ddr5_wb_i.dat,
wb0_data_o => ddr5_wb_o.dat,
wb0_ack_o => ddr5_wb_o.ack,
wb0_stall_o => ddr5_wb_o.stall,
p0_cmd_empty_o => open,
p0_cmd_full_o => open,
p0_rd_full_o => open,
p0_rd_empty_o => open,
p0_rd_count_o => open,
p0_rd_overflow_o => open,
p0_rd_error_o => open,
p0_wr_full_o => open,
p0_wr_empty_o => ddr5_wr_fifo_empty_o,
p0_wr_count_o => open,
p0_wr_underrun_o => open,
p0_wr_error_o => open,
wb1_rst_n_i => rst_gbl_n,
wb1_clk_i => clk_sys_62m5,
wb1_sel_i => ddr5_wb_out.sel,
wb1_cyc_i => ddr5_wb_out.cyc,
wb1_stb_i => ddr5_wb_out.stb,
wb1_we_i => ddr5_wb_out.we,
wb1_addr_i => ddr5_wb_out.adr,
wb1_data_i => ddr5_wb_out.dat,
wb1_data_o => ddr5_wb_in.dat,
wb1_ack_o => ddr5_wb_in.ack,
wb1_stall_o => ddr5_wb_in.stall,
p1_cmd_empty_o => open,
p1_cmd_full_o => open,
p1_rd_full_o => open,
p1_rd_empty_o => open,
p1_rd_count_o => open,
p1_rd_overflow_o => open,
p1_rd_error_o => open,
p1_wr_full_o => open,
p1_wr_empty_o => open,
p1_wr_count_o => open,
p1_wr_underrun_o => open,
p1_wr_error_o => open
);
ddr5_calib_done <= ddr5_status(0);
-- unused Wishbone signals
ddr5_wb_in.err <= '0';
ddr5_wb_in.rty <= '0';
p_ddr5_addr: process (clk_sys_62m5)
begin
if rising_edge(clk_sys_62m5) then
if rst_sys_62m5_n = '0' then
csr_ddr5_addr <= x"0000_0000";
elsif csr_ddr5_addr_wr = '1' then
csr_ddr5_addr <= csr_ddr5_addr_out;
elsif ddr5_wb_in.ack = '1' then
csr_ddr5_addr <= std_logic_vector(unsigned(csr_ddr5_addr) + 4);
end if;
end if;
end process;
p_ddr5_ack: process (clk_sys_62m5)
begin
if rising_edge(clk_sys_62m5) then
if rst_sys_62m5_n = '0' then
ddr5_read_ip <= '0';
ddr5_write_ip <= '0';
else
ddr5_read_ip <= csr_ddr5_data_rd or (ddr5_read_ip and not ddr5_wb_in.ack);
ddr5_write_ip <= csr_ddr5_data_wr or (ddr5_write_ip and not ddr5_wb_in.ack);
end if;
end if;
end process;
ddr5_wb_out <= (adr => csr_ddr5_addr,
cyc => csr_ddr5_data_rd or csr_ddr5_data_wr or ddr5_read_ip or ddr5_write_ip,
stb => csr_ddr5_data_rd or csr_ddr5_data_wr,
sel => x"f",
we => csr_ddr5_data_wr,
dat => csr_ddr5_data_out);
csr_ddr5_data_in <= ddr5_wb_in.dat;
csr_ddr5_data_rack <= ddr5_read_ip and ddr5_wb_in.ack;
csr_ddr5_data_wack <= ddr5_write_ip and ddr5_wb_in.ack;
end generate gen_with_ddr5;
gen_without_ddr5 : if not g_WITH_DDR5 generate
ddr5_calib_done <= '0';
ddr5_wb_in <= c_DUMMY_WB_MASTER_IN;
ddr5_a_o <= (others => '0');
ddr5_ba_o <= (others => '0');
ddr5_dq_b <= (others => 'Z');
ddr5_cas_n_o <= '0';
ddr5_ck_p_o <= '0';
ddr5_ck_n_o <= '0';
ddr5_cke_o <= '0';
ddr5_ldm_o <= '0';
ddr5_ldqs_n_b <= 'Z';
ddr5_ldqs_p_b <= 'Z';
ddr5_udqs_n_b <= 'Z';
ddr5_udqs_p_b <= 'Z';
ddr5_odt_o <= '0';
ddr5_udm_o <= '0';
ddr5_ras_n_o <= '0';
ddr5_reset_n_o <= '0';
ddr5_we_n_o <= '0';
ddr5_rzq_b <= 'Z';
ddr5_wb_o.dat <= (others => '0');
ddr5_wb_o.ack <= '1';
ddr5_wb_o.stall <= '0';
ddr5_wr_fifo_empty_o <= '0';
csr_ddr5_addr <= x"0000_0000";
ddr5_wb_out <= (adr => (others => 'X'), cyc => '0', stb => '0', sel => x"0", we => '0',
dat => (others => 'X'));
csr_ddr5_data_in <= x"0000_0000";
csr_ddr5_data_rack <= csr_ddr5_data_wr;
csr_ddr5_data_wack <= csr_ddr5_data_wr;
end generate gen_without_ddr5;
ddr5_wb_o.err <= '0';
ddr5_wb_o.rty <= '0';
end architecture top;
......@@ -14,5 +14,6 @@ for p in svec_base_ucf:
f = ucf_dict.get(p, None)
assert f is not None, "unknown name {} in 'svec_base_ucf'".format(p)
if p == 'ddr4' or p == 'ddr5':
files.append('svec_base_ddr_common.ucf')
if 'svec_base_ddr_common.ucf' not in files:
files.append('svec_base_ddr_common.ucf')
files.append(f)
......@@ -218,10 +218,6 @@ TIMESPEC TS_clk_125m_pllref = PERIOD "clk_125m_ref" 8 ns HIGH 50%;
# Ignore async reset inputs to reset synchronisers
NET "*/gc_reset_async_in" TIG;
# Ignore async reset to DDR controller
NET "inst_svec_base/ddr_rst" TPTHRU = ddr_rst;
TIMESPEC TS_ddr_rst_tig = FROM FFS THRU ddr_rst TIG;
#----------------------------------------
# Cross-clock domain sync
#----------------------------------------
......
......@@ -14,62 +14,62 @@ NET "ddr5_cke_o" LOC = B29;
NET "ddr5_ck_p_o" LOC = E27;
NET "ddr5_ck_n_o" LOC = E28;
NET "ddr5_cas_n_o" LOC = K27;
NET "ddr5_dq_b[15]" LOC = M30;
NET "ddr5_dq_b[14]" LOC = M28;
NET "ddr5_dq_b[13]" LOC = M27;
NET "ddr5_dq_b[12]" LOC = M26;
NET "ddr5_dq_b[11]" LOC = L30;
NET "ddr5_dq_b[10]" LOC = L29;
NET "ddr5_dq_b[9]" LOC = L28;
NET "ddr5_dq_b[8]" LOC = L27;
NET "ddr5_dq_b[7]" LOC = F30;
NET "ddr5_dq_b[6]" LOC = F28;
NET "ddr5_dq_b[5]" LOC = G28;
NET "ddr5_dq_b[4]" LOC = G27;
NET "ddr5_dq_b[3]" LOC = G30;
NET "ddr5_dq_b[2]" LOC = G29;
NET "ddr5_dq_b[1]" LOC = H30;
NET "ddr5_dq_b[0]" LOC = H28;
NET "ddr5_ba_o[2]" LOC = D26;
NET "ddr5_ba_o[1]" LOC = C27;
NET "ddr5_ba_o[0]" LOC = D27;
NET "ddr5_a_o[13]" LOC = A28;
NET "ddr5_a_o[12]" LOC = B30;
NET "ddr5_a_o[11]" LOC = A26;
NET "ddr5_a_o[10]" LOC = F26;
NET "ddr5_a_o[9]" LOC = A27;
NET "ddr5_a_o[8]" LOC = B27;
NET "ddr5_a_o[7]" LOC = C29;
NET "ddr5_a_o[6]" LOC = H27;
NET "ddr5_a_o[5]" LOC = H26;
NET "ddr5_a_o[4]" LOC = F27;
NET "ddr5_a_o[3]" LOC = E29;
NET "ddr5_a_o[2]" LOC = C30;
NET "ddr5_a_o[1]" LOC = D30;
NET "ddr5_a_o[0]" LOC = D28;
NET "ddr5_dq_b[15]" LOC = M30;
NET "ddr5_dq_b[14]" LOC = M28;
NET "ddr5_dq_b[13]" LOC = M27;
NET "ddr5_dq_b[12]" LOC = M26;
NET "ddr5_dq_b[11]" LOC = L30;
NET "ddr5_dq_b[10]" LOC = L29;
NET "ddr5_dq_b[9]" LOC = L28;
NET "ddr5_dq_b[8]" LOC = L27;
NET "ddr5_dq_b[7]" LOC = F30;
NET "ddr5_dq_b[6]" LOC = F28;
NET "ddr5_dq_b[5]" LOC = G28;
NET "ddr5_dq_b[4]" LOC = G27;
NET "ddr5_dq_b[3]" LOC = G30;
NET "ddr5_dq_b[2]" LOC = G29;
NET "ddr5_dq_b[1]" LOC = H30;
NET "ddr5_dq_b[0]" LOC = H28;
NET "ddr5_ba_o[2]" LOC = D26;
NET "ddr5_ba_o[1]" LOC = C27;
NET "ddr5_ba_o[0]" LOC = D27;
NET "ddr5_a_o[13]" LOC = A28;
NET "ddr5_a_o[12]" LOC = B30;
NET "ddr5_a_o[11]" LOC = A26;
NET "ddr5_a_o[10]" LOC = F26;
NET "ddr5_a_o[9]" LOC = A27;
NET "ddr5_a_o[8]" LOC = B27;
NET "ddr5_a_o[7]" LOC = C29;
NET "ddr5_a_o[6]" LOC = H27;
NET "ddr5_a_o[5]" LOC = H26;
NET "ddr5_a_o[4]" LOC = F27;
NET "ddr5_a_o[3]" LOC = E29;
NET "ddr5_a_o[2]" LOC = C30;
NET "ddr5_a_o[1]" LOC = D30;
NET "ddr5_a_o[0]" LOC = D28;
# DDR IO standards and terminations
NET "ddr5_udqs_p_b[*]" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_udqs_n_b[*]" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ldqs_p_b[*]" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ldqs_n_b[*]" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ck_p_o[*]" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ck_n_o[*]" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_rzq_b[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_we_n_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_udm_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_reset_n_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_ras_n_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_odt_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_ldm_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_cke_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_cas_n_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_dq_b[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_ba_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_a_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_udqs_p_b" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_udqs_n_b" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ldqs_p_b" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ldqs_n_b" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ck_p_o" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_ck_n_o" IOSTANDARD = "DIFF_SSTL15_II";
NET "ddr5_rzq_b" IOSTANDARD = "SSTL15_II";
NET "ddr5_we_n_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_udm_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_reset_n_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_ras_n_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_odt_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_ldm_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_cke_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_cas_n_o" IOSTANDARD = "SSTL15_II";
NET "ddr5_dq_b[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_ba_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_a_o[*]" IOSTANDARD = "SSTL15_II";
NET "ddr5_dq_b[*]" IN_TERM = NONE;
NET "ddr5_ldqs_p_b[*]" IN_TERM = NONE;
NET "ddr5_ldqs_n_b[*]" IN_TERM = NONE;
NET "ddr5_udqs_p_b[*]" IN_TERM = NONE;
NET "ddr5_udqs_n_b[*]" IN_TERM = NONE;
NET "ddr5_dq_b[*]" IN_TERM = NONE;
NET "ddr5_ldqs_p_b" IN_TERM = NONE;
NET "ddr5_ldqs_n_b" IN_TERM = NONE;
NET "ddr5_udqs_p_b" IN_TERM = NONE;
NET "ddr5_udqs_n_b" IN_TERM = NONE;
......@@ -7,7 +7,7 @@
NET "inst_svec_base/gen_with_ddr?.cmp_ddr_ctrl_bank/*/c?_pll_lock" TIG;
NET "inst_svec_base/gen_with_ddr?.cmp_ddr_ctrl_bank/*/memc?_mcb_raw_wrapper_inst/selfrefresh_mcb_mode" TIG;
NET "inst_svec_base/gen_with_ddr?.cmp_ddr_ctrl_bank/*/mcb_soft_calibration_inst/DONE_SOFTANDHARD_CAL" TIG;
#NET "inst_svec_base/gen_with_ddr?.cmp_ddr_ctrl_bank/*/mcb_soft_calibration_inst/SELFREFRESH_MCB_REQ" TIG;
NET "inst_svec_base/gen_with_ddr?.cmp_ddr_ctrl_bank/*/mcb_soft_calibration_inst/SELFREFRESH_MCB_REQ" TIG;
#----------------------------------------
# Asynchronous resets
......
......@@ -14,6 +14,7 @@
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <libvmebus.h>
//#include <libsdbfs.h>
......@@ -26,9 +27,11 @@
#define BOOTLOADER_SDB_BASE 0x600000
#define ID_M25P128 0x202018
#define ID_MT25QL128 0x20BA18
#define FLASH_PAGE_SIZE 256
#define FLASH_SECTOR_SIZE 0x40000
#define FLASH_SECTOR_SIZE_M25P128 0x40000
#define FLASH_SECTOR_SIZE_MT25QL128 0x10000
#define FLASH_SIZE 0x1000000
/* M25Pxxx SPI flash commands */
......@@ -228,16 +231,32 @@ void flash_program_page(uint32_t addr, const uint8_t * data, int size)
flash_wait_completion();
}
void flash_program(uint32_t addr, const uint8_t * data, int size)
int flash_program(uint32_t addr, const uint8_t * data, int size, uint32_t flash_id)
{
int n = 0;
int sector_map[FLASH_SIZE / FLASH_SECTOR_SIZE];
int ret = 0;
int sector_size;
int *sector_map;
if (flash_id == ID_M25P128)
sector_size = FLASH_SECTOR_SIZE_M25P128;
else if (flash_id == ID_MT25QL128)
sector_size = FLASH_SECTOR_SIZE_MT25QL128;
else
return -ENODEV;
sector_map = (int *)malloc(sizeof(int) * FLASH_SIZE / sector_size);
if (sector_map == NULL)
return -ENOMEM;
memset(sector_map, 0, sizeof(sector_map));
const uint8_t *p = data;
while (n < size) {
int plen = (size > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE : size);
int sector = ((addr + n) / FLASH_SECTOR_SIZE);
int sector = ((addr + n) / sector_size);
if (!sector_map[sector]) {
flash_write_enable();
......@@ -270,17 +289,20 @@ void flash_program(uint32_t addr, const uint8_t * data, int size)
fprintf(stderr,
"Verification failed at offset 0x%06x (is: 0x%02x, should be: 0x%02x)\n.",
addr + n, d, *p);
spi_cs(0);
exit(-1);
ret = -EINVAL;
goto flash_program_exit;
}
}
flash_program_exit:
spi_cs(0);
free(sector_map);
return ret;
}
int program_flash(char *name, uint8_t *buf, size_t size, int program_boot)
{
int ret = 0;
printf("Programming the Application FPGA flash with bitstream %s.\n",
name);
......@@ -291,11 +313,14 @@ int program_flash(char *name, uint8_t *buf, size_t size, int program_boot)
return -1;
}
if (flash_read_id() != ID_M25P128) {
fprintf(stderr,
"Flash memory ID invalid. You are probably be running an old version\nof the bootloader that doesn't support flash programming via VME.\n");
return -1;
uint32_t flash_id = flash_read_id();
if ((flash_id != ID_M25P128) && (flash_id != ID_MT25QL128)) {
fprintf(stderr, "Flash memory ID invalid (0x%.8x). ", flash_id);
fprintf(stderr, "You are probably running an old version of the bootloader\n");
fprintf(stderr, "that doesn't support flash programming via VME.\n");
return -ENODEV;
}
printf("Flash ID: 0x%.7x, OK\n", flash_id);
if(program_boot)
{
......@@ -310,14 +335,19 @@ int program_flash(char *name, uint8_t *buf, size_t size, int program_boot)
printf("Bootloader update aborted.\n");
return -1;
}
flash_program(0, buf, size);
ret = flash_program(0, buf, size, flash_id);
} else {
flash_program(BOOTLOADER_SDB_BASE, sdb_header, sizeof(sdb_header));
flash_program(BOOTLOADER_BITSTREAM_BASE, buf, size);
printf("Programming OK.\n");
ret = flash_program(BOOTLOADER_SDB_BASE, sdb_header, sizeof(sdb_header), flash_id);
if (ret == 0)
ret = flash_program(BOOTLOADER_BITSTREAM_BASE, buf, size, flash_id);
}
return 0;
if (ret == 0)
printf("Programming OK.\n");
else
printf("Flash programming failed with error %s\n", strerror(ret));
return ret;
}
int program_afpga(char *name, uint8_t *buf, size_t size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment