Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • project/gn4124-core
1 result
Show changes
Showing
with 865 additions and 304 deletions
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
-- description: GN4124 core top level. Version for spartan6 FPGAs. -- description: GN4124 core top level. Version for spartan6 FPGAs.
-- --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Copyright CERN 2010-2018 -- Copyright CERN 2010-2020
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware -- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except -- License, Version 2.0 (the "License"); you may not use this file except
...@@ -25,8 +25,10 @@ ...@@ -25,8 +25,10 @@
library IEEE; library IEEE;
use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all; use IEEE.NUMERIC_STD.all;
use work.gn4124_core_pkg.all; use work.gn4124_core_pkg.all;
use work.gencores_pkg.all; use work.gencores_pkg.all;
use work.wishbone_pkg.all;
library UNISIM; library UNISIM;
use UNISIM.vcomponents.all; use UNISIM.vcomponents.all;
...@@ -37,10 +39,20 @@ use UNISIM.vcomponents.all; ...@@ -37,10 +39,20 @@ use UNISIM.vcomponents.all;
--============================================================================== --==============================================================================
entity gn4124_core is entity gn4124_core is
generic ( generic (
g_ACK_TIMEOUT : positive := 100 -- Wishbone ACK timeout (in wishbone clock cycles) -- If TRUE, enable the DMA interface
); g_WITH_DMA : boolean := TRUE;
port -- Tunable size and threshold for all async FIFOs.
( -- If not sure, leave the defaults.
g_WBM_TO_WB_FIFO_SIZE : positive := 128;
g_WBM_TO_WB_FIFO_FULL_THRES : positive := 110;
g_WBM_FROM_WB_FIFO_SIZE : positive := 128;
g_WBM_FROM_WB_FIFO_FULL_THRES : positive := 110;
g_P2L_FIFO_SIZE : positive := 64;
g_L2P_FIFO_SIZE : positive := 256;
g_L2P_FIFO_FULL_THRES : positive := 64;
-- Wishbone ACK timeout (in wishbone clock cycles)
g_ACK_TIMEOUT : positive := 100);
port (
--------------------------------------------------------- ---------------------------------------------------------
-- Control and status -- Control and status
rst_n_a_i : in std_logic; -- Asynchronous reset from GN4124 rst_n_a_i : in std_logic; -- Asynchronous reset from GN4124
...@@ -80,7 +92,7 @@ entity gn4124_core is ...@@ -80,7 +92,7 @@ entity gn4124_core is
--------------------------------------------------------- ---------------------------------------------------------
-- Interrupt interface -- Interrupt interface
dma_irq_o : out std_logic_vector(1 downto 0); -- Interrupts sources to IRQ manager dma_irq_o : out std_logic; -- Interrupt source to IRQ manager
irq_p_i : in std_logic; -- Interrupt request pulse from IRQ manager irq_p_i : in std_logic; -- Interrupt request pulse from IRQ manager
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO
...@@ -147,6 +159,7 @@ architecture rtl of gn4124_core is ...@@ -147,6 +159,7 @@ architecture rtl of gn4124_core is
signal io_clk : std_logic; signal io_clk : std_logic;
signal serdes_strobe : std_logic; signal serdes_strobe : std_logic;
signal p2l_pll_locked : std_logic; signal p2l_pll_locked : std_logic;
signal arst_logic_in : std_logic;
attribute keep : string; attribute keep : string;
attribute keep of sys_clk : signal is "TRUE"; attribute keep of sys_clk : signal is "TRUE";
...@@ -164,7 +177,6 @@ architecture rtl of gn4124_core is ...@@ -164,7 +177,6 @@ architecture rtl of gn4124_core is
signal des_pd_data : std_logic_vector(31 downto 0); signal des_pd_data : std_logic_vector(31 downto 0);
-- Local bus control -- Local bus control
signal p_wr_rdy : std_logic;
signal p2l_rdy_wbm : std_logic; signal p2l_rdy_wbm : std_logic;
signal p2l_rdy_pdm : std_logic; signal p2l_rdy_pdm : std_logic;
...@@ -242,6 +254,8 @@ architecture rtl of gn4124_core is ...@@ -242,6 +254,8 @@ architecture rtl of gn4124_core is
signal dma_ctrl_start_l2p : std_logic; signal dma_ctrl_start_l2p : std_logic;
signal dma_ctrl_start_p2l : std_logic; signal dma_ctrl_start_p2l : std_logic;
signal dma_ctrl_start_next : std_logic; signal dma_ctrl_start_next : std_logic;
signal dma_ctrl_direction : std_logic;
signal dma_ctrl_direction_d : std_logic;
signal dma_ctrl_done : std_logic; signal dma_ctrl_done : std_logic;
signal dma_ctrl_error : std_logic; signal dma_ctrl_error : std_logic;
...@@ -261,7 +275,7 @@ architecture rtl of gn4124_core is ...@@ -261,7 +275,7 @@ architecture rtl of gn4124_core is
signal next_item_attrib : std_logic_vector(31 downto 0); signal next_item_attrib : std_logic_vector(31 downto 0);
signal next_item_valid : std_logic; signal next_item_valid : std_logic;
signal dma_irq : std_logic_vector(1 downto 0); signal dma_irq : std_logic;
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- CSR wishbone bus -- CSR wishbone bus
...@@ -271,26 +285,11 @@ architecture rtl of gn4124_core is ...@@ -271,26 +285,11 @@ architecture rtl of gn4124_core is
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DMA wishbone bus -- DMA wishbone bus
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
signal l2p_dma_adr : std_logic_vector(31 downto 0); signal l2p_dma_in : t_wishbone_master_in;
signal l2p_dma_dat_s2m : std_logic_vector(31 downto 0); signal l2p_dma_out : t_wishbone_master_out;
signal l2p_dma_dat_m2s : std_logic_vector(31 downto 0);
signal l2p_dma_sel : std_logic_vector(3 downto 0);
signal l2p_dma_cyc : std_logic;
signal l2p_dma_stb : std_logic;
signal l2p_dma_we : std_logic;
signal l2p_dma_ack : std_logic;
signal l2p_dma_stall : std_logic;
signal p2l_dma_adr : std_logic_vector(31 downto 0);
signal p2l_dma_dat_s2m : std_logic_vector(31 downto 0);
signal p2l_dma_dat_m2s : std_logic_vector(31 downto 0);
signal p2l_dma_sel : std_logic_vector(3 downto 0);
signal p2l_dma_cyc : std_logic;
signal p2l_dma_stb : std_logic;
signal p2l_dma_we : std_logic;
signal p2l_dma_ack : std_logic;
signal p2l_dma_stall : std_logic;
signal p2l_dma_in : t_wishbone_master_in;
signal p2l_dma_out : t_wishbone_master_out;
--============================================================================== --==============================================================================
-- Architecture begin (gn4124_core) -- Architecture begin (gn4124_core)
...@@ -324,18 +323,22 @@ begin ...@@ -324,18 +323,22 @@ begin
bitslip => open, bitslip => open,
reset => arst_pll, reset => arst_pll,
datain => open, datain => open,
rx_bufpll_lckd => p2l_pll_locked) ; rx_bufpll_lckd => p2l_pll_locked);
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Reset aligned to core clock -- Reset aligned to core clock
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
cmp_core_rst_sync: gc_sync_ffs arst_logic_in <= not p2l_pll_locked;
cmp_core_rst_sync : gc_reset_multi_aasd
generic map (
g_CLOCKS => 1,
g_RST_LEN => 16)
port map ( port map (
clk_i => sys_clk, arst_i => arst_logic_in,
rst_n_i => rst_n_a_i, clks_i(0) => sys_clk,
data_i => p2l_pll_locked, rst_n_o(0) => sys_rst_n);
synced_o => sys_rst_n);
-- Always active high reset for PLL and SERDES -- Always active high reset for PLL and SERDES
arst_pll <= not(rst_n_a_i); arst_pll <= not(rst_n_a_i);
...@@ -433,11 +436,13 @@ begin ...@@ -433,11 +436,13 @@ begin
-- Wishbone master -- Wishbone master
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
cmp_wbmaster32 : entity work.wbmaster32 cmp_wbmaster32 : entity work.wbmaster32
generic map( generic map (
g_ACK_TIMEOUT => g_ACK_TIMEOUT g_TO_WB_FIFO_SIZE => g_WBM_TO_WB_FIFO_SIZE,
) g_TO_WB_FIFO_FULL_THRES => g_WBM_TO_WB_FIFO_FULL_THRES,
port map g_FROM_WB_FIFO_SIZE => g_WBM_FROM_WB_FIFO_SIZE,
( g_FROM_WB_FIFO_FULL_THRES => g_WBM_FROM_WB_FIFO_FULL_THRES,
g_ACK_TIMEOUT => g_ACK_TIMEOUT)
port map (
--------------------------------------------------------- ---------------------------------------------------------
-- Clock/Reset -- Clock/Reset
clk_i => sys_clk, clk_i => sys_clk,
...@@ -497,214 +502,234 @@ begin ...@@ -497,214 +502,234 @@ begin
-- Adapt address bus width for top level -- Adapt address bus width for top level
csr_adr_o <= '0' & csr_adr; csr_adr_o <= '0' & csr_adr;
----------------------------------------------------------------------------- gen_with_dma: if g_WITH_DMA generate
-- DMA controller
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
cmp_dma_controller : entity work.dma_controller -- DMA controller
port map -----------------------------------------------------------------------------
( cmp_dma_controller : entity work.dma_controller
clk_i => sys_clk, port map
rst_n_i => sys_rst_n, (
clk_i => sys_clk,
dma_ctrl_irq_o => dma_irq, rst_n_i => sys_rst_n,
dma_ctrl_carrier_addr_o => dma_ctrl_carrier_addr, dma_ctrl_irq_o => dma_irq,
dma_ctrl_host_addr_h_o => dma_ctrl_host_addr_h,
dma_ctrl_host_addr_l_o => dma_ctrl_host_addr_l, dma_ctrl_direction_o => dma_ctrl_direction,
dma_ctrl_len_o => dma_ctrl_len,
dma_ctrl_start_l2p_o => dma_ctrl_start_l2p, dma_ctrl_carrier_addr_o => dma_ctrl_carrier_addr,
dma_ctrl_start_p2l_o => dma_ctrl_start_p2l, dma_ctrl_host_addr_h_o => dma_ctrl_host_addr_h,
dma_ctrl_start_next_o => dma_ctrl_start_next, dma_ctrl_host_addr_l_o => dma_ctrl_host_addr_l,
dma_ctrl_done_i => dma_ctrl_done, dma_ctrl_len_o => dma_ctrl_len,
dma_ctrl_error_i => dma_ctrl_error, dma_ctrl_start_l2p_o => dma_ctrl_start_l2p,
dma_ctrl_byte_swap_o => dma_ctrl_byte_swap, dma_ctrl_start_p2l_o => dma_ctrl_start_p2l,
dma_ctrl_abort_o => dma_ctrl_abort, dma_ctrl_start_next_o => dma_ctrl_start_next,
dma_ctrl_done_i => dma_ctrl_done,
next_item_carrier_addr_i => next_item_carrier_addr, dma_ctrl_error_i => dma_ctrl_error,
next_item_host_addr_h_i => next_item_host_addr_h, dma_ctrl_byte_swap_o => dma_ctrl_byte_swap,
next_item_host_addr_l_i => next_item_host_addr_l, dma_ctrl_abort_o => dma_ctrl_abort,
next_item_len_i => next_item_len,
next_item_next_l_i => next_item_next_l, next_item_carrier_addr_i => next_item_carrier_addr,
next_item_next_h_i => next_item_next_h, next_item_host_addr_h_i => next_item_host_addr_h,
next_item_attrib_i => next_item_attrib, next_item_host_addr_l_i => next_item_host_addr_l,
next_item_valid_i => next_item_valid, next_item_len_i => next_item_len,
next_item_next_l_i => next_item_next_l,
wb_rst_n_i => dma_reg_rst_n_i, next_item_next_h_i => next_item_next_h,
wb_clk_i => dma_reg_clk_i, next_item_attrib_i => next_item_attrib,
wb_adr_i => dma_reg_adr_i(3 downto 0), next_item_valid_i => next_item_valid,
wb_dat_o => dma_reg_dat_o,
wb_dat_i => dma_reg_dat_i, wb_rst_n_i => dma_reg_rst_n_i,
wb_sel_i => dma_reg_sel_i, wb_clk_i => dma_reg_clk_i,
wb_cyc_i => dma_reg_cyc_i, wb_adr_i => dma_reg_adr_i(3 downto 0),
wb_stb_i => dma_reg_stb_i, wb_dat_o => dma_reg_dat_o,
wb_we_i => dma_reg_we_i, wb_dat_i => dma_reg_dat_i,
wb_ack_o => dma_reg_ack_o wb_sel_i => dma_reg_sel_i,
); wb_cyc_i => dma_reg_cyc_i,
wb_stb_i => dma_reg_stb_i,
wb_we_i => dma_reg_we_i,
wb_ack_o => dma_reg_ack_o
);
-- DMA registers is a classic wishbone slave supporting single pipelined cycles -- DMA registers is a classic wishbone slave supporting single pipelined cycles
dma_reg_stall_o <= '0'; dma_reg_stall_o <= '0';
-- Status signals from DMA masters -- Status signals from DMA masters
dma_ctrl_done <= dma_ctrl_l2p_done or dma_ctrl_p2l_done; dma_ctrl_done <= dma_ctrl_l2p_done or dma_ctrl_p2l_done;
dma_ctrl_error <= dma_ctrl_l2p_error or dma_ctrl_p2l_error; dma_ctrl_error <= dma_ctrl_l2p_error or dma_ctrl_p2l_error;
-- Synchronise DMA IRQ pulse to csr_clk_i clock domain -- Synchronise DMA IRQ to csr_clk_i clock domain
l_dma_irq_sync : for I in 0 to dma_irq'length-1 generate cmp_dma_irq_sync : entity work.gc_sync_ffs
cmp_dma_irq_sync : gc_pulse_synchronizer2
port map( port map(
clk_in_i => sys_clk, clk_i => csr_clk_i,
rst_in_n_i => sys_rst_n, rst_n_i => csr_rst_n_i,
clk_out_i => csr_clk_i, data_i => dma_irq,
rst_out_n_i => csr_rst_n_i, synced_o => dma_irq_o
d_p_i => dma_irq(I),
d_ready_o => open,
q_p_o => dma_irq_o(I)
); );
end generate l_dma_irq_sync;
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- L2P DMA master -- L2P DMA master (for board to host transfers)
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
cmp_l2p_dma_master : entity work.l2p_dma_master cmp_l2p_dma_master : entity work.l2p_dma_master
port map generic map (
( g_FIFO_FULL_THRES => g_L2P_FIFO_FULL_THRES,
clk_i => sys_clk, g_FIFO_SIZE => g_L2P_FIFO_SIZE,
rst_n_i => sys_rst_n, g_BYTE_SWAP => TRUE)
port map (
dma_ctrl_target_addr_i => dma_ctrl_carrier_addr, clk_i => sys_clk,
dma_ctrl_host_addr_h_i => dma_ctrl_host_addr_h, rst_n_i => sys_rst_n,
dma_ctrl_host_addr_l_i => dma_ctrl_host_addr_l,
dma_ctrl_len_i => dma_ctrl_len, dma_ctrl_target_addr_i => dma_ctrl_carrier_addr,
dma_ctrl_start_l2p_i => dma_ctrl_start_l2p, dma_ctrl_host_addr_h_i => dma_ctrl_host_addr_h,
dma_ctrl_done_o => dma_ctrl_l2p_done, dma_ctrl_host_addr_l_i => dma_ctrl_host_addr_l,
dma_ctrl_error_o => dma_ctrl_l2p_error, dma_ctrl_len_i => dma_ctrl_len,
dma_ctrl_byte_swap_i => dma_ctrl_byte_swap, dma_ctrl_start_l2p_i => dma_ctrl_start_l2p,
dma_ctrl_abort_i => dma_ctrl_abort, dma_ctrl_done_o => dma_ctrl_l2p_done,
dma_ctrl_error_o => dma_ctrl_l2p_error,
ldm_arb_valid_o => ldm_arb_valid, dma_ctrl_byte_swap_i => dma_ctrl_byte_swap,
ldm_arb_dframe_o => ldm_arb_dframe, dma_ctrl_abort_i => dma_ctrl_abort,
ldm_arb_data_o => ldm_arb_data,
ldm_arb_req_o => ldm_arb_req, ldm_arb_valid_o => ldm_arb_valid,
arb_ldm_gnt_i => arb_ldm_gnt, ldm_arb_dframe_o => ldm_arb_dframe,
ldm_arb_data_o => ldm_arb_data,
l2p_edb_o => l2p_edb, ldm_arb_req_o => ldm_arb_req,
l_wr_rdy_i => l_wr_rdy, ldm_arb_gnt_i => arb_ldm_gnt,
l2p_rdy_i => l2p_rdy,
tx_error_i => tx_error, l2p_edb_o => l2p_edb,
l_wr_rdy_i => l_wr_rdy,
l2p_dma_rst_n_i => dma_rst_n_i, l2p_rdy_i => l2p_rdy,
l2p_dma_clk_i => dma_clk_i, tx_error_i => tx_error,
l2p_dma_adr_o => l2p_dma_adr,
l2p_dma_dat_i => l2p_dma_dat_s2m, wb_dma_rst_n_i => dma_rst_n_i,
l2p_dma_dat_o => l2p_dma_dat_m2s, wb_dma_clk_i => dma_clk_i,
l2p_dma_sel_o => l2p_dma_sel, wb_dma_i => l2p_dma_in,
l2p_dma_cyc_o => l2p_dma_cyc, wb_dma_o => l2p_dma_out);
l2p_dma_stb_o => l2p_dma_stb,
l2p_dma_we_o => l2p_dma_we, l2p_dma_in.dat <= dma_dat_i;
l2p_dma_ack_i => l2p_dma_ack, l2p_dma_in.err <= dma_err_i;
l2p_dma_stall_i => l2p_dma_stall, l2p_dma_in.rty <= dma_rty_i;
p2l_dma_cyc_i => p2l_dma_cyc
); -----------------------------------------------------------------------------
-- P2L DMA master (for host to board transfers)
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- P2L DMA master cmp_p2l_dma_master : entity work.p2l_dma_master
----------------------------------------------------------------------------- generic map (
cmp_p2l_dma_master : entity work.p2l_dma_master g_FIFO_SIZE => g_P2L_FIFO_SIZE,
port map g_BYTE_SWAP => TRUE)
( port map (
clk_i => sys_clk, clk_i => sys_clk,
rst_n_i => sys_rst_n, rst_n_i => sys_rst_n,
dma_ctrl_carrier_addr_i => dma_ctrl_carrier_addr, dma_ctrl_carrier_addr_i => dma_ctrl_carrier_addr,
dma_ctrl_host_addr_h_i => dma_ctrl_host_addr_h, dma_ctrl_host_addr_h_i => dma_ctrl_host_addr_h,
dma_ctrl_host_addr_l_i => dma_ctrl_host_addr_l, dma_ctrl_host_addr_l_i => dma_ctrl_host_addr_l,
dma_ctrl_len_i => dma_ctrl_len, dma_ctrl_len_i => dma_ctrl_len,
dma_ctrl_start_p2l_i => dma_ctrl_start_p2l, dma_ctrl_start_p2l_i => dma_ctrl_start_p2l,
dma_ctrl_start_next_i => dma_ctrl_start_next, dma_ctrl_start_next_i => dma_ctrl_start_next,
dma_ctrl_done_o => dma_ctrl_p2l_done, dma_ctrl_done_o => dma_ctrl_p2l_done,
dma_ctrl_error_o => dma_ctrl_p2l_error, dma_ctrl_error_o => dma_ctrl_p2l_error,
dma_ctrl_byte_swap_i => dma_ctrl_byte_swap, dma_ctrl_byte_swap_i => dma_ctrl_byte_swap,
dma_ctrl_abort_i => dma_ctrl_abort, dma_ctrl_abort_i => dma_ctrl_abort,
pd_pdm_hdr_start_i => p2l_hdr_start, pd_pdm_hdr_start_i => p2l_hdr_start,
pd_pdm_hdr_length_i => p2l_hdr_length, pd_pdm_hdr_length_i => p2l_hdr_length,
pd_pdm_hdr_cid_i => p2l_hdr_cid, pd_pdm_hdr_cid_i => p2l_hdr_cid,
pd_pdm_master_cpld_i => p2l_master_cpld, pd_pdm_master_cpld_i => p2l_master_cpld,
pd_pdm_master_cpln_i => p2l_master_cpln, pd_pdm_master_cpln_i => p2l_master_cpln,
pd_pdm_data_valid_i => p2l_d_valid, pd_pdm_data_valid_i => p2l_d_valid,
pd_pdm_data_last_i => p2l_d_last, pd_pdm_data_last_i => p2l_d_last,
pd_pdm_data_i => p2l_d, pd_pdm_data_i => p2l_d,
pd_pdm_be_i => p2l_be, pd_pdm_be_i => p2l_be,
p2l_rdy_o => p2l_rdy_pdm, p2l_rdy_o => p2l_rdy_pdm,
rx_error_o => rx_error_o, rx_error_o => rx_error_o,
pdm_arb_valid_o => pdm_arb_valid, pdm_arb_valid_o => pdm_arb_valid,
pdm_arb_dframe_o => pdm_arb_dframe, pdm_arb_dframe_o => pdm_arb_dframe,
pdm_arb_data_o => pdm_arb_data, pdm_arb_data_o => pdm_arb_data,
pdm_arb_req_o => pdm_arb_req, pdm_arb_req_o => pdm_arb_req,
arb_pdm_gnt_i => arb_pdm_gnt, arb_pdm_gnt_i => arb_pdm_gnt,
p2l_dma_rst_n_i => dma_rst_n_i, wb_dma_rst_n_i => dma_rst_n_i,
p2l_dma_clk_i => dma_clk_i, wb_dma_clk_i => dma_clk_i,
p2l_dma_adr_o => p2l_dma_adr, wb_dma_i => p2l_dma_in,
p2l_dma_dat_i => p2l_dma_dat_s2m, wb_dma_o => p2l_dma_out,
p2l_dma_dat_o => p2l_dma_dat_m2s,
p2l_dma_sel_o => p2l_dma_sel, next_item_carrier_addr_o => next_item_carrier_addr,
p2l_dma_cyc_o => p2l_dma_cyc, next_item_host_addr_h_o => next_item_host_addr_h,
p2l_dma_stb_o => p2l_dma_stb, next_item_host_addr_l_o => next_item_host_addr_l,
p2l_dma_we_o => p2l_dma_we, next_item_len_o => next_item_len,
p2l_dma_ack_i => p2l_dma_ack, next_item_next_l_o => next_item_next_l,
p2l_dma_stall_i => p2l_dma_stall, next_item_next_h_o => next_item_next_h,
l2p_dma_cyc_i => l2p_dma_cyc, next_item_attrib_o => next_item_attrib,
next_item_valid_o => next_item_valid
next_item_carrier_addr_o => next_item_carrier_addr, );
next_item_host_addr_h_o => next_item_host_addr_h,
next_item_host_addr_l_o => next_item_host_addr_l,
next_item_len_o => next_item_len,
next_item_next_l_o => next_item_next_l,
next_item_next_h_o => next_item_next_h,
next_item_attrib_o => next_item_attrib,
next_item_valid_o => next_item_valid
);
p_dma_wb_mux : process (l2p_dma_adr, l2p_dma_cyc, l2p_dma_dat_m2s,
l2p_dma_sel, l2p_dma_stb, l2p_dma_we, p2l_dma_adr,
p2l_dma_cyc, p2l_dma_dat_m2s, p2l_dma_sel,
p2l_dma_stb, p2l_dma_we)
begin
if (l2p_dma_cyc = '1') then
dma_adr_o <= l2p_dma_adr;
dma_dat_o <= l2p_dma_dat_m2s;
dma_sel_o <= l2p_dma_sel;
dma_cyc_o <= l2p_dma_cyc;
dma_stb_o <= l2p_dma_stb;
dma_we_o <= l2p_dma_we;
elsif (p2l_dma_cyc = '1') then
dma_adr_o <= p2l_dma_adr;
dma_dat_o <= p2l_dma_dat_m2s;
dma_sel_o <= p2l_dma_sel;
dma_cyc_o <= p2l_dma_cyc;
dma_stb_o <= p2l_dma_stb;
dma_we_o <= p2l_dma_we;
else
dma_adr_o <= (others => '0');
dma_dat_o <= (others => '0');
dma_sel_o <= (others => '0');
dma_cyc_o <= '0';
dma_stb_o <= '0';
dma_we_o <= '0';
end if;
end process p_dma_wb_mux;
l2p_dma_dat_s2m <= dma_dat_i; p2l_dma_in.dat <= dma_dat_i;
p2l_dma_dat_s2m <= dma_dat_i; p2l_dma_in.err <= dma_err_i;
l2p_dma_ack <= dma_ack_i; p2l_dma_in.rty <= dma_rty_i;
p2l_dma_ack <= dma_ack_i;
l2p_dma_stall <= dma_stall_i;
p2l_dma_stall <= dma_stall_i;
-- NOTE: dma_ctrl_direction crosses clock domains.
process (dma_clk_i)
begin
if rising_edge(dma_clk_i) then
dma_ctrl_direction_d <= dma_ctrl_direction;
end if;
end process;
p_dma_wb_mux : process (dma_ack_i, dma_ctrl_direction_d, dma_stall_i,
l2p_dma_out, p2l_dma_out)
begin
if dma_ctrl_direction_d = '0' then
dma_adr_o <= l2p_dma_out.adr;
dma_dat_o <= l2p_dma_out.dat;
dma_sel_o <= l2p_dma_out.sel;
dma_cyc_o <= l2p_dma_out.cyc;
dma_stb_o <= l2p_dma_out.stb;
dma_we_o <= l2p_dma_out.we;
l2p_dma_in.ack <= dma_ack_i;
l2p_dma_in.stall <= dma_stall_i;
p2l_dma_in.ack <= '0';
p2l_dma_in.stall <= '0';
else
dma_adr_o <= p2l_dma_out.adr;
dma_dat_o <= p2l_dma_out.dat;
dma_sel_o <= p2l_dma_out.sel;
dma_cyc_o <= p2l_dma_out.cyc;
dma_stb_o <= p2l_dma_out.stb;
dma_we_o <= p2l_dma_out.we;
p2l_dma_in.ack <= dma_ack_i;
p2l_dma_in.stall <= dma_stall_i;
l2p_dma_in.ack <= '0';
l2p_dma_in.stall <= '0';
end if;
end process p_dma_wb_mux;
end generate gen_with_dma;
gen_without_dma : if not g_WITH_DMA generate
rx_error_o <= '0';
dma_irq_o <= '0';
dma_reg_dat_o <= (others => '0');
dma_adr_o <= (others => '0');
dma_dat_o <= (others => '0');
dma_sel_o <= (others => '0');
ldm_arb_data <= (others => '0');
pdm_arb_data <= (others => '0');
dma_reg_ack_o <= '0';
dma_reg_stall_o <= '0';
dma_stb_o <= '0';
dma_we_o <= '0';
dma_cyc_o <= '0';
p2l_rdy_pdm <= '1';
l2p_edb <= '0';
ldm_arb_req <= '0';
ldm_arb_valid <= '0';
ldm_arb_dframe <= '0';
pdm_arb_req <= '0';
pdm_arb_valid <= '0';
pdm_arb_dframe <= '0';
end generate gen_without_dma;
--=========================================================================== --===========================================================================
-- L2P DataPath -- L2P DataPath
...@@ -793,7 +818,7 @@ begin ...@@ -793,7 +818,7 @@ begin
arb_wbm_gnt_o => arb_wbm_gnt, arb_wbm_gnt_o => arb_wbm_gnt,
--------------------------------------------------------- ---------------------------------------------------------
-- From DMA controller (pdm) to arbiter (arb) -- From P2L DMA master (pdm) to arbiter (arb)
pdm_arb_valid_i => pdm_arb_valid, pdm_arb_valid_i => pdm_arb_valid,
pdm_arb_dframe_i => pdm_arb_dframe, pdm_arb_dframe_i => pdm_arb_dframe,
pdm_arb_data_i => pdm_arb_data, pdm_arb_data_i => pdm_arb_data,
...@@ -850,4 +875,3 @@ end rtl; ...@@ -850,4 +875,3 @@ end rtl;
--============================================================================== --==============================================================================
-- Architecture end (gn4124_core) -- Architecture end (gn4124_core)
--============================================================================== --==============================================================================
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
-- Spartan6 FPGAs version. -- Spartan6 FPGAs version.
-- --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Copyright CERN 2010-2018 -- Copyright CERN 2010-2020
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware -- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except -- License, Version 2.0 (the "License"); you may not use this file except
...@@ -55,13 +55,21 @@ package gn4124_core_pkg is ...@@ -55,13 +55,21 @@ package gn4124_core_pkg is
component xwb_gn4124_core is component xwb_gn4124_core is
generic ( generic (
g_WB_MASTER_MODE : t_wishbone_interface_mode := PIPELINED; g_WITH_DMA : boolean := TRUE;
g_WB_MASTER_GRANULARITY : t_wishbone_address_granularity := BYTE; g_WBM_TO_WB_FIFO_SIZE : positive := 128;
g_WB_DMA_CFG_MODE : t_wishbone_interface_mode := PIPELINED; g_WBM_TO_WB_FIFO_FULL_THRES : positive := 110;
g_WB_DMA_CFG_GRANULARITY : t_wishbone_address_granularity := BYTE; g_WBM_FROM_WB_FIFO_SIZE : positive := 128;
g_WB_DMA_DAT_MODE : t_wishbone_interface_mode := PIPELINED; g_WBM_FROM_WB_FIFO_FULL_THRES : positive := 110;
g_WB_DMA_DAT_GRANULARITY : t_wishbone_address_granularity := BYTE; g_P2L_FIFO_SIZE : positive := 64;
g_ACK_TIMEOUT : positive := 100); g_L2P_FIFO_SIZE : positive := 256;
g_L2P_FIFO_FULL_THRES : positive := 64;
g_WB_MASTER_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_MASTER_GRANULARITY : t_wishbone_address_granularity := BYTE;
g_WB_DMA_CFG_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_DMA_CFG_GRANULARITY : t_wishbone_address_granularity := BYTE;
g_WB_DMA_DAT_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_DMA_DAT_GRANULARITY : t_wishbone_address_granularity := BYTE;
g_ACK_TIMEOUT : positive := 100);
port ( port (
rst_n_a_i : in std_logic; rst_n_a_i : in std_logic;
status_o : out std_logic_vector(31 downto 0); status_o : out std_logic_vector(31 downto 0);
...@@ -85,7 +93,7 @@ package gn4124_core_pkg is ...@@ -85,7 +93,7 @@ package gn4124_core_pkg is
l_wr_rdy_i : in std_logic_vector(1 downto 0); l_wr_rdy_i : in std_logic_vector(1 downto 0);
p_rd_d_rdy_i : in std_logic_vector(1 downto 0); p_rd_d_rdy_i : in std_logic_vector(1 downto 0);
tx_error_i : in std_logic; tx_error_i : in std_logic;
dma_irq_o : out std_logic_vector(1 downto 0); dma_irq_o : out std_logic; -- Interrupt source to IRQ manager
irq_p_i : in std_logic; irq_p_i : in std_logic;
irq_p_o : out std_logic; irq_p_o : out std_logic;
wb_master_clk_i : in std_logic; wb_master_clk_i : in std_logic;
...@@ -105,10 +113,16 @@ package gn4124_core_pkg is ...@@ -105,10 +113,16 @@ package gn4124_core_pkg is
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
component gn4124_core component gn4124_core
generic ( generic (
g_ACK_TIMEOUT : positive := 100 -- Wishbone ACK timeout (in wishbone clock cycles) g_WITH_DMA : boolean := TRUE;
); g_WBM_TO_WB_FIFO_SIZE : positive := 128;
port g_WBM_TO_WB_FIFO_FULL_THRES : positive := 110;
( g_WBM_FROM_WB_FIFO_SIZE : positive := 128;
g_WBM_FROM_WB_FIFO_FULL_THRES : positive := 110;
g_P2L_FIFO_SIZE : positive := 64;
g_L2P_FIFO_SIZE : positive := 256;
g_L2P_FIFO_FULL_THRES : positive := 64;
g_ACK_TIMEOUT : positive := 100);
port (
--------------------------------------------------------- ---------------------------------------------------------
-- Control and status -- Control and status
rst_n_a_i : in std_logic; -- Asynchronous reset from GN4124 rst_n_a_i : in std_logic; -- Asynchronous reset from GN4124
...@@ -148,7 +162,7 @@ package gn4124_core_pkg is ...@@ -148,7 +162,7 @@ package gn4124_core_pkg is
--------------------------------------------------------- ---------------------------------------------------------
-- Interrupt interface -- Interrupt interface
dma_irq_o : out std_logic_vector(1 downto 0); -- Interrupts sources to IRQ manager dma_irq_o : out std_logic; -- Interrupt source to IRQ manager
irq_p_i : in std_logic; -- Interrupt request pulse from IRQ manager irq_p_i : in std_logic; -- Interrupt request pulse from IRQ manager
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO
...@@ -210,9 +224,9 @@ package body gn4124_core_pkg is ...@@ -210,9 +224,9 @@ package body gn4124_core_pkg is
-- enable | byte_swap | din | dout -- enable | byte_swap | din | dout
-- false | XX | ABCD | ABCD -- false | XX | ABCD | ABCD
-- true | 00 | ABCD | ABCD -- true | 00 | ABCD | ABCD
-- true | 01 | ABCD | BADC -- true | 01 | ABCD | DCBA
-- true | 10 | ABCD | CDAB -- true | 10 | ABCD | CDAB
-- true | 11 | ABCD | DCBA -- true | 11 | ABCD | BADC
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
function f_byte_swap ( function f_byte_swap (
constant enable : boolean; constant enable : boolean;
...@@ -226,18 +240,18 @@ package body gn4124_core_pkg is ...@@ -226,18 +240,18 @@ package body gn4124_core_pkg is
when "00" => when "00" =>
dout := din; dout := din;
when "01" => when "01" =>
dout := din(23 downto 16)
& din(31 downto 24)
& din(7 downto 0)
& din(15 downto 8);
when "10" =>
dout := din(15 downto 0)
& din(31 downto 16);
when "11" =>
dout := din(7 downto 0) dout := din(7 downto 0)
& din(15 downto 8) & din(15 downto 8)
& din(23 downto 16) & din(23 downto 16)
& din(31 downto 24); & din(31 downto 24);
when "10" =>
dout := din(15 downto 0)
& din(31 downto 16);
when "11" =>
dout := din(23 downto 16)
& din(31 downto 24)
& din(7 downto 0)
& din(15 downto 8);
when others => when others =>
dout := din; dout := din;
end case; end case;
......
...@@ -97,12 +97,15 @@ architecture rtl of p2l_des is ...@@ -97,12 +97,15 @@ architecture rtl of p2l_des is
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- SDR signals -- SDR signals
signal p2l_valid_t : std_logic_vector(1 downto 0) := (others => '0'); signal p2l_data_t : std_logic_vector(31 downto 0) := (others => '0');
signal p2l_dframe_t : std_logic_vector(1 downto 0) := (others => '0'); signal p2l_data_d : std_logic_vector(31 downto 0) := (others => '0');
signal p2l_dframe_t : std_logic_vector(1 downto 0) := (others => '0');
signal p2l_dframe_d : std_logic := '0';
signal p2l_valid_t : std_logic_vector(1 downto 0) := (others => '0');
signal p2l_valid_d : std_logic := '0';
begin begin
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- data inputs -- data inputs
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
...@@ -119,7 +122,7 @@ begin ...@@ -119,7 +122,7 @@ begin
gclk => sys_clk_i, gclk => sys_clk_i,
bitslip => '0', bitslip => '0',
reset => rst_a_i, reset => rst_a_i,
data_out => p2l_data_o, data_out => p2l_data_t,
debug_in => "00", debug_in => "00",
debug => open); debug => open);
...@@ -143,8 +146,6 @@ begin ...@@ -143,8 +146,6 @@ begin
debug_in => "00", debug_in => "00",
debug => open); debug => open);
p2l_dframe_o <= p2l_dframe_t(0);
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- valid input -- valid input
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
...@@ -165,6 +166,20 @@ begin ...@@ -165,6 +166,20 @@ begin
debug_in => "00", debug_in => "00",
debug => open); debug => open);
p2l_valid_o <= p2l_valid_t(0); ------------------------------------------------------------------------------
-- register module outputs to help with timing
------------------------------------------------------------------------------
p_p2l_reg_out : process (sys_clk_i) is
begin
if rising_edge(sys_clk_i) then
p2l_data_d <= p2l_data_t;
p2l_dframe_d <= p2l_dframe_t(0);
p2l_valid_d <= p2l_valid_t(0);
end if;
end process p_p2l_reg_out;
p2l_data_o <= p2l_data_d;
p2l_dframe_o <= p2l_dframe_d;
p2l_valid_o <= p2l_valid_d;
end rtl; end rtl;
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
-- Version for Spartan6 FPGAs. -- Version for Spartan6 FPGAs.
-- --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Copyright CERN 2018 -- Copyright CERN 2018 - 2020
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware -- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except -- License, Version 2.0 (the "License"); you may not use this file except
...@@ -32,14 +32,26 @@ use work.wishbone_pkg.all; ...@@ -32,14 +32,26 @@ use work.wishbone_pkg.all;
entity xwb_gn4124_core is entity xwb_gn4124_core is
generic ( generic (
g_WB_MASTER_MODE : t_wishbone_interface_mode := PIPELINED; -- If TRUE, enable the DMA interface
g_WB_MASTER_GRANULARITY : t_wishbone_address_granularity := BYTE; g_WITH_DMA : boolean := TRUE;
g_WB_DMA_CFG_MODE : t_wishbone_interface_mode := PIPELINED; -- Tunable size and threshold for all async FIFOs.
g_WB_DMA_CFG_GRANULARITY : t_wishbone_address_granularity := BYTE; -- If not sure, leave the defaults.
g_WB_DMA_DAT_MODE : t_wishbone_interface_mode := PIPELINED; g_WBM_TO_WB_FIFO_SIZE : positive := 128;
g_WB_DMA_DAT_GRANULARITY : t_wishbone_address_granularity := BYTE; g_WBM_TO_WB_FIFO_FULL_THRES : positive := 110;
g_WBM_FROM_WB_FIFO_SIZE : positive := 128;
g_WBM_FROM_WB_FIFO_FULL_THRES : positive := 110;
g_P2L_FIFO_SIZE : positive := 64;
g_L2P_FIFO_SIZE : positive := 256;
g_L2P_FIFO_FULL_THRES : positive := 64;
-- WB config for three WB interfaces
g_WB_MASTER_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_MASTER_GRANULARITY : t_wishbone_address_granularity := BYTE;
g_WB_DMA_CFG_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_DMA_CFG_GRANULARITY : t_wishbone_address_granularity := BYTE;
g_WB_DMA_DAT_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_DMA_DAT_GRANULARITY : t_wishbone_address_granularity := BYTE;
-- Wishbone ACK timeout (in wishbone clock cycles) -- Wishbone ACK timeout (in wishbone clock cycles)
g_ACK_TIMEOUT : positive := 100); g_ACK_TIMEOUT : positive := 100);
port ( port (
--------------------------------------------------------- ---------------------------------------------------------
-- Control and status -- Control and status
...@@ -80,7 +92,7 @@ entity xwb_gn4124_core is ...@@ -80,7 +92,7 @@ entity xwb_gn4124_core is
--------------------------------------------------------- ---------------------------------------------------------
-- Interrupt interface -- Interrupt interface
dma_irq_o : out std_logic_vector(1 downto 0); -- Interrupts sources to IRQ manager dma_irq_o : out std_logic; -- Interrupt source to IRQ manager
irq_p_i : in std_logic; -- Interrupt request pulse from IRQ manager irq_p_i : in std_logic; -- Interrupt request pulse from IRQ manager
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO
...@@ -175,7 +187,15 @@ begin ...@@ -175,7 +187,15 @@ begin
cmp_wrapped_gn4124 : gn4124_core cmp_wrapped_gn4124 : gn4124_core
generic map ( generic map (
g_ACK_TIMEOUT => g_ACK_TIMEOUT) g_WITH_DMA => g_WITH_DMA,
g_WBM_TO_WB_FIFO_SIZE => g_WBM_TO_WB_FIFO_SIZE,
g_WBM_TO_WB_FIFO_FULL_THRES => g_WBM_TO_WB_FIFO_FULL_THRES,
g_WBM_FROM_WB_FIFO_SIZE => g_WBM_FROM_WB_FIFO_SIZE,
g_WBM_FROM_WB_FIFO_FULL_THRES => g_WBM_FROM_WB_FIFO_FULL_THRES,
g_P2L_FIFO_SIZE => g_P2L_FIFO_SIZE,
g_L2P_FIFO_SIZE => g_L2P_FIFO_SIZE,
g_L2P_FIFO_FULL_THRES => g_L2P_FIFO_FULL_THRES,
g_ACK_TIMEOUT => g_ACK_TIMEOUT)
port map ( port map (
rst_n_a_i => rst_n_a_i, rst_n_a_i => rst_n_a_i,
status_o => status_o, status_o => status_o,
......
...@@ -33,10 +33,12 @@ use work.genram_pkg.all; ...@@ -33,10 +33,12 @@ use work.genram_pkg.all;
entity wbmaster32 is entity wbmaster32 is
generic ( generic (
g_ACK_TIMEOUT : positive := 100 -- Wishbone ACK timeout (in wb_clk cycles) g_TO_WB_FIFO_SIZE : positive := 128;
); g_TO_WB_FIFO_FULL_THRES : positive := 110;
port g_FROM_WB_FIFO_SIZE : positive := 128;
( g_FROM_WB_FIFO_FULL_THRES : positive := 110;
g_ACK_TIMEOUT : positive := 100); -- Wishbone ACK timeout (in wb_clk cycles)
port (
--------------------------------------------------------- ---------------------------------------------------------
-- GN4124 core clock and reset -- GN4124 core clock and reset
clk_i : in std_logic; clk_i : in std_logic;
...@@ -98,15 +100,6 @@ end wbmaster32; ...@@ -98,15 +100,6 @@ end wbmaster32;
architecture behaviour of wbmaster32 is architecture behaviour of wbmaster32 is
-----------------------------------------------------------------------------
-- Constants declaration
-----------------------------------------------------------------------------
constant c_TO_WB_FIFO_SIZE : integer := 128;
constant c_TO_WB_FIFO_FULL_THRES : integer := 110;
constant c_FROM_WB_FIFO_SIZE : integer := 128;
constant c_FROM_WB_FIFO_FULL_THRES : integer := 110;
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Signals declaration -- Signals declaration
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
...@@ -149,7 +142,7 @@ architecture behaviour of wbmaster32 is ...@@ -149,7 +142,7 @@ architecture behaviour of wbmaster32 is
signal wb_we_t : std_logic; signal wb_we_t : std_logic;
signal wb_sel_t : std_logic_vector(3 downto 0) := (others => '0'); signal wb_sel_t : std_logic_vector(3 downto 0) := (others => '0');
signal wb_stall_t : std_logic; signal wb_stall_t : std_logic;
signal wb_cid_t : std_logic_vector(1 downto 0); signal wb_cid_t : std_logic_vector(1 downto 0) := (others => '0');
signal wb_ack_timeout_cnt : unsigned(log2_ceil(g_ACK_TIMEOUT)-1 downto 0); signal wb_ack_timeout_cnt : unsigned(log2_ceil(g_ACK_TIMEOUT)-1 downto 0);
signal wb_ack_timeout : std_logic; signal wb_ack_timeout : std_logic;
...@@ -314,7 +307,7 @@ begin ...@@ -314,7 +307,7 @@ begin
cmp_fifo_to_wb : generic_async_fifo_dual_rst cmp_fifo_to_wb : generic_async_fifo_dual_rst
generic map ( generic map (
g_data_width => 66, g_data_width => 66,
g_size => c_TO_WB_FIFO_SIZE, g_size => g_TO_WB_FIFO_SIZE,
g_show_ahead => false, g_show_ahead => false,
g_with_rd_empty => true, g_with_rd_empty => true,
g_with_rd_full => false, g_with_rd_full => false,
...@@ -327,7 +320,7 @@ begin ...@@ -327,7 +320,7 @@ begin
g_with_wr_almost_full => true, g_with_wr_almost_full => true,
g_with_wr_count => false, g_with_wr_count => false,
g_almost_empty_threshold => 0, g_almost_empty_threshold => 0,
g_almost_full_threshold => c_TO_WB_FIFO_FULL_THRES) g_almost_full_threshold => g_TO_WB_FIFO_FULL_THRES)
port map ( port map (
rst_wr_n_i => fifo_rst_n, rst_wr_n_i => fifo_rst_n,
clk_wr_i => clk_i, clk_wr_i => clk_i,
...@@ -357,7 +350,7 @@ begin ...@@ -357,7 +350,7 @@ begin
cmp_from_wb_fifo : generic_async_fifo_dual_rst cmp_from_wb_fifo : generic_async_fifo_dual_rst
generic map ( generic map (
g_data_width => 34, g_data_width => 34,
g_size => c_FROM_WB_FIFO_SIZE, g_size => g_FROM_WB_FIFO_SIZE,
g_show_ahead => false, g_show_ahead => false,
g_with_rd_empty => true, g_with_rd_empty => true,
g_with_rd_full => false, g_with_rd_full => false,
...@@ -370,7 +363,7 @@ begin ...@@ -370,7 +363,7 @@ begin
g_with_wr_almost_full => true, g_with_wr_almost_full => true,
g_with_wr_count => false, g_with_wr_count => false,
g_almost_empty_threshold => 0, g_almost_empty_threshold => 0,
g_almost_full_threshold => c_FROM_WB_FIFO_FULL_THRES) g_almost_full_threshold => g_FROM_WB_FIFO_FULL_THRES)
port map ( port map (
rst_wr_n_i => wb_fifo_rst_n, rst_wr_n_i => wb_fifo_rst_n,
clk_wr_i => wb_clk_i, clk_wr_i => wb_clk_i,
......
...@@ -5,11 +5,14 @@ target = "xilinx" ...@@ -5,11 +5,14 @@ target = "xilinx"
syn_device = "xc6slx45t" syn_device = "xc6slx45t"
vcom_opt = "-93 -mixedsvvh" vcom_opt = "-93 -mixedsvvh"
fetchto = "../../../ip_cores" # Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../ip_cores"
include_dirs = [ include_dirs = [
"../gn4124_bfm", "../gn4124_bfm",
"../../../ip_cores/general-cores/sim/", fetchto + "/general-cores/sim",
] ]
files = [ files = [
...@@ -18,10 +21,9 @@ files = [ ...@@ -18,10 +21,9 @@ files = [
modules = { modules = {
"local" : [ "local" : [
"../gn4124_bfm", "../../../",
"../../rtl",
], ],
"git" : [ "git" : [
"git://ohwr.org/hdl-core-lib/general-cores.git", "https://ohwr.org/project/general-cores.git",
], ],
} }
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// GN4124 core for PCIe FMC carrier
// http://www.ohwr.org/projects/gn4124-core
//------------------------------------------------------------------------------
//
// unit name: main
//
// description: This is a simple example testbench, to demonstrate how to use
// the SystemVerilog BFM of the GN4124 to perform simple accesses over wishbone.
//
// The testbench simply connects the wishbone master of the GN4124 to its own
// DMA configuration wishbone slave and attaches a pre-initialised dummy RAM
// with a wishbone interface to the pipelined DMA interface in order to perform
// a DMA read.
//
//------------------------------------------------------------------------------
// Copyright CERN 2019
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------
`timescale 1ns/1ps
`include "gn4124_bfm.svh"
import wishbone_pkg::*;
module main;
reg clk_125m = 0;
reg clk_62m5 = 0;
logic gn4124_irq;
t_wishbone_master_in wb_in, wb_dma_in, wb_mem_in;
t_wishbone_master_out wb_out, wb_dma_out, wb_mem_out;
always #4ns clk_125m <= ~clk_125m;
always #23ns clk_62m5 <= ~clk_62m5;
logic rst_125m_n;
logic rst_62m5_n;
logic rst_gn4124_n;
logic clk_gn4124;
logic wb_dma_clk;
logic wb_dma_rst_n;
initial begin
rst_125m_n = 0;
rst_62m5_n = 0;
#80ns;
rst_125m_n = 1;
rst_62m5_n = 1;
end
IGN4124PCIMaster i_gn4124 ();
xwb_gn4124_core
DUT (
.rst_n_a_i (i_gn4124.rst_n),
.p2l_clk_p_i (i_gn4124.p2l_clk_p),
.p2l_clk_n_i (i_gn4124.p2l_clk_n),
.p2l_data_i (i_gn4124.p2l_data),
.p2l_dframe_i (i_gn4124.p2l_dframe),
.p2l_valid_i (i_gn4124.p2l_valid),
.p2l_rdy_o (i_gn4124.p2l_rdy),
.p_wr_req_i (i_gn4124.p_wr_req),
.p_wr_rdy_o (i_gn4124.p_wr_rdy),
.rx_error_o (i_gn4124.rx_error),
.vc_rdy_i (i_gn4124.vc_rdy),
.l2p_clk_p_o (i_gn4124.l2p_clk_p),
.l2p_clk_n_o (i_gn4124.l2p_clk_n),
.l2p_data_o (i_gn4124.l2p_data),
.l2p_dframe_o (i_gn4124.l2p_dframe),
.l2p_valid_o (i_gn4124.l2p_valid),
.l2p_edb_o (i_gn4124.l2p_edb),
.l2p_rdy_i (i_gn4124.l2p_rdy),
.l_wr_rdy_i (i_gn4124.l_wr_rdy),
.p_rd_d_rdy_i (i_gn4124.p_rd_d_rdy),
.tx_error_i (i_gn4124.tx_error),
.dma_irq_o (dma_irq),
.irq_p_i (1'b0),
.irq_p_o (gn4124_irq),
.status_o (),
.wb_master_clk_i (clk_125m),
.wb_master_rst_n_i (rst_125m_n),
.wb_master_i (wb_in),
.wb_master_o (wb_out),
.wb_dma_cfg_clk_i (clk_125m),
.wb_dma_cfg_rst_n_i (rst_125m_n),
.wb_dma_cfg_i (wb_out),
.wb_dma_cfg_o (wb_in),
.wb_dma_dat_clk_i (wb_dma_clk),
.wb_dma_dat_rst_n_i (wb_dma_rst_n),
.wb_dma_dat_i (wb_dma_in),
.wb_dma_dat_o (wb_dma_out)
);
assign wb_dma_clk = clk_125m;
assign wb_dma_rst_n = rst_125m_n;
xwb_dpram #
(
.g_size (16384),
.g_slave1_interface_mode (1), // 1 = PIPELINED
.g_slave2_interface_mode (1),
.g_slave1_granularity (1), // 1 = WORD
.g_slave2_granularity (1)
)
MEM (
.rst_n_i (wb_dma_rst_n),
.clk_sys_i (wb_dma_clk),
.slave1_i (wb_dma_out),
.slave1_o (wb_dma_in),
.slave2_i (wb_mem_out),
.slave2_o (wb_mem_in)
);
CBusAccessor acc;
task val_check(string name, uint32_t addr, val, expected);
if (val != expected)
begin
$display();
$display("Simulation FAILED");
$fatal(1, "%s error at address 0x%.2x. Expected 0x%.8x, got 0x%.8x",
name, addr, expected, val);
end
endtask // val_check
task reg_check(uint32_t addr, expected);
uint64_t val;
acc.read(addr, val);
val_check("Register read-back", addr, val, expected);
endtask // reg_check
task mem_check(uint32_t addr, expected);
uint64_t val;
i_gn4124.host_mem_read(addr, val);
val_check("Memory read-back", addr, val, expected);
endtask // reg_check
task check_irq_status;
// Check irq status
reg_check('h04, 'h04);
if (dma_irq != 1'b1)
$fatal(1, "dma irq should be 1");
endtask
task clear_irq;
acc.write('h04, 'h04);
reg_check('h04, 'h00);
if (dma_irq != 1'b0)
$fatal(1, "dma irq should be 0");
endtask
initial begin
int stall_cycle[14];
automatic int ntest = 1;
const int tests = 12;
uint32_t addr, val, expected;
@(posedge i_gn4124.ready);
acc = i_gn4124.get_accessor();
acc.set_default_xfer_size(4);
@(posedge clk_125m);
// ---------------------------------
$write("Test %0d/%0d: simple read/write accesses over Wishbone: ",
ntest++, tests);
// Verify simple read/writes over wishbone
reg_check('h0, 'h0);
acc.write('h0c, 'hffacce55);
acc.write('h10, 'h1badcafe);
reg_check('h0c, 'hffacce55);
reg_check('h10, 'h1badcafe);
// Reset all DMA config registers
for (addr = 'h00; addr <= 'h20; addr += 4)
begin
acc.write(addr, 'h0);
end
repeat(2) @(posedge clk_125m);
$write("PASS\n");
// ---------------------------------
$write("Test %0d/%0d: 128B read over DMA, abort after first read: ",
ntest++, tests);
if (dma_irq != 1'b0)
$fatal(1, "dma irq should be 0");
acc.write('h14, 'h80); // count
acc.write('h00, 'h01); // start
// wait for transfer to start
@(posedge i_gn4124.l2p_valid);
repeat(2) @(posedge clk_125m);
// Test abort feature
acc.write('h00, 'h02);
reg_check('h04, 'h03);
acc.write('h00, 'h00);
repeat(2) @(posedge clk_125m);
$write("PASS\n");
// ---------------------------------
$write("Test %0d/%0d: 256B DMA write: ",
ntest++, tests);
// Setup data in BFM memory
for (addr = 'h00; addr < 'h40; addr += 1)
i_gn4124.host_mem_write(4 * addr, 32'h80000020 - addr);
// Setup DMA
acc.write('h14, 'h100); // count
acc.write('h20, 'h01); // attrib
acc.write('h0c, 'h20000000); // hstartL
acc.write('h10, 'h00000000); // hstartH
acc.write('h00, 'h01); // start
@(posedge dma_irq);
check_irq_status;
clear_irq;
repeat(4) @(posedge clk_125m);
$write("PASS\n");
// wait for WB transfer to finish
#5us;
// ---------------------------------
$write("Test %0d/%0d: 2x128B chained DMA reads: ",
ntest++, tests);
// Setup DMA chain info in BFM memory
i_gn4124.host_mem_write('h20000, 'h00000080); // remote address
i_gn4124.host_mem_write('h20004, 'h20000080); // hstartL
i_gn4124.host_mem_write('h20008, 'h00000000); // hstartH
i_gn4124.host_mem_write('h2000C, 'h80); // count
i_gn4124.host_mem_write('h20010, 'h00); // nextL
i_gn4124.host_mem_write('h20014, 'h00); // nextH
i_gn4124.host_mem_write('h20018, 'h00); // attrib
acc.write('h14, 'h80); // count
acc.write('h20, 'h02); // attrib
acc.write('h0c, 'h20000000); // hstartL
acc.write('h10, 'h00000000); // hstartH
// Point to chain info in BFM memory
acc.write('h18, 'h20020000); // nextL
acc.write('h1C, 'h00000000); // nextH
acc.write('h00, 'h01); // start
@(posedge dma_irq);
check_irq_status;
clear_irq;
for (addr = 'h00; addr < 'h40; addr += 1)
begin
expected = 32'h80000020 - addr;
mem_check(4 * addr, expected);
end
repeat(4) @(posedge clk_125m);
$write("PASS\n");
// ---------------------------------
$write("Test %0d/%0d: 256B DMA read: ",
ntest++, tests);
// Setup DMA
acc.write('h14, 'h100); // count
acc.write('h20, 'h00); // attrib
acc.write('h0c, 'h20000000); // hstartL
acc.write('h10, 'h00000000); // hstartH
acc.write('h00, 'h01); // start
@(posedge dma_irq);
check_irq_status;
clear_irq;
for (addr = 'h00; addr < 'h40; addr += 1)
begin
expected = 32'h80000020 - addr;
mem_check(4 * addr, expected);
end
repeat(4) @(posedge clk_125m);
$write("PASS\n");
// ---------------------------------
$write("Test %0d/%0d: 256B DMA reads with stalling: ",
ntest++, tests);
// Setup DMA
acc.write('h14, 'h100); // count
acc.write('h20, 'h00); // attrib
acc.write('h0c, 'h20000000); // hstartL
acc.write('h10, 'h00000000); // hstartH
stall_cycle = '{0,1,2,14,15,16,17,30,31,32,33,61,62,63};
foreach(stall_cycle[i])
begin
acc.write('h00, 'h01); // start
@(posedge wb_dma_out.stb);
repeat(stall_cycle[i]) @(posedge clk_125m);
force DUT.cmp_wrapped_gn4124.dma_stall_i = 1'b1;
@(posedge clk_125m);
force DUT.cmp_wrapped_gn4124.dma_ack_i = 1'b0;
@(posedge clk_125m);
release DUT.cmp_wrapped_gn4124.dma_stall_i;
@(posedge clk_125m);
release DUT.cmp_wrapped_gn4124.dma_ack_i;
@(posedge dma_irq);
check_irq_status;
clear_irq;
for (addr = 'h00; addr < 'h40; addr += 1)
begin
expected = 32'h80000020 - addr;
mem_check(4 * addr, expected);
end
repeat(4) @(posedge clk_125m);
end
$write("PASS\n");
// ---------------------------------
$write("Test %0d/%0d: 8KiB chained DMA write: ",
ntest++, tests);
// Setup data in BFM memory
for (addr = 'h00; addr < 'h800; addr += 1)
i_gn4124.host_mem_write(4 * addr, 32'h80000020 - addr);
// Setup DMA chain info in BFM memory
i_gn4124.host_mem_write('h20000, 'h00001800); // remote address
i_gn4124.host_mem_write('h20004, 'h20001800); // hstartL
i_gn4124.host_mem_write('h20008, 'h00000000); // hstartH
i_gn4124.host_mem_write('h2000C, 'h800); // count
i_gn4124.host_mem_write('h20010, 'h00); // nextL
i_gn4124.host_mem_write('h20014, 'h00); // nextH
i_gn4124.host_mem_write('h20018, 'h01); // attrib
// Setup DMA
acc.write('h14, 'h1800); // count
acc.write('h20, 'h03); // attrib
acc.write('h0c, 'h20000000); // hstartL
acc.write('h10, 'h00000000); // hstartH
// Point to chain info in BFM memory
acc.write('h18, 'h20020000); // nextL
acc.write('h1C, 'h00000000); // nextH
acc.write('h00, 'h01); // start
@(posedge dma_irq);
check_irq_status;
clear_irq;
repeat(4) @(posedge clk_125m);
$write("PASS\n");
// wait for WB transfer to finish
#5us;
// Check all four byte swap settings
// ---------------------------------
for (int i = 0; i < 4; i++) begin
$write("Test %0d/%0d: 8KiB DMA read (byte swap = %0d): ",
ntest++, tests, i);
// Restart
acc.write('h14, 'h2000); // count
acc.write('h20, 'h00); // attrib
acc.write('h0c, 'h20000000); // hstartL
acc.write('h10, 'h00000000); // hstartH
acc.write('h00, (i << 2) | 'h01); // start
@(posedge dma_irq);
check_irq_status;
for (addr = 'h00; addr < 'h800; addr += 1)
begin
expected = 32'h80000020 - addr;
if (i == 1)
expected = {<<8{expected}};
else if (i == 2)
expected = {<<16{expected}};
else if (i == 3)
expected = {<<16{{<<8{expected}}}};
mem_check(4 * addr, expected);
end
clear_irq;
repeat(4) @(posedge clk_125m);
$write("PASS\n");
#1us;
end
$write("Test %0d/%0d: 256B DMA read with 32bit host address overflow: ",
ntest++, tests);
acc.write('h14, 'h100); // count
acc.write('h20, 'h00); // attrib
acc.write('h0c, 'hffffff80); // hstartL
acc.write('h10, 'h00000000); // hstartH
acc.write('h00, 'h01); // start
// Transfer will be split internally by L2P DMA master in two requests, the first
// one with a 32-bit adress starting at ffff_ff80 and the next one with a 64-bit
// address starting at 1_0000_0000
@(posedge DUT.cmp_wrapped_gn4124.ldm_arb_dframe);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow header", 1, DUT.cmp_wrapped_gn4124.ldm_arb_data, 'h02ff0020);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow address", 1, DUT.cmp_wrapped_gn4124.ldm_arb_data, 'hffffff80);
@(posedge DUT.cmp_wrapped_gn4124.ldm_arb_dframe);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow header", 2, DUT.cmp_wrapped_gn4124.ldm_arb_data, 'h03ff0020);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow address high", 2, DUT.cmp_wrapped_gn4124.ldm_arb_data, 1);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow address low", 2, DUT.cmp_wrapped_gn4124.ldm_arb_data, 0);
@(posedge dma_irq);
// Check irq status
reg_check('h04, 'h04);
if (dma_irq != 1'b1)
$fatal(1, "dma irq should be 1");
// clear irq
acc.write('h04, 'h04);
reg_check('h04, 'h00);
if (dma_irq != 1'b0)
$fatal(1, "dma irq should be 0");
repeat(4) @(posedge clk_125m);
$write("PASS\n");
$display();
$display("Simulation PASSED");
$finish;
end // initial begin
endmodule // main