Commit 4e67ab38 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

modules/wrsw_swcore: removed obsolete files

parent 05efcd1e
SRCS_VHDL = swc_swcore_pkg.vhd \
swc_block_alloc.vhd \
swc_core.vhd \
swc_input_block.vhd \
swc_lost_pck_dealloc.vhd \
swc_multiport_linked_list.vhd \
swc_multiport_page_allocator.vhd \
swc_multiport_pck_pg_free_module.vhd \
swc_ob_prio_queue.vhd \
swc_output_block.vhd \
swc_packet_mem.vhd \
swc_packet_mem_read_pump.vhd \
swc_packet_mem_write_pump.vhd \
swc_page_alloc.vhd \
swc_pck_pg_free_module.vhd \
swc_pck_transfer_arbiter.vhd \
swc_pck_transfer_input.vhd \
swc_pck_transfer_output.vhd \
swc_prio_encoder.vhd \
swc_rr_arbiter.vhd
WORK = work
#directories in which we should search for the VHDL/verilog source files
VPATH =
include ../../scripts/modules.mk
-- Copyright (C) 1991-2009 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Quartus II generated Memory Initialization File (.mif)
WIDTH=32;
DEPTH=32;
ADDRESS_RADIX=UNS;
DATA_RADIX=UNS;
CONTENT BEGIN
[0..31] : 4294967295;
END;
-------------------------------------------------------------------------------
-- Title : Switch Core
-- Project : WhiteRabbit switch
-------------------------------------------------------------------------------
-- File : swc_core.vhd
-- Author : Maciej Lipinski
-- Company : CERN BE-Co-HT
-- Created : 2010-10-29
-- Last update: 2010-10-29
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description:
--
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
--
-------------------------------------------------------------------------------
--
-- Copyright (c) 2010 Maciej Lipinski / CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-10-29 1.0 mlipinsk Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.swc_swcore_pkg.all;
entity swc_core is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-------------------------------------------------------------------------------
-- Fabric I/F : input (comes from the Endpoint)
-------------------------------------------------------------------------------
tx_sof_p1_i : in std_logic;
tx_eof_p1_i : in std_logic;
tx_data_i : in std_logic_vector(c_swc_data_width - 1 downto 0);
tx_ctrl_i : in std_logic_vector(c_swc_ctrl_width - 1 downto 0);
tx_valid_i : in std_logic;
tx_bytesel_i : in std_logic;
tx_dreq_o : out std_logic;
tx_abort_p1_i : in std_logic;
tx_rerror_p1_i : in std_logic;
-------------------------------------------------------------------------------
-- Fabric I/F : output (goes to the Endpoint)
-------------------------------------------------------------------------------
rx_sof_p1_o : out std_logic;
rx_eof_p1_o : out std_logic;
rx_dreq_i : in std_logic;
rx_ctrl_o : out std_logic_vector(c_swc_ctrl_width - 1 downto 0);
rx_data_o : out std_logic_vector(c_swc_data_width - 1 downto 0);
rx_valid_o : out std_logic;
rx_bytesel_o : out std_logic;
rx_idle_o : out std_logic;
rx_rerror_p1_o : out std_logic;
rx_terror_p1_i : in std_logic;
rx_rabort_p1_i : in std_logic;
-- rx_sof_p1_o : out std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_eof_p1_o : out std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_dreq_i : in std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_ctrl_o : out std_logic_vector(c_swc_num_ports * c_swc_ctrl_width - 1 downto 0);
-- rx_data_o : out std_logic_vector(c_swc_num_ports * c_swc_data_width - 1 downto 0);
-- rx_valid_o : out std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_bytesel_o : out std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_idle_o : out std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_rerror_p1_o : out std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_terror_p1_i : in std_logic_vector(c_swc_num_ports - 1 downto 0);
-- rx_rabort_p1_i : in std_logic_vector(c_swc_num_ports - 1 downto 0);
-------------------------------------------------------------------------------
-- I/F with Routing Table Unit (RTU)
-------------------------------------------------------------------------------
rtu_rsp_valid_i : in std_logic;
rtu_rsp_ack_o : out std_logic;
rtu_dst_port_mask_i : in std_logic_vector(c_swc_num_ports - 1 downto 0);
rtu_drop_i : in std_logic;
rtu_prio_i : in std_logic_vector(c_swc_prio_width - 1 downto 0)
);
end swc_core;
architecture rtl of swc_core is
----------------------------------------------------------------------------------------------------
-- signals connecting >>Input Block<< with >>Memory Management Unit<<
----------------------------------------------------------------------------------------------------
-- Input Block -> Memory Management Unit
signal ib_page_alloc_req : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ib_pageaddr_output : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
signal ib_set_usecnt : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ib_usecnt : std_logic_vector(c_swc_num_ports * c_swc_usecount_width - 1 downto 0);
-- Memory Management Unit -> Input Block
signal mmu_page_alloc_done : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mmu_pageaddr_input : std_logic_vector( 1 * c_swc_page_addr_width - 1 downto 0);
signal mmu_set_usecnt_done : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mmu_nomem : std_logic;
----------------------------------------------------------------------------------------------------
-- signals connecting >>Input Block<< with >>Multiport Memory<<
----------------------------------------------------------------------------------------------------
-- Input Block -> Multiport Memory
signal ib_pckstart : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ib_pageaddr_to_mpm : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
signal ib_pagereq : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ib_data : std_logic_vector(c_swc_num_ports * c_swc_data_width - 1 downto 0);
signal ib_ctrl : std_logic_vector(c_swc_num_ports * c_swc_ctrl_width - 1 downto 0);
signal ib_drdy : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ib_flush : std_logic_vector(c_swc_num_ports - 1 downto 0);
-- Multiport Memory -> Input Block
signal mpm_pageend : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mpm_full : std_logic_vector(c_swc_num_ports - 1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Input Block<< with >>Pck Transfer Arbiter<<
----------------------------------------------------------------------------------------------------
-- Input Block -> Pck Transfer Arbiter
signal ib_transfer_pck : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ib_pageaddr_to_pta : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
signal ib_mask : std_logic_vector(c_swc_num_ports * c_swc_num_ports - 1 downto 0);
signal ib_prio : std_logic_vector(c_swc_num_ports * c_swc_prio_width - 1 downto 0);
signal ib_pck_size : std_logic_vector(c_swc_num_ports * c_swc_max_pck_size_width - 1 downto 0);
-- Pck Transfer Arbiter -> Input Block
signal pta_transfer_ack : std_logic_vector(c_swc_num_ports - 1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Output Block<< with >>Pck Transfer Arbiter<<
----------------------------------------------------------------------------------------------------
-- Input Block -> Pck Transfer Arbiter
signal pta_data_valid : std_logic_vector(c_swc_num_ports -1 downto 0);
signal pta_pageaddr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
signal pta_prio : std_logic_vector(c_swc_num_ports * c_swc_prio_width - 1 downto 0);
signal pta_pck_size : std_logic_vector(c_swc_num_ports * c_swc_max_pck_size_width - 1 downto 0);
-- Input Block -> Pck Transfer Arbiter
signal ob_ack : std_logic_vector(c_swc_num_ports -1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Output Block<< with >>Multiport Memory<<
----------------------------------------------------------------------------------------------------
-- Output Block -> Multiport Memory
signal ob_pgreq : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ob_pgaddr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
signal ob_dreq : std_logic_vector(c_swc_num_ports - 1 downto 0);
-- Multiport Memory -> Output Block
signal mpm_pckend : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mpm_pgend : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mpm_drdy : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mpm_data : std_logic_vector(c_swc_num_ports * c_swc_data_width - 1 downto 0);
signal mpm_ctrl : std_logic_vector(c_swc_num_ports * c_swc_ctrl_width - 1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Muliport Memory<< with >>Linked List<<
----------------------------------------------------------------------------------------------------
-- Multiport Memory -> Linked List
signal mpm_write : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mpm_write_addr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
signal mpm_write_data : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
signal mpm_read_pump_read : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal mpm_read_pump_addr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
-- Linked List -> Multiport memory
-- signal ll_free_done : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ll_write_done : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ll_read_pump_read_done : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ll_data : std_logic_vector(c_swc_page_addr_width - 1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Input Block<< with >>Pck's pages freeeing module<<
----------------------------------------------------------------------------------------------------
-- Input block -> Lost pck dealloc
signal ib_force_free : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ib_force_free_pgaddr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
-- lost pck dealloc -> input block
signal ppfm_force_free_done_to_ib : std_logic_vector(c_swc_num_ports - 1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Output Block<< with >>Pck's Pages Freeing Module (PPFM)<<
----------------------------------------------------------------------------------------------------
-- output block -> Lost pck dealloc
signal ob_free : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal ob_free_pgaddr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width - 1 downto 0);
-- lost pck dealloc -> output block
signal ppfm_free_done_to_ob : std_logic_vector(c_swc_num_ports - 1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Pck's pages freeeing module<< with >>Linkded List<<
----------------------------------------------------------------------------------------------------
-- LPD -> LL
signal ppfm_read_addr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width -1 downto 0);
signal ppfm_read_req : std_logic_vector(c_swc_num_ports-1 downto 0);
-- LL -> LPD
signal ll_read_valid_data : std_logic_vector(c_swc_num_ports-1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Pck's pages freeing module (PPFM)<< with >>Page allocator (MMU)<<
----------------------------------------------------------------------------------------------------
-- PPFM -> MMU
signal ppfm_force_free : std_logic_vector(c_swc_num_ports-1 downto 0);
signal ppfm_force_free_pgaddr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width -1 downto 0);
signal ppfm_free : std_logic_vector(c_swc_num_ports-1 downto 0);
signal ppfm_free_pgaddr : std_logic_vector(c_swc_num_ports * c_swc_page_addr_width -1 downto 0);
-- MMU -> PPFM
signal mmu_force_free_done : std_logic_vector(c_swc_num_ports-1 downto 0);
signal mmu_free_done : std_logic_vector(c_swc_num_ports-1 downto 0);
----------------------------------------------------------------------------------------------------
-- tmp
----------------------------------------------------------------------------------------------------
signal tx_sof_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal tx_eof_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal tx_data : std_logic_vector(c_swc_num_ports * c_swc_data_width - 1 downto 0);
signal tx_ctrl : std_logic_vector(c_swc_num_ports * c_swc_ctrl_width - 1 downto 0);
signal tx_valid : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal tx_bytesel : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal tx_dreq : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal tx_abort_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal tx_rerror_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_sof_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_eof_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_dreq : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_ctrl : std_logic_vector(c_swc_num_ports * c_swc_ctrl_width - 1 downto 0);
signal rx_data : std_logic_vector(c_swc_num_ports * c_swc_data_width - 1 downto 0);
signal rx_valid : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_bytesel : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_idle : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_rerror_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_terror_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rx_rabort_p1 : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rtu_rsp_valid : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rtu_rsp_ack : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rtu_dst_port_mask : std_logic_vector(c_swc_num_ports * c_swc_num_ports - 1 downto 0);
signal rtu_drop : std_logic_vector(c_swc_num_ports - 1 downto 0);
signal rtu_prio : std_logic_vector(c_swc_num_ports * c_swc_prio_width - 1 downto 0);
---- end tmp
begin --rtl
---- tmp
tx_sof_p1(0) <= tx_sof_p1_i;
tx_sof_p1(c_swc_num_ports - 1 downto 1) <= (others=>'0');
tx_eof_p1(0) <= tx_eof_p1_i;
tx_eof_p1(c_swc_num_ports - 1 downto 1) <= (others=>'0');
tx_data(c_swc_data_width - 1 downto 0) <= tx_data_i;
tx_data(c_swc_num_ports * c_swc_data_width - 1 downto c_swc_data_width) <= (others=>'0');
tx_ctrl(c_swc_ctrl_width - 1 downto 0) <= tx_ctrl_i;
tx_ctrl(c_swc_num_ports * c_swc_ctrl_width - 1 downto c_swc_ctrl_width) <= (others=>'0');
tx_valid(0) <= tx_valid_i;
tx_valid(c_swc_num_ports - 1 downto 1) <= (others=>'0');
tx_bytesel(0) <= tx_bytesel_i;
tx_bytesel(c_swc_num_ports - 1 downto 1) <= (others=>'0');
tx_dreq_o <= tx_dreq(0);
tx_abort_p1(0) <= tx_abort_p1_i;
tx_abort_p1(c_swc_num_ports - 1 downto 1) <= (others=>'0');
tx_rerror_p1(0) <= tx_rerror_p1_i;
tx_rerror_p1(c_swc_num_ports - 1 downto 1) <= (others=>'0');
rx_sof_p1_o <= rx_sof_p1(0);
rx_eof_p1_o <= rx_eof_p1(0);
rx_ctrl_o <= rx_ctrl(c_swc_ctrl_width - 1 downto 0);
rx_data_o <= rx_data(c_swc_data_width - 1 downto 0);
rx_valid_o <= rx_valid(0) ;
rx_bytesel_o <= rx_bytesel(0) ;
rx_idle_o <= rx_idle(0);
rx_rerror_p1_o<= rx_rerror_p1(0);
rx_terror_p1(0) <= rx_terror_p1_i;
rx_terror_p1(c_swc_num_ports - 1 downto 1) <= (others => '0');
rx_rabort_p1(0) <= rx_rabort_p1_i;
rx_rabort_p1(c_swc_num_ports - 1 downto 1) <= (others => '0');
rx_dreq(0) <= rx_dreq_i;
rx_dreq(c_swc_num_ports - 1 downto 1) <= (others => '0');
rtu_rsp_valid(0) <= rtu_rsp_valid_i;
rtu_rsp_valid(c_swc_num_ports - 1 downto 1) <= (others=> '0');
rtu_rsp_ack_o <= rtu_rsp_ack(0);
rtu_drop(0) <= rtu_drop_i;
rtu_drop(c_swc_num_ports - 1 downto 1) <= (others=> '0');
rtu_dst_port_mask(c_swc_num_ports - 1 downto 0) <= rtu_dst_port_mask_i;
rtu_dst_port_mask(c_swc_num_ports * c_swc_num_ports - 1 downto c_swc_num_ports) <= (others=> '0');
rtu_prio(c_swc_prio_width - 1 downto 0) <= rtu_prio_i;
rtu_prio(c_swc_prio_width * c_swc_num_ports - 1 downto c_swc_prio_width)<= (others=> '0');
---- end timp
gen_blocks : for i in 0 to c_swc_num_ports-1 generate
INPUT_BLOCK : swc_input_block
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
-------------------------------------------------------------------------------
-- Fabric I/F
------------------------------------------------------------------------------
tx_sof_p1_i => tx_sof_p1(i),
tx_eof_p1_i => tx_eof_p1(i),
tx_data_i => tx_data((i + 1) * c_swc_data_width -1 downto i * c_swc_data_width),
tx_ctrl_i => tx_ctrl((i + 1) * c_swc_ctrl_width -1 downto i * c_swc_ctrl_width),
tx_valid_i => tx_valid(i),
tx_bytesel_i => tx_bytesel(i),
tx_dreq_o => tx_dreq(i),
tx_abort_p1_i => tx_abort_p1(i),
tx_rerror_p1_i => tx_rerror_p1(i),
-------------------------------------------------------------------------------
-- I/F with Page allocator (MMU)
-------------------------------------------------------------------------------
mmu_page_alloc_req_o => ib_page_alloc_req(i),
mmu_page_alloc_done_i => mmu_page_alloc_done(i),
mmu_pageaddr_i => mmu_pageaddr_input,
mmu_pageaddr_o => ib_pageaddr_output((i + 1) * c_swc_page_addr_width - 1 downto i * c_swc_page_addr_width),
mmu_set_usecnt_o => ib_set_usecnt(i),
mmu_set_usecnt_done_i => mmu_set_usecnt_done(i),
mmu_usecnt_o => ib_usecnt((i + 1) * c_swc_usecount_width -1 downto i * c_swc_usecount_width),
mmu_nomem_i => mmu_nomem,
-------------------------------------------------------------------------------
-- I/F with Pck's Pages Freeing Module (PPFM)
-------------------------------------------------------------------------------
mmu_force_free_o => ib_force_free(i),
mmu_force_free_done_i => ppfm_force_free_done_to_ib(i),
mmu_force_free_addr_o => ib_force_free_pgaddr((i + 1) * c_swc_page_addr_width - 1 downto i * c_swc_page_addr_width),
-------------------------------------------------------------------------------
-- I/F with Routing Table Unit (RTU)
-------------------------------------------------------------------------------
rtu_rsp_valid_i => rtu_rsp_valid(i),
rtu_rsp_ack_o => rtu_rsp_ack(i),
rtu_dst_port_mask_i => rtu_dst_port_mask((i + 1) * c_swc_num_ports -1 downto i * c_swc_num_ports),
rtu_drop_i => rtu_drop(i),
rtu_prio_i => rtu_prio((i + 1) * c_swc_prio_width -1 downto i * c_swc_prio_width),
-------------------------------------------------------------------------------
-- I/F with Multiport Memory (MPU)
-------------------------------------------------------------------------------
mpm_pckstart_o => ib_pckstart(i),
mpm_pageaddr_o => ib_pageaddr_to_mpm((i + 1) * c_swc_page_addr_width - 1 downto i * c_swc_page_addr_width),
mpm_pagereq_o => ib_pagereq(i),
mpm_pageend_i => mpm_pageend(i),
mpm_data_o => ib_data((i + 1) * c_swc_data_width - 1 downto i * c_swc_data_width),
mpm_ctrl_o => ib_ctrl((i + 1) * c_swc_ctrl_width - 1 downto i * c_swc_ctrl_width),
mpm_drdy_o => ib_drdy(i),
mpm_full_i => mpm_full(i),
mpm_flush_o => ib_flush(i),
-------------------------------------------------------------------------------
-- I/F with Page Transfer Arbiter (PTA)
-------------------------------------------------------------------------------
pta_transfer_pck_o => ib_transfer_pck(i),
pta_transfer_ack_i => pta_transfer_ack(i),
pta_pageaddr_o => ib_pageaddr_to_pta((i + 1) * c_swc_page_addr_width -1 downto i * c_swc_page_addr_width),
pta_mask_o => ib_mask ((i + 1) * c_swc_num_ports -1 downto i * c_swc_num_ports),
pta_prio_o => ib_prio ((i + 1) * c_swc_prio_width -1 downto i * c_swc_prio_width),
pta_pck_size_o => ib_pck_size ((i + 1) * c_swc_max_pck_size_width -1 downto i * c_swc_max_pck_size_width)
);
OUTPUT_BLOCK: swc_output_block
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
-------------------------------------------------------------------------------
-- I/F with Page Transfer Arbiter (PTA)
-------------------------------------------------------------------------------
pta_transfer_data_valid_i=> pta_data_valid(i),
pta_pageaddr_i => pta_pageaddr((i + 1) * c_swc_page_addr_width -1 downto i * c_swc_page_addr_width),
pta_prio_i => pta_prio ((i + 1) * c_swc_prio_width -1 downto i * c_swc_prio_width),
pta_pck_size_i => pta_pck_size((i + 1) * c_swc_max_pck_size_width -1 downto i * c_swc_max_pck_size_width),
pta_transfer_data_ack_o => ob_ack(i),
-------------------------------------------------------------------------------
-- I/F with Multiport Memory (MPM)
-------------------------------------------------------------------------------
mpm_pgreq_o => ob_pgreq(i),
mpm_pgaddr_o => ob_pgaddr((i + 1) * c_swc_page_addr_width -1 downto i * c_swc_page_addr_width),
mpm_pckend_i => mpm_pckend(i),
mpm_pgend_i => mpm_pgend(i),
mpm_drdy_i => mpm_drdy(i),
mpm_dreq_o => ob_dreq(i),
mpm_data_i => mpm_data((i + 1) * c_swc_data_width - 1 downto i * c_swc_data_width),
mpm_ctrl_i => mpm_ctrl((i + 1) * c_swc_ctrl_width - 1 downto i * c_swc_ctrl_width),
-------------------------------------------------------------------------------
-- I/F with Pck's Pages Freeing Module (PPFM)
-------------------------------------------------------------------------------
ppfm_free_o => ob_free(i),
ppfm_free_done_i => ppfm_free_done_to_ob(i),
ppfm_free_pgaddr_o => ob_free_pgaddr((i + 1) * c_swc_page_addr_width -1 downto i * c_swc_page_addr_width),
-------------------------------------------------------------------------------
-- Fabric I/F
-------------------------------------------------------------------------------
rx_sof_p1_o => rx_sof_p1(i),
rx_eof_p1_o => rx_eof_p1(i),
rx_dreq_i => rx_dreq(i),
rx_ctrl_o => rx_ctrl((i + 1) * c_swc_ctrl_width -1 downto i * c_swc_ctrl_width),
rx_data_o => rx_data((i + 1) * c_swc_data_width -1 downto i * c_swc_data_width),
rx_valid_o => rx_valid(i),
rx_bytesel_o => rx_bytesel(i),
rx_idle_o => rx_idle(i),
rx_rerror_p1_o => rx_rerror_p1(i),
rx_terror_p1_i => rx_terror_p1(i),
rx_rabort_p1_i => rx_rabort_p1(i)
);
end generate gen_blocks;
PCK_PAGES_FREEEING_MODULE: swc_multiport_pck_pg_free_module
port map(
clk_i => clk_i,
rst_n_i => rst_n_i,
ib_force_free_i => ib_force_free,
ib_force_free_done_o => ppfm_force_free_done_to_ib,
ib_force_free_pgaddr_i => ib_force_free_pgaddr,
ob_free_i => ob_free,
ob_free_done_o => ppfm_free_done_to_ob,
ob_free_pgaddr_i => ob_free_pgaddr,
ll_read_addr_o => ppfm_read_addr,
ll_read_data_i => ll_data,
ll_read_req_o => ppfm_read_req,
ll_read_valid_data_i => ll_read_valid_data,
mmu_force_free_o => ppfm_force_free,
mmu_force_free_done_i => mmu_force_free_done,
mmu_force_free_pgaddr_o => ppfm_force_free_pgaddr,
mmu_free_o => ppfm_free,
mmu_free_done_i => mmu_free_done,
mmu_free_pgaddr_o => ppfm_free_pgaddr
);
LINKED_LIST: swc_multiport_linked_list
port map(
rst_n_i => rst_n_i,
clk_i => clk_i,
write_i => mpm_write,
write_done_o => ll_write_done,
write_addr_i => mpm_write_addr,
write_data_i => mpm_write_data,
-- not used for the time being
free_i => (others => '0'),
free_done_o => open,
free_addr_i => (others => '0'),
read_pump_read_i => mpm_read_pump_read,
read_pump_read_done_o => ll_read_pump_read_done,
read_pump_addr_i => mpm_read_pump_addr,
free_pck_read_i => ppfm_read_req,
free_pck_read_done_o => ll_read_valid_data,
free_pck_addr_i => ppfm_read_addr,
data_o => ll_data
);
----------------------------------------------------------------------
-- Memory Mangement Unit (MMU)
----------------------------------------------------------------------
MEMORY_MANAGEMENT_UNIT: swc_multiport_page_allocator
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
alloc_i => ib_page_alloc_req,
alloc_done_o => mmu_page_alloc_done,
pgaddr_alloc_o => mmu_pageaddr_input,
set_usecnt_i => ib_set_usecnt,
set_usecnt_done_o => mmu_set_usecnt_done,
usecnt_i => ib_usecnt,
free_i => ppfm_free,
free_done_o => mmu_free_done,
pgaddr_free_i => ppfm_free_pgaddr,
force_free_i => ppfm_force_free,
force_free_done_o => mmu_force_free_done,
pgaddr_force_free_i => ppfm_force_free_pgaddr,
nomem_o => mmu_nomem
);
----------------------------------------------------------------------
-- MultiPort Memory (MPM) [ 1 module]
----------------------------------------------------------------------
MUPTIPORT_MEMORY: swc_packet_mem
port map(
clk_i => clk_i,
rst_n_i => rst_n_i,
-------------------------------------------------------------------------------
-- I/F with Input Block (IB)
-------------------------------------------------------------------------------
wr_pagereq_i => ib_pagereq,
wr_pckstart_i => ib_pckstart,
wr_pageaddr_i => ib_pageaddr_to_mpm,
wr_pageend_o => mpm_pageend,
wr_ctrl_i => ib_ctrl,
wr_data_i => ib_data,
wr_drdy_i => ib_drdy,
wr_full_o => mpm_full,
wr_flush_i => ib_flush,
-------------------------------------------------------------------------------
-- I/F with Output Block
-------------------------------------------------------------------------------
rd_pagereq_i => ob_pgreq,
rd_pageaddr_i => ob_pgaddr,
rd_pageend_o => mpm_pckend,
rd_pckend_o => mpm_pgend,
rd_drdy_o => mpm_drdy,
rd_dreq_i => ob_dreq,
--!!!!!!!!!!
rd_sync_read_i => ob_pgreq, -- TODO ???
--!!!!!!!!!!!!!!!!!!
rd_data_o => mpm_data,
rd_ctrl_o => mpm_ctrl,
write_o => mpm_write,
write_done_i => ll_write_done,
write_addr_o => mpm_write_addr,
write_data_o => mpm_write_data,
read_pump_read_o => mpm_read_pump_read,
read_pump_read_done_i => ll_read_pump_read_done,
read_pump_addr_o => mpm_read_pump_addr,
data_i => ll_data
);
----------------------------------------------------------------------
-- Page Transfer Arbiter [ 1 module]
----------------------------------------------------------------------
TRANSER_ARBITER: swc_pck_transfer_arbiter
port map(
clk_i => clk_i,
rst_n_i => rst_n_i,
-------------------------------------------------------------------------------
-- I/F with Output Block (OB)
-------------------------------------------------------------------------------
ob_data_valid_o => pta_data_valid,
ob_ack_i => ob_ack,
ob_pageaddr_o => pta_pageaddr,
ob_prio_o => pta_prio,
ob_pck_size_o => pta_pck_size,
-------------------------------------------------------------------------------
-- I/F with Input Block (IB)
-------------------------------------------------------------------------------
ib_transfer_pck_i => ib_transfer_pck,
ib_transfer_ack_o => pta_transfer_ack,
ib_busy_o => open,
ib_pageaddr_i => ib_pageaddr_to_pta,
ib_mask_i => ib_mask,
ib_prio_i => ib_prio,
ib_pck_size_i => ib_pck_size
);
end rtl;
-------------------------------------------------------------------------------
-- Title : Pack packets to memory :)
-- Project : WhiteRabbit switch
-------------------------------------------------------------------------------
-- File : swc_packet_mem.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-04-08
-- Last update: 2012-02-02
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Here we enable 'g_num_ports' ports to write and read to/from
-- shared memory. We assume we know the memory page (provided by page
-- allocator/deallocator, another component).
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
-- Packets from each port are written/read to/from memory pumps. Each port has
-- its own write and read pump. The pumps are an intermediate step (buffer)
-- between port and shared memory (Fucking Big SRAM). Each pump has its own
-- time slot to access FB SRAM. The time slot is one cycle. The time slot is
-- granted every 'g_packet_mem_multiply' cycles (regardless it's requested
-- by the pump).
--
-- ** writing **
-- 'g_packet_mem_multiply' number of words written to a pump are saved in
-- FB SRAM (when the access is granted). Writting to a pump can be done
-- regardless of the time slots granted to the pumps. It can be done as long as
-- the pump's buffer (register of g_packet_mem_multiply words) is not full.
-- Provided data (g_packet_mem_multiply words) is written to one FB SRAM
-- word. The address of the word is determined by the provided to the pump
-- pgaddr (page address, which comes from page allocator) and internal page
-- address. When the register being filled in currently will be written to the
-- last word of the page, the rd_pageend_o is high indicating that next page
-- needs to be allocated.
--
-- ** reading **
-- similar to writing. there is a register of g_packet_mem_multiply words
-- (ctrl+data) which are read from FB SRAM in the pump's time slot (one cycle).
-- Each word of the register is made available consequtivelly, so first the
-- LSB word can be read by the port (availability of data is indicated by
-- rd_drdy_o being set to HIGH. Next word can be requested by setting rd_dreq_i
-- HIGH (while the previous word is read).
--
-- If the date which is written to a page by a port does not fill entire
-- input register (the number is not modulo g_packet_mem_multiply), but
-- the port wants to write next data to new page and save the "not-full-input-reg"
-- in the FB SRAM, e.g. new package is to be saved, then wr_flush_i should be
-- set HIGH, it forces the pump to save "not-entirely-full" input register
-- in FB SRAM during the next time slot for this port
--
-------------------------------------------------------------------------------
--
-- Copyright (c) 2010 Tomasz Wlostowski, Maciej Lipinski / CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-04-08 1.0 twlostow Created
-- 2010-10-12 1.1 mlipinsk comments added !!!!!
-- 2012-02-02 2.0 mlipinsk generic-azed
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.CEIL;
use ieee.math_real.log2;
library work;
use work.swc_swcore_pkg.all;
use work.genram_pkg.all;
entity swc_packet_mem is
generic (
g_mem_size : integer ;--:= c_swc_packet_mem_size (in input words: 16 bits)
g_num_ports : integer ;--:= c_swc_num_ports
g_page_num : integer ;--:= c_swc_packet_mem_num_pages
g_page_addr_width : integer ;--:= c_swc_page_addr_width;
g_data_width : integer ;--:= c_swc_data_width
g_ctrl_width : integer ;--:= c_swc_ctrl_width
g_page_size : integer ;--:= c_swc_page_size
-- probably useless with new memory
g_packet_mem_multiply : integer --:= c_swc_packet_mem_multiply
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
---------------------------------------------------------------------------
-- Write ports
---------------------------------------------------------------------------
------------------- writing to the shared memory --------------------------
-- indicates that a port X wants to write page address of the "write" access
wr_pagereq_i : in std_logic_vector(g_num_ports-1 downto 0);
-- indicates the beginning of the package
wr_pckstart_i : in std_logic_vector(g_num_ports-1 downto 0);
-- array of pages' addresses to which ports want to write
wr_pageaddr_i : in std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
-- indicator that the current page is about to be full (the last FB SRAM word
-- is being pumped in currently), after ~g_packet_mem_multiply cycles
-- from the rising edge of this signal this page will finish
wr_pageend_o : out std_logic_vector(g_num_ports -1 downto 0);
-- array of control data from each port to be written to memoroy
wr_ctrl_i : in std_logic_vector(g_num_ports * g_ctrl_width - 1 downto 0);
-- array of data from each port to be written to memory
wr_data_i : in std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
-- data ready - request from each port to write data to port's pump
wr_drdy_i : in std_logic_vector(g_num_ports-1 downto 0);
-- the input register of a pump is full, this means that the pump cannot
-- be written by the port. As soon as the data which is in the input registet
-- is written to FB SRAM memory, the signal goes LOW and writing is possible
wr_full_o : out std_logic_vector(g_num_ports-1 downto 0);
-- request to write the content of pump's input register to FB SRAM memory,
-- thus flash/clean input register of the pump
wr_flush_i : in std_logic_vector(g_num_ports-1 downto 0);
wr_sync_o : out std_logic_vector(g_num_ports -1 downto 0);
------------------- reading from the shared memory --------------------------
-- indicates that a port X wants to write page address of the "read" access
rd_pagereq_i : in std_logic_vector(g_num_ports-1 downto 0);
-- array of pages' addresses from which ports want to read
rd_pageaddr_i : in std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
-- indicates that the page being read is about to finish (the last FB SRAM word
-- is being pumped out currently), after ~g_packet_mem_multiply cycles
-- from the rising edge of this signal this page will finish
rd_pageend_o : out std_logic_vector(g_num_ports -1 downto 0);
-- end of the package, new package start-page-address needs to be provided
-- the best if it is before the last page's word is read
rd_pckend_o : out std_logic_vector(g_num_ports-1 downto 0);
-- data ready to be read
rd_drdy_o : out std_logic_vector(g_num_ports -1 downto 0);
-- request next word (ctrl + data) from the pump
rd_dreq_i : in std_logic_vector(g_num_ports -1 downto 0);
rd_sync_read_i : in std_logic_vector(g_num_ports -1 downto 0);
-- data read from the shared memory
rd_data_o : out std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
-- control data read from the shared memory
rd_ctrl_o : out std_logic_vector(g_num_ports * g_ctrl_width - 1 downto 0);
rd_sync_o : out std_logic_vector(g_num_ports -1 downto 0);
-- pa_free_o : out std_logic_vector(g_num_ports -1 downto 0);
-- pa_free_done_i : in std_logic_vector(g_num_ports -1 downto 0);
-- pa_free_pgaddr_o : out std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
write_o : out std_logic_vector(g_num_ports - 1 downto 0);
write_done_i : in std_logic_vector(g_num_ports - 1 downto 0);
write_addr_o : out std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
write_data_o : out std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
read_pump_read_o : out std_logic_vector(g_num_ports - 1 downto 0);
read_pump_read_done_i : in std_logic_vector(g_num_ports - 1 downto 0);
read_pump_addr_o : out std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
data_i : in std_logic_vector(g_page_addr_width - 1 downto 0)
);
end swc_packet_mem;
architecture rtl of swc_packet_mem is
constant c_pump_width : integer := g_data_width + g_ctrl_width; --c_swc_pump_width
constant g_page_addr_offset_width: integer := integer(CEIL(LOG2(real(g_page_size / g_packet_mem_multiply)))); --c_swc_page_offset_width
constant c_mem_addr_width : integer := g_page_addr_width + g_page_addr_offset_width; --c_swc_packet_mem_addr_width
component generic_ssram_dualport_singleclock
generic (
g_width : natural;
g_addr_bits : natural;
g_size : natural);
port (
data_i : in std_logic_vector (g_width-1 downto 0);
clk_i : in std_logic;
rd_addr_i : in std_logic_vector (g_addr_bits-1 downto 0);
wr_addr_i : in std_logic_vector (g_addr_bits-1 downto 0);
wr_en_i : in std_logic := '1';
q_o : out std_logic_vector (g_width-1 downto 0));
end component;
--
subtype t_pump_data_in is std_logic_vector(c_pump_width-1 downto 0);
subtype t_pump_data_out is std_logic_vector(g_packet_mem_multiply * c_pump_width-1 downto 0);
subtype t_pump_addr is std_logic_vector(c_mem_addr_width - 1 downto 0);
subtype t_pump_page_addr is std_logic_vector(g_page_addr_width - 1 downto 0);
type t_pump_addr_array is array (g_packet_mem_multiply - 1 downto 0) of t_pump_addr;
type t_pump_data_in_array is array (g_packet_mem_multiply - 1 downto 0) of t_pump_data_in;
type t_pump_data_out_array is array (g_packet_mem_multiply - 1 downto 0) of t_pump_data_out;
type t_pump_page_addr_array is array (g_packet_mem_multiply - 1 downto 0) of t_pump_page_addr;
---------------------------------------------------------------------------
------------------ arrays consisting of data from all pumps ---------------
---------------------------------------------------------------------------
-- array of addresses to which each pump wants to write its data (FB SRAM word)
-- in FB SRAM word (page addr + internal addr)
-- *Signal inputed to mux*
signal wr_pump_addr_out : t_pump_addr_array;
-- data pumped in from the ports: array of words (ctrl + data) from all ports
-- *Signal inputed to mux*
signal wr_pump_data_in : t_pump_data_in_array;
-- data outputed by the pump and inputed to FB SRAM,
-- it consists of g_packet_mem_multiply words (ctrl + data) which
-- are written to one FB SRAM word, this is array of such FB SRAM words
-- from all pumps.
-- *Signal inputed to mux*
signal wr_pump_data_out : t_pump_data_out_array;
-- write enable coming from each pump, it needs to be synchronozed with
-- the time slot given to each pump, synch by the pump.
-- *Signal inputed to mux*
signal wr_pump_we : std_logic_vector(g_num_ports-1 downto 0);
-- indicates address of the next page in the packet, it is written to
-- a linked list of addresses
signal wr_pump_ll_data_out :t_pump_page_addr_array;
signal wr_pump_ll_addr_out :t_pump_page_addr_array;
signal wr_pump_ll_wr_req_out : std_logic_vector(g_num_ports-1 downto 0);
signal wr_pump_ll_wr_req_done_in : std_logic_vector(g_num_ports-1 downto 0);
---------------------------------------------------------------------------
---------------------- direct input to FB SRAM (muxed)---------------------
---------------------------------------------------------------------------
-- data currently being written to FB SRAM, depending which pump
-- is granted a time slot
signal ram_wr_data_muxed : std_logic_vector(c_pump_width * g_packet_mem_multiply - 1 downto 0);
-- address to which the data from the given pump is written
signal ram_wr_addr_muxed : std_logic_vector(c_mem_addr_width-1 downto 0);
-- write enable
signal ram_we_muxed : std_logic;
---------------------------------------------------------------------------
---------------------- direct input to Linked List (muxed) ----------------
---------------------------------------------------------------------------
signal ll_write_i : std_logic_vector(g_num_ports - 1 downto 0);
signal ll_write_done_o : std_logic_vector(g_num_ports - 1 downto 0);
signal ll_write_addr_i : std_logic_vector(g_page_addr_width * g_num_ports - 1 downto 0);
signal ll_write_data_i : std_logic_vector(g_page_addr_width * g_num_ports - 1 downto 0);
signal ll_read_pump_read_i : std_logic_vector(g_num_ports - 1 downto 0);
signal ll_read_pump_read_done_o : std_logic_vector(g_num_ports - 1 downto 0);
signal ll_read_pump_addr_i : std_logic_vector(g_page_addr_width * g_num_ports - 1 downto 0);
---------------------------------------------------------------------------
------------ input to all pumps which is demuxed from FB SRAM -------------
---------------------------------------------------------------------------
-- address of the FB SRAM word which is read from FB SRAM from a given pump
signal rd_pump_addr_out : t_pump_addr_array;
-- unused
signal rd_pump_data_in : t_pump_data_out_array;
-- array of outputs from the pumps to the ports
signal rd_pump_data_out : t_pump_data_in_array;
signal rd_pump_ll_addr_out : t_pump_page_addr_array;
signal rd_pump_ll_rd_req_out : std_logic_vector(g_num_ports-1 downto 0);
signal rd_pump_ll_rd_req_done_in : std_logic_vector(g_num_ports-1 downto 0);
---------------------------------------------------------------------------
------------------------- direct output from FB SRAM ----------------------
---------------------------------------------------------------------------
-- data (FB SRAM word) read from the FB SRAM and inputted to the pump
-- which is requesting it
signal ram_rd_data : std_logic_vector(c_pump_width * g_packet_mem_multiply - 1 downto 0);
-- read address muxed from the array of addresses from all the pumps
signal ram_rd_addr_muxed : std_logic_vector(c_mem_addr_width-1 downto 0);
---------------------------------------------------------------------------
------------------------- direct output from Linked List ------------------
---------------------------------------------------------------------------
signal llist_rd_data : std_logic_vector(g_page_addr_width - 1 downto 0);
signal llist_rd_addr_muxed : std_logic_vector(g_page_addr_width-1 downto 0);
---------------------------------------------------------------------------
------------------------- synchronization of pumps ------------------------
---------------------------------------------------------------------------
-- produces a strobe indicating the pump to which current time slot for
-- for writing is assigned (time slot == one cycle)
signal sync_sreg : std_logic_vector(g_packet_mem_multiply-1 downto 0);
-- produces a strobe indicating the pump to which current time slot for
-- for writing is assigned (time slot == one cycle)
signal sync_sreg_rd : std_logic_vector(g_packet_mem_multiply-1 downto 0);
-- used for multiplexing of data in arrays (write data)
-- into *_muxed data inputed into FB SRAM.
-- not necesserely occures in the same time as sync, since e.g. address
-- may be needed advance, etc
signal sync_cntr : integer range 0 to g_packet_mem_multiply-1;
-- used for multiplexing of data in arrays of rd_addr
-- and for demultiplexing of data ouputed by FB SRAM to
-- arrays inputed to pumps
-- not necesserely occures in the same time as sync, since e.g. address
-- may be needed advance, etc
signal sync_cntr_rd : integer range 0 to g_packet_mem_multiply-1;
signal ram_zeros : std_logic_vector(g_packet_mem_multiply * c_pump_width - 1 downto 0);
signal ram_ones : std_logic_vector((g_packet_mem_multiply * c_pump_width+7)/8 - 1 downto 0);
begin -- rtl
ram_zeros <=(others => '0');
ram_ones <=(others => '1');
-- managing synchronization of the pumps, so each pump is given one-cycle
-- time slot in which it can read and write.
-- the sync_sreg produces a strobe to indicate the timeslot
-- synch_cntr produces a number indicating pump number to mux/demux data
sync_gen : process (clk_i, rst_n_i)
begin -- process
if rising_edge(clk_i) then
if(rst_n_i = '0') then
sync_sreg (0) <= '1';
sync_sreg (sync_sreg'length - 1 downto 1) <= (others => '0');
sync_cntr <= g_packet_mem_multiply-1;
-- ML: BUGFIX ?????????
sync_cntr_rd <= 1; -- g_packet_mem_multiply-1;
else
sync_sreg <= sync_sreg(sync_sreg'length-2 downto 0) & sync_sreg(sync_sreg'length-1);
if(sync_cntr = g_packet_mem_multiply-1) then
sync_cntr <= 0;
else
sync_cntr <= sync_cntr + 1;
end if;
if(sync_cntr_rd = g_packet_mem_multiply-1) then
sync_cntr_rd <= 0;
else
sync_cntr_rd <= sync_cntr_rd + 1;
end if;
end if;
end if;
end process;
sync_sreg_rd <= sync_sreg;
rd_sync_o <= sync_sreg(g_num_ports - 1 downto 0);
-- sync_sreg_rd(g_packet_mem_multiply-1 downto 0) <= sync_sreg(1 downto 0) & sync_sreg(g_num_ports-1 downto 2);
-- producing pump output data
merge_ctrl_data_wr : for i in 0 to g_num_ports-1 generate
wr_pump_data_in(i) <= wr_ctrl_i(i * g_ctrl_width + g_ctrl_width - 1 downto i * g_ctrl_width)
& wr_data_i(i * g_data_width + g_data_width - 1 downto i * g_data_width);
end generate merge_ctrl_data_wr;
------------------------------------------------------------------------------------------------------------
------------------------------------- mutiport memory modul --------------------------------------------
------------------------------------------------------------------------------------------------------------
-- write pump: it saves g_packet_mem_multiply words (ctrl + data) into an input register (regardless
-- of the above synch and time slot). As soon as the reg is full (or flush req), it is written to
-- FB SRAM (one word). The pump accepts page number of the FB SRAM to which data shall be written.
-- The pump handles page-internal address. There is one pump for each port.
gen_write_pumps : for i in 0 to g_num_ports-1 generate
WRPUMP : swc_packet_mem_write_pump
generic map(
g_page_addr_width => g_page_addr_width,
g_pump_data_width => c_pump_width,
g_mem_addr_width => c_mem_addr_width,
g_page_addr_offset_width => g_page_addr_offset_width,
-- probably useless with new memory
g_packet_mem_multiply => g_packet_mem_multiply
)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
pgaddr_i => wr_pageaddr_i(g_page_addr_width * i + g_page_addr_width - 1 downto g_page_addr_width * i),
pgreq_i => wr_pagereq_i(i),
pckstart_i => wr_pckstart_i(i),
pgend_o => wr_pageend_o(i),
drdy_i => wr_drdy_i(i),
full_o => wr_full_o(i),
flush_i => wr_flush_i(i),
ll_addr_o => wr_pump_ll_addr_out(i),
ll_data_o => wr_pump_ll_data_out(i),
ll_wr_req_o => wr_pump_ll_wr_req_out(i),
ll_wr_done_i => wr_pump_ll_wr_req_done_in(i),
-- current_page_addr_o => wr_pump_current_page_addr_out(i),
-- next_page_addr_o => wr_pump_next_page_addr_out(i),
-- next_page_addr_we_o => wr_pump_next_page_addr_we_out(i),
sync_i => sync_sreg(i),
d_i => wr_pump_data_in(i),
q_o => wr_pump_data_out(i),
addr_o => wr_pump_addr_out(i),
we_o => wr_pump_we(i));
end generate gen_write_pumps;
-- Muxing of data from each pump (array) into data inputted into FB SRAM.
-- which data is muxed, depends on the current time slot.
ram_write_mux : process(sync_cntr, wr_pump_addr_out, wr_pump_data_out, wr_pump_we)
begin
if(sync_cntr < g_num_ports) then
ram_we_muxed <= wr_pump_we(sync_cntr);
ram_wr_addr_muxed <= wr_pump_addr_out(sync_cntr);
ram_wr_data_muxed <= wr_pump_data_out(sync_cntr);
else
ram_we_muxed <= '0';
ram_wr_data_muxed <= (others => '0');
ram_wr_addr_muxed <= (others => '0');
end if;
end process;
-- The most important part, the shared memory
-- FUCKING_BIG_MEMORY : generic_ssram_dualport_singleclock
-- generic map (
-- g_width => g_packet_mem_multiply * c_pump_width,
-- g_addr_bits => c_mem_addr_width,
-- g_size => g_mem_size / g_packet_mem_multiply)
-- port map (
-- clk_i => clk_i,
-- rd_addr_i => ram_rd_addr_muxed,
-- wr_addr_i => ram_wr_addr_muxed,
-- data_i => ram_wr_data_muxed,
-- wr_en_i => ram_we_muxed,
-- q_o => ram_rd_data);
FUCKING_BIG_MEMORY : generic_dpram
generic map (
g_data_width => g_packet_mem_multiply * c_pump_width,
g_size => (g_mem_size / g_packet_mem_multiply)
)
port map (
-- Port A -- writing
clka_i => clk_i,
bwea_i => ram_ones,
wea_i => ram_we_muxed,
aa_i => ram_wr_addr_muxed,
da_i => ram_wr_data_muxed,
qa_o => open,
-- Port B -- reading
clkb_i => clk_i,
bweb_i => ram_ones,
web_i => '0',
ab_i => ram_rd_addr_muxed,
db_i => ram_zeros,
qb_o => ram_rd_data
);
-- read pump: it reads g_packet_mem_multiply words (ctrl + data) from FB SRAM and makes it
-- available to be read by port (word by wrod, word=ctrl+data). Reading of output register can be
-- done regardless of the synch and time slot. As soon as the reg is empty and more reading is
-- requested by a port, new FB SRAM word is read
-- The pump accepts page number of the FB SRAM from which data shall be read.
-- The pump handles page-internal address. There is one pump for each port.
gen_read_pumps : for i in 0 to g_num_ports-1 generate
RDPUMP : swc_packet_mem_read_pump
generic map(
g_page_addr_width => g_page_addr_width,
g_pump_data_width => c_pump_width,
g_mem_addr_width => c_mem_addr_width,
g_page_addr_offset_width => g_page_addr_offset_width,
-- probably useless with new memory
g_packet_mem_multiply => g_packet_mem_multiply
)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
pgreq_i => rd_pagereq_i(i),
pgaddr_i => rd_pageaddr_i(g_page_addr_width * i + g_page_addr_width - 1 downto g_page_addr_width * i),
pckend_o => rd_pckend_o(i),
pgend_o => rd_pageend_o(i),
drdy_o => rd_drdy_o(i),
dreq_i => rd_dreq_i(i),
sync_read_i => rd_sync_read_i(i),
ll_read_addr_o => rd_pump_ll_addr_out(i),
ll_read_data_i => llist_rd_data,
ll_read_req_o => rd_pump_ll_rd_req_out(i),
ll_read_valid_data_i=> rd_pump_ll_rd_req_done_in(i),
-- free_o => pa_free_o(i),
-- free_done_i => pa_free_done_i(i),
-- free_pgaddr_o => pa_free_pgaddr_o((i + 1)*g_page_addr_width -1 downto i * g_page_addr_width),
-- current_page_addr_o => rd_pump_current_page_addr_out(i),
-- next_page_addr_i => llist_rd_data,
d_o => rd_pump_data_out(i),
sync_i => sync_sreg_rd(i),
addr_o => rd_pump_addr_out(i),
q_i => ram_rd_data);
end generate gen_read_pumps;
-- data from the pump to the ports (demux)
split_ctrl_data_rd : for i in 0 to g_num_ports-1 generate
rd_ctrl_o(i * g_ctrl_width + g_ctrl_width - 1 downto i * g_ctrl_width) <= rd_pump_data_out(i)(g_data_width + g_ctrl_width -1 downto g_data_width);
rd_data_o(i * g_data_width + g_data_width - 1 downto i * g_data_width) <= rd_pump_data_out(i)(g_data_width-1 downto 0);
end generate split_ctrl_data_rd;
-- muxing read address
ram_read_mux : process(sync_cntr_rd, rd_pump_addr_out)
begin
if(sync_cntr_rd < g_num_ports) then
ram_rd_addr_muxed <= rd_pump_addr_out(sync_cntr_rd);
else
ram_rd_addr_muxed <= (others => '0');
end if;
end process;
------------------------------------------------------------------------------------------------------------
------------------------------------- linkded list modul --------------------------------------------
------------------------------------------------------------------------------------------------------------
-- llist_write_mux : process(sync_cntr,wr_pump_next_page_addr_we_out , wr_pump_current_page_addr_out, wr_pump_next_page_addr_out)
-- begin
-- if(sync_cntr < g_num_ports) then
-- llist_we_muxed <= wr_pump_next_page_addr_we_out(sync_cntr);
-- llist_wr_addr_muxed <= wr_pump_current_page_addr_out(sync_cntr);
-- llist_wr_data_muxed <= wr_pump_next_page_addr_out(sync_cntr);
-- else
-- llist_we_muxed <= '0';
-- llist_wr_data_muxed <= (others => '0');
-- llist_wr_addr_muxed <= (others => '0');
-- end if;
-- end process;
--
-- -- muxing read address
-- llist_read_mux : process(sync_cntr_rd, wr_pump_current_page_addr_out)
-- begin
-- if(sync_cntr_rd < g_num_ports) then
-- llist_rd_addr_muxed <= rd_pump_current_page_addr_out(sync_cntr_rd);
-- else
-- llist_rd_addr_muxed <= (others => '0');
-- end if;
-- end process;
--
-- -- The most important part, the shared memory
-- PAGE_INDEX_LINKED_LIST : generic_ssram_dualport_singleclock
-- generic map (
-- g_width => g_page_addr_width,
-- g_addr_bits => g_page_addr_width,
-- g_size => g_mem_size / g_packet_mem_multiply)
-- port map (
-- clk_i => clk_i,
-- rd_addr_i => llist_rd_addr_muxed,
-- wr_addr_i => llist_wr_addr_muxed,
-- data_i => llist_wr_data_muxed,
-- wr_en_i => llist_we_muxed ,
-- q_o => llist_rd_data);
linked_list_data : for i in 0 to g_num_ports-1 generate
ll_write_addr_i (i* g_page_addr_width + g_page_addr_width - 1 downto i * g_page_addr_width) <= wr_pump_ll_addr_out(i);
ll_write_data_i (i* g_page_addr_width + g_page_addr_width - 1 downto i * g_page_addr_width) <= wr_pump_ll_data_out(i);
ll_read_pump_addr_i(i* g_page_addr_width + g_page_addr_width - 1 downto i * g_page_addr_width) <= rd_pump_ll_addr_out(i);
end generate linked_list_data;
ll_read_pump_read_i <= rd_pump_ll_rd_req_out;
rd_pump_ll_rd_req_done_in <= ll_read_pump_read_done_o;
ll_write_i <= wr_pump_ll_wr_req_out;
wr_pump_ll_wr_req_done_in <= ll_write_done_o;
-- LINKED_LIST : swc_multiport_linked_list
-- port map (
-- rst_n_i => rst_n_i,
-- clk_i => clk_i,
--
-- -- IF with write pump
-- write_i => ll_write_i,
-- write_done_o => ll_write_done_o,
-- write_addr_i => ll_write_addr_i,
-- write_data_i => ll_write_data_i,
--
-- -- IF with page allocator
-- free_i => (others =>'0'),
-- free_done_o => open,
-- free_addr_i => (others =>'0'),
--
-- -- IF with read pump
-- read_pump_read_i => ll_read_pump_read_i,
-- read_pump_read_done_o => ll_read_pump_read_done_o,
-- read_pump_addr_i => ll_read_pump_addr_i,
--
-- -- IF with Lost Pck Dealloc (LPD)
-- free_pck_read_i => (others =>'0'),
-- free_pck_read_done_o => open,
-- free_pck_addr_i => (others =>'0'),
--
-- -- output data for all reads
-- data_o => llist_rd_data
-- );
-------------------------------------------------
-- Interface with Linked List
-- [a bit strange naming due to the fact that
-- the LL module was initialy inside packet_mem]
------------------------------------------------
write_o <= ll_write_i;
write_addr_o <= ll_write_addr_i;
write_data_o <= ll_write_data_i;
read_pump_read_o <= ll_read_pump_read_i;
read_pump_addr_o <= ll_read_pump_addr_i;
-- output data for all reads
ll_read_pump_read_done_o <= read_pump_read_done_i;
ll_write_done_o <= write_done_i;
llist_rd_data <= data_i ;
wr_sync_o <= sync_sreg(g_num_ports-1 downto 0);
end rtl;
-------------------------------------------------------------------------------
-- Title : Memory Read Pump
-- Project : WhiteRabbit switch
-------------------------------------------------------------------------------
-- File : swc_packet_mem_read_pump.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-04-08
-- Last update: 2012-02-02
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: This piece of code reads a bunch ('g_packet_mem_multiply'
-- of words = ctrl + data) from the FUCKING BIG SRAM and makes it available
-- for read by port. There is one read_pump for each port. Each pump has its
-- time slot to read from FB SRAM.
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
-- Detailed description:
-- the thing works in the following way:
-- 1) it takes the address (FB SRAM addr) of the page
-- 2) it reads it in its time slot which is one cycle every
-- g_packet_mem_multiply cycles
-- 3) it makes it available on its output (d_o) word by word (in number of
-- g_packet_mem_multiply words, this is how many words is saved in
-- on FB SRAM word)
-- 4) it announces it with 'drdy_o' HIGH
-- 5) the next word is available after setting dreq_i high
--
-- BUGS:
-- 1) does not indicate the end of the package (pckend_o does not work well)
-- but it's not really used by the output_block
-------------------------------------------------------------------------------
--
-- Copyright (c) 2010 Tomasz Wlostowski, Maciej Lipinski / CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-04-08 1.0 twlostow Created
-- 2010-10-12 1.1 mlipinsk comments added !!!!!
-- 2012-02-02 2.0 mlipinsk generic-azed
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.swc_swcore_pkg.all;
entity swc_packet_mem_read_pump is
generic (
g_page_addr_width : integer ;--:= c_swc_page_addr_width;
g_pump_data_width : integer ;--:= c_swc_pump_width
g_mem_addr_width : integer ;--:= c_swc_packet_mem_addr_width
g_page_addr_offset_width : integer ;--:= c_swc_page_offset_width
-- probably useless with new memory
g_packet_mem_multiply : integer --:= c_swc_packet_mem_multiply
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Next page address input strobe (active HI) - loads internal
-- memory address register with the address of new page
pgreq_i : in std_logic;
-- Next page address input (from page allocator)
pgaddr_i : in std_logic_vector(g_page_addr_width - 1 downto 0);
-- end of package
pckend_o : out std_logic;
-- HI indicates that current page is done, and that the parent entity must
-- select another page in following clock cycles (g_packet_mem_multiply
-- 2) if it wants to write more data into the memory
-- ML: BUG : it's assigned directly to the output, that sucks, it should be
-- done through register, I presume
pgend_o : out std_logic;
-- data ready to be read by the host entity
drdy_o : out std_logic;
-- data request (request next word)
dreq_i : in std_logic;
-- used to synchronize first read attempt with synch,
-- in other words, it tells the read_pump that this is the
-- first attempt to read, and the data that is now availabel (some rubbish)
-- is not interesting for us, so itm (reg_out) does not need to be read to
-- the end
-- to be HIGH during first cycle of dreq_i HIGH (and also most often preq_i)
sync_read_i : in std_logic;
-- address in LL SRAM which corresponds to the page address
--current_page_addr_o : out std_logic_vector(g_page_addr_width -1 downto 0);
ll_read_addr_o : out std_logic_vector(g_page_addr_width -1 downto 0);
-- data output for LL SRAM - it is the address of the next page or 0xF...F
-- if this is the last page of the package
--next_page_addr_i : in std_logic_vector(g_page_addr_width - 1 downto 0);
ll_read_data_i : in std_logic_vector(g_page_addr_width - 1 downto 0);
ll_read_req_o : out std_logic;
ll_read_valid_data_i : in std_logic;
-- the data we want: one word= ctrl+data
d_o : out std_logic_vector(g_pump_data_width - 1 downto 0);
-- strobe indicating the time slot for this pump
sync_i : in std_logic;
-- address in FB SRAM from which the FB SRAM word ( g_packet_mem_multiply
-- of words=ctrl+data) is to be read in the pump's time slot
--------------
-- IMPORTANT :
--------------
-- this address output needs to be multiplexed so that it is 'visible' by
-- FBSRAM during the pump's time slot (sync_i is HIGH). It means that
-- the timeslot for reading addr_o by multiplexer is one cycle before sync_i !!!
addr_o : out std_logic_vector(g_mem_addr_width - 1 downto 0);
-- data read from FB SRAM
q_i : in std_logic_vector(g_pump_data_width * g_packet_mem_multiply -1 downto 0)
);
end swc_packet_mem_read_pump;
architecture syn of swc_packet_mem_read_pump is
subtype t_pump_entry is std_logic_vector(g_pump_data_width-1 downto 0);
type t_pump_reg is array (g_packet_mem_multiply-1 downto 0) of t_pump_entry;
-- the register to hold g_packet_mem_multiply words(ctrl+data) read from
-- one FB SRAM word
signal out_reg : t_pump_reg;
-- count the words already read by the host entity
signal cntr : unsigned(3 downto 0);
-- some delaying of synch strobe
signal sync_d0 : std_logic;
signal sync_d1 : std_logic;
-- out_reg not empty yet,
signal reg_not_empty : std_logic;
-- all words in the out_reg have been read by the host entity
signal cntr_full : std_logic;
-- address to be suplied to FB SRAM, consists of the pgaddr and page-internal address
signal mem_addr : std_logic_vector (g_mem_addr_width - 1 downto 0);
-- ... we love VHDL ...
signal allones : std_logic_vector(63 downto 0);
signal zeros : std_logic_vector(63 downto 0);
-- for the condition needed to increase page-internal address
signal advance_addr : std_logic;
-- indicates whether the next FB SRAM word is bo be read and loaded to out_reg
signal load_out_reg : std_logic;
-- seems not used ....
-- signal nothing_read : std_logic;
-- HI indicates that current page is done, and that the parent entity must
-- select another page in following clock cycles (g_packet_mem_multiply
-- 2) if it wants to write more data into the memory
signal pgend : std_logic;
-- page end
signal pckend : std_logic;
signal current_page_addr : std_logic_vector(g_page_addr_width - 1 downto 0);
signal next_page_addr : std_logic_vector(g_page_addr_width - 1 downto 0);
signal ll_read_req : std_logic;
signal reading_pck : std_logic;
signal read_valid : std_logic;
signal pgreq_d0 : std_logic;
begin -- syn
allones <= (others => '1');
zeros <= (others => '0');
-- last word from out_reg read
cntr_full <= '1' when cntr = to_unsigned(g_packet_mem_multiply-1, cntr'length) else '0';
-- reading new FB SRAM word is needed. it happens in the pump's time slot only if :
-- * out_reg is empty (used in case there is no request to read data from the pump ????)
-- * the last word from the out_reg has been read and there host entity wants more !!!)
-- load_out_reg <= '1' when sync_i = '1' and (reg_not_empty = '0' or (cntr_full = '1' and dreq_i = '1')) else '0';
load_out_reg <= '1' when (sync_i = '1' and (reg_not_empty = '0' or (cntr_full = '1' and dreq_i = '1')) and pgreq_d0 = '0' and pgreq_i = '0') else '0';
process (clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
sync_d1 <= '0';
sync_d0 <= '0';
pgreq_d0<= '0';
else
sync_d1 <= sync_d0;
sync_d0 <= sync_i;
pgreq_d0<= pgreq_i;
end if;
end if;
end process;
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
cntr <= (others => '0');
reg_not_empty <= '0';
mem_addr <= (others => '0');
advance_addr <= '0';
-- nothing_read <= '0';
pgend <= '0';
pckend <= '0';
current_page_addr <= (others => '0');
next_page_addr <= (others => '0');
ll_read_req <= '0';
reading_pck <= '0';
read_valid <= '0';
else
if(pgreq_i = '1') then
-- writing FB SRAM web address which consists of page address and page-internal address
mem_addr(g_mem_addr_width-1 downto g_page_addr_offset_width) <= pgaddr_i;
mem_addr(g_page_addr_offset_width-1 downto 0) <= (others => '0');
pgend <= '0';
current_page_addr <= pgaddr_i;
pckend <='0';
reading_pck <='1';
-----------------------------
reg_not_empty <= '0'; -- added by ML
cntr <= (others=>'0');
-----------------------------
--ll_read_req <= '1';
elsif(sync_d1 = '1' and advance_addr = '1' and pgreq_i = '0' and pgreq_d0 = '0') then
-- incrementing address inside the same page
mem_addr(g_page_addr_offset_width-1 downto 0) <= std_logic_vector(unsigned(mem_addr(g_page_addr_offset_width-1 downto 0)) + 1);
-- we are approaching the end of current page. Inform the host entity some
-- cycles in advance.
advance_addr <= '0';
if(mem_addr(g_page_addr_offset_width-1 downto 0) = allones(g_page_addr_offset_width-1 downto 0)) then
if(next_page_addr = allones(g_page_addr_width - 1 downto 0)) then
pckend <= '1';
reading_pck <= '0';
else
mem_addr(g_mem_addr_width-1 downto g_page_addr_offset_width) <= next_page_addr;
mem_addr(g_page_addr_offset_width-1 downto 0) <= (others => '0');
end if;
pgend <= '1';
end if;
if(mem_addr(g_page_addr_offset_width-1 downto 0) = zeros(g_page_addr_offset_width-1 downto 0)) then
current_page_addr <= mem_addr(g_mem_addr_width-1 downto g_page_addr_offset_width);
pgend <= '0';
-- start requesting next address
if(reading_pck = '1') then
ll_read_req <= '1';
end if;
end if;
end if;
-- we want to read next FB SRAM word and laod it into out_reg (this s our
-- time slot
if(load_out_reg = '1' and pckend = '0') then
reg_not_empty <= '1';
advance_addr <= '1';
-- next_page_addr <= next_page_addr_i;
for i in 0 to g_packet_mem_multiply-1 loop
-- reading the word and putting it into out_reg array
out_reg (i) <= q_i(g_pump_data_width * (i+1) - 1 downto g_pump_data_width * i);
end loop;
-- we read all the words from out_reg, we want more but it's not
-- our time slot yet, so we indicate with reg_not_empty that
-- in the next time slot read from FB SRAM should be done
elsif(sync_i = '0' and cntr_full = '1' and dreq_i = '1') then
reg_not_empty <= '0';
end if;
-- request for the next word from out_reg, increment the counter
if(dreq_i = '1' and reg_not_empty = '1') then
if(sync_read_i = '1') then
reg_not_empty <= '0';
cntr <= (others=>'0');
else
cntr <= cntr + 1;
end if;
-- we don't load new stuff from the FB SRAM, so
-- this is normal situation, this means that
-- the currently available word has been read and
-- we want to provide new word to the outside word
-- so we shift right the words in the array
if(load_out_reg = '0') then
for i in 1 to g_packet_mem_multiply-1 loop
out_reg (i-1) <= out_reg(i);
end loop;
out_reg(g_packet_mem_multiply-1) <= (others => 'X');
end if;
end if;
if(ll_read_valid_data_i = '1' ) then
next_page_addr <= ll_read_data_i;
ll_read_req <= '0';
end if;
-- if(dreq_i = '1' and reg_not_empty = '1' and load_out_reg = '0') then
if(reg_not_empty = '1' and load_out_reg = '0') then
read_valid <= '1';
elsif(load_out_reg = '1' and pckend = '0') then
read_valid <= '1';
else
read_valid <= '0';
end if;
end if;
end if;
end process;
drdy_o <= reg_not_empty and read_valid;
addr_o <= mem_addr;
d_o <= out_reg (0);
pgend_o <= pgend;
pckend_o <= pckend;
ll_read_addr_o <= current_page_addr; -- current_page_addr_o <= current_page_addr;
ll_read_req_o <= ll_read_req;
end syn;
-------------------------------------------------------------------------------
-- Title : Memory Write Pump
-- Project : WhiteRabbit switch
-------------------------------------------------------------------------------
-- File : swc_packet_mem_write_pump.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-04-08
-- Last update: 2012-02-02
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Collectes data (words of ctrl+data seq) from one port and
-- pumps (saves) sequence of such data to one word of SRAM memory with the
-- page address allocated by mutiport memory allocator. The access to
-- SSRAM is shared equally between many such pumps, each pump represents
-- one port.
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
-- A pump works in the following way:
-- 1) it collects data from a port, data can be written continuously.
-- - data consits of a word of ctrl + data seq
-- - one word can be written at one clock cycle, in such case drdy_i is
-- - constantly HIGH
-- 2) if entire "vector" of data words is collected ('g_packet_mem_multiply'
-- number of data words), such a vector is written to SSRAM to one word:
-- - the dats is written to SRAM memory address = page_addr + offset
-- - each "memory page" (indicated by page_addr) consists of a few
-- SRAM consecutive addresses
-- 3) when the vector to be written to the last address of the page is being
-- filled in, the 'pend_o' indicates that the end of the page
--
-- Each pump has its 'time slot' (one cycle) to read/write from/to
-- *FUCKING BIG SRAM (FB SRAM)*. The access is granted to each pump in sequence:
-- 1,2,3...(g_packet_mem_multiply - 1). The access is multiplexed
-- between the pumps.
--
-- If we want to write to the FB SRAM vector not fully filled in with data,
-- we can use 'flush_i'. High stribe on flush input enforces the pump to
-- behave as if it was full and the write to FB SRAM was needed in the
-- next available 'time slot'.
--
-------------------------------------------------------------------------------
--
-- Copyright (c) 2010 Tomasz Wlostowski, Maciej Lipinski / CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-- -------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-04-08 1.0 twlostow Created
-- 2010-10-12 1.1 mlipinsk comments added !!!!!
-- 2010-10-18 1.2 mlipinsk clearing register
-- 2010-11-24 1.3 mlipinsk adding main FSM !
-- 2012-02-02 2.0 mlipinsk generic-azed
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.log2;
use ieee.math_real.ceil;
--use std.textio.all;
library work;
use work.swc_swcore_pkg.all;
--use work.pck_fio.all;
entity swc_packet_mem_write_pump is
generic (
g_page_addr_width : integer ;--:= c_swc_page_addr_width;
g_pump_data_width : integer ;--:= c_swc_pump_width
g_mem_addr_width : integer ;--:= c_swc_packet_mem_addr_width
g_page_addr_offset_width : integer ;--:= c_swc_page_offset_width
-- probably useless with new memory
g_packet_mem_multiply : integer --:= c_swc_packet_mem_multiply
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-------------------------------------------------------------------------------
-- paging interface
-------------------------------------------------------------------------------
-- Next page address input (from page allocator)
pgaddr_i : in std_logic_vector(g_page_addr_width-1 downto 0);
-- Next page address input strobe (active HI) - loads internal
-- memory address register with the address of new page
pgreq_i : in std_logic;
-- HI indicates that current page is done, and that the parent entity must
-- select another page in following clock cycles (g_packet_mem_multiply
-- 2) if it wants to write more data into the memory
pgend_o : out std_logic;
-- it indicates the start of a package, it need to be high when writing the
-- first data of the new package
pckstart_i: in std_logic;
-------------------------------------------------------------------------------
-- data channel interface
-------------------------------------------------------------------------------
-- data input. data consists of 'c_swc_ctrl_width' of control data and
-- 'c_swc_data_width' of data
-- sequence (of 'g_packet_mem_multiply' number) of such data is saved
-- in one SRAM memory word at the pgaddr_i
d_i : in std_logic_vector(g_pump_data_width -1 downto 0);
-- data input ready strobe (active HI). Clocks in the data. drdy_i cannot
-- be asserted when full_o is active.
drdy_i : in std_logic;
-- input register full (active HI). Indicates that the memory input
-- register is full ('g_packet_mem_multiply' words have been written)
-- it will go back to 0 as soon as the memory input reg is synced to the
-- shared memory.
full_o : out std_logic;
-- Memory input register flush (active HI). Forces a flush of memory input
-- register to the shared memory on the next sync pulse even if the number
-- of words clocked into the pump is less than g_packet_mem_multiply.
flush_i : in std_logic;
-------------------------------------------------------------------------------
-- Linked List of page addresses (LL SRAM) interface
-------------------------------------------------------------------------------
-- address in LL SRAM which corresponds to the page address
ll_addr_o : out std_logic_vector(g_page_addr_width -1 downto 0);
-- data output for LL SRAM - it is the address of the next page or 0xF...F
-- if this is the last page of the package
ll_data_o : out std_logic_vector(g_page_addr_width - 1 downto 0);
-- request to write to Linked List, should be high until
-- ll_wr_done_i indicates successfull write
ll_wr_req_o : out std_logic;
ll_wr_done_i : in std_logic;
-------------------------------------------------------------------------------
-- shared memory (FB SRAM) interface
-- The access is multiplexed with other pumps. Each pump has a one-cycle-timeslot
-- to access the FB SRAM every 'g_packet_mem_multiply' cycles.
-------------------------------------------------------------------------------
-- synchronization pulse. HI indicates a time-slot assigned to this write pump.
-- One cycle after reception of pulse on sync_i, the pump must provide valid
-- values of addr_o, q_o and we_o, eventually commiting the contents of memory
-- input register to the shared mem block.
sync_i : in std_logic;
-- address output for shared memory block
addr_o : out std_logic_vector(g_mem_addr_width -1 downto 0);
-- data output for shared memory block
q_o : out std_logic_vector(g_pump_data_width * g_packet_mem_multiply - 1 downto 0);
-- write strobe output for shared memory block (FB SRAM), multiplexed with other pumps
we_o : out std_logic
);
end swc_packet_mem_write_pump;
architecture rtl of swc_packet_mem_write_pump is
-- word counter (word consists of ctrl + data), counts words in the 'in_reg' register
signal cntr : unsigned(3 downto 0);
subtype t_pump_entry is std_logic_vector(g_pump_data_width-1 downto 0);
type t_pump_reg is array (g_packet_mem_multiply-1 downto 0) of t_pump_entry;
-- memory input register organized as an array of (g_packet_mem_multiply) input
-- wordsn (ctrl + data).
signal in_reg : t_pump_reg;
-- indicates that in_reg is full, 'g_packet_mem_multiply' words has been written)
signal reg_full : std_logic;
-- memory register, consists of 'pg_addr' and in-page count (the number of inside
-- page FB SRAM words is: (c_swc_page_size / g_packet_mem_multiply)
signal mem_addr : std_logic_vector (g_mem_addr_width - 1 downto 0);
-- FB SRAM write enable (internal). Translate into write request to FB SRAM.
-- the access is multiplexed, so the write request has to be issued in this
-- pump's time slot.
signal we_int : std_logic;
-- stores the flush request from 'hihger up'
signal flush_reg : std_logic;
-- combinatorial signal: attempt to write when counter is max
signal write_on_sync : std_logic;
-- indicates that the 'page' is full, so the internal
-- FB SRAM address counter is 1..1
signal cntr_full : std_logic;
-- we all love VHDL :)
signal allones : std_logic_vector(63 downto 0);
--signal zeros : std_logic_vector(63 downto 0);
-- HI indicates that current page is done, and that the parent entity must
-- select another page in following clock cycles (g_packet_mem_multiply
-- 2) if it wants to write more data into the memory
signal pgend : std_logic;
-- start of package
signal pckstart : std_logic;
-- signal before_sync : std_logic;
--=================================================================================
-- address in LL SRAM which corresponds to the page address
signal current_page_addr_int : std_logic_vector(g_page_addr_width -1 downto 0);
-- stored during FSM cycle (next->eop), this is needed for the last page of the pck
-- in such case we need to remember it, otherwise we have problems
signal current_page_addr_fsm : std_logic_vector(g_page_addr_width -1 downto 0);
signal previous_page_addr_int : std_logic_vector(g_page_addr_width -1 downto 0);
-- internal
signal ll_write_addr : std_logic_vector(g_page_addr_width - 1 downto 0);
-- internal
signal ll_write_data : std_logic_vector(g_page_addr_width - 1 downto 0);
-- indicatest that the next address shall be writtent to
-- Linked List SRAM
signal ll_wr_req : std_logic;
signal ll_idle : std_logic;
signal ll_wr_done_reg : std_logic;
signal no_next_page_addr: std_logic;
signal writing_last_page : std_logic;
type t_state is (IDLE, WR_NEXT, WR_EOP, WR_LAST_EOP, WR_TRANS_EOP);
signal state : t_state;
type t_state_write is (S_IDLE, S_READ_DATA,
S_READ_LAST_DATA_WORD,
S_WRITE_DATA,
S_WRITE_ON_FLUSH,
S_FLUSH,
S_WAIT_WRITE,
S_WAIT_LL_READY,
S_NASTY_WAIT);
signal state_write : t_state_write;
-- signal cnt_last_word : std_logic;
-- signal next_page_loaded : std_logic;
signal pgreq_reg : std_logic;
signal pckstart_reg : std_logic;
signal pgreq_or : std_logic;
signal pckstart_or : std_logic;
signal sync_d : std_logic_vector(g_packet_mem_multiply - 1 downto 0);
-- signal nasty_wait_full : std_logic;
begin -- rtl
-- VHDL sucks...
allones <= (others => '1');
-- zeros <= (others => '0');
write_on_sync <= '1' when (cntr = to_unsigned(0,cntr'length)) else '0';
synch_delay : process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
sync_d <= (others =>'0');
else
sync_d(0) <= sync_i;
for i in 1 to g_packet_mem_multiply-1 loop
sync_d(i) <= sync_d(i - 1);
end loop;
end if;
end if;
end process;
-- before_sync <= sync_d(g_packet_mem_multiply - 2);
write_fsm : process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
we_int <= '0';
reg_full <= '0';
-- cnt_last_word <='0';
else
-- main finite state machine
case state_write is
when S_IDLE =>
if(drdy_i = '1') then
state_write <= S_READ_DATA;
end if;
when S_READ_DATA =>
if(flush_i = '1') then
state_write <= S_FLUSH;
reg_full <= '1';
elsif(cntr = to_unsigned(g_packet_mem_multiply - 2,cntr'length) and drdy_i ='1') then
state_write <= S_READ_LAST_DATA_WORD;
-- cnt_last_word <= '1';
end if;
when S_READ_LAST_DATA_WORD =>
if( sync_i = '1') then
if(pgend = '1' and drdy_i = '1') then -- see screenshot: swcore-writepump-p1
reg_full <= '1';
state_write <= S_WAIT_WRITE;
-- cnt_last_word <= '0';
-- during the last address of the page, the Linked list is being written, so we need
-- to wait for it to finish
elsif(mem_addr(g_page_addr_offset_width-1 downto 0) = allones(g_page_addr_offset_width-1 downto 0) and ll_idle = '0' ) then
state_write <= S_WAIT_LL_READY;
reg_full <= '1';
elsif(drdy_i ='1') then
state_write <= S_WRITE_DATA;
we_int <= '1';
reg_full <= '0';
-- cnt_last_word <= '0';
elsif(flush_i = '1') then
state_write <= S_WRITE_DATA;
we_int <= '1';
reg_full <= '0';
else
state_write <= S_NASTY_WAIT;
we_int <= '0';
reg_full <= '0';
-- cnt_last_word <= '0';
end if;
-- elsif(drdy_i = '1' and flush_i ='1') then
--
-- state_write <= S_WRITE_DATA;
-- we_int <= '1';
-- reg_full <= '0';
-- cnt_last_word <= '0';
--
else -- synch_i = '0'
-- if(cntr = to_unsigned(g_packet_mem_multiply -1,cntr'length) and drdy_i = '1') then
--
--==== needs test - start ===
if (flush_i = '1') then -- when we flush the last word
state_write <= S_FLUSH;
reg_full <= '1';
elsif( drdy_i = '1') then
--==== needs test - end ===
reg_full <= '1';
state_write <= S_WAIT_WRITE;
-- cnt_last_word <= '0';
--==== needs test - start ===
end if;
--==== needs test - end ===
--
-- else
--
--- reg_full <= '0';
-- state_write <= S_NASTY_WAIT;
-- cnt_last_word <= '0';
-- end if;
end if;
when S_NASTY_WAIT =>
if(drdy_i = '1' and sync_i = '1' and cntr = to_unsigned(g_packet_mem_multiply -1,cntr'length)) then
state_write <= S_WRITE_DATA;
we_int <= '1';
reg_full <= '0';
-- cnt_last_word <= '0';
elsif(drdy_i = '1' and sync_i = '0' ) then
reg_full <= '1';
state_write <= S_WAIT_WRITE;
-- cnt_last_word <= '0';
end if;
when S_WRITE_DATA =>
we_int <= '0';
reg_full <= '0';
-- flushed precisely when writing data
-- when there is new data available
-- in such case, there will be one word
-- to write in new page
if(drdy_i = '1' and flush_i ='1') then
state_write <= S_FLUSH;
reg_full <= '1';
-- NORMAL CASE: writing when new data available
elsif(drdy_i = '1' and flush_i ='0') then
state_write <= S_READ_DATA;
elsif(drdy_i = '1' and ll_idle = '0') then
state_write <= S_WAIT_LL_READY;
reg_full <= '1';
-- flush when there is no new data, it means that
-- the data that is being written is the last
elsif(drdy_i = '0' and flush_i ='1') then
state_write <= S_IDLE;
else
-- state_write <= S_IDLE;
state_write <= S_READ_DATA;
end if;
when S_FLUSH =>
if(sync_i = '1' and pgend = '0') then
state_write <= S_WRITE_DATA;
reg_full <= '0';
we_int <= '1';
end if;
when S_WAIT_WRITE =>
if(sync_i = '1' and pgend = '0') then
if(mem_addr(g_page_addr_offset_width-1 downto 0) = allones(g_page_addr_offset_width-1 downto 0) and ll_idle = '0') then
state_write <= S_WAIT_LL_READY;
reg_full <= '1';
elsif(drdy_i = '1' or write_on_sync = '1' or flush_reg = '1') then
-- else
state_write <= S_WRITE_DATA;
we_int <= '1';
reg_full <= '0';
end if;
end if;
when S_WAIT_LL_READY =>
if(drdy_i = '0' and ll_idle = '1') then
state_write <= S_WRITE_DATA;
we_int <= '1';
reg_full <= '0';
-- cnt_last_word <= '0';
end if;
when others =>
state_write <= S_IDLE;
end case;
end if;
end if;
end process;
-- cntr_full <= '1' when cntr = to_unsigned(g_packet_mem_multiply-1, cntr'length) else '0';
process(clk_i, rst_n_i)
begin
if rising_edge (clk_i) then
if(rst_n_i = '0') then
cntr <= (others => '0');
mem_addr <= (others => '0');
pgend <= '0';
-- next_page_loaded <= '0';
--pckstart <= '0';
for i in 0 to g_packet_mem_multiply-1 loop
in_reg(i) <= (others => '0');
end loop; -- i
pckstart_reg <= '0';
pgreq_reg <= '0';
flush_reg <='0';
else
if(flush_i = '1' and sync_i = '0') then
flush_reg <= '1';
elsif(sync_i = '1' and flush_reg ='1') then
flush_reg <= '0';
end if;
if(pgreq_i = '1') then
pgend <= '0';
elsif(mem_addr(g_page_addr_offset_width-1 downto 0) = allones(g_page_addr_offset_width-1 downto 0) ) then
if(cntr = to_unsigned(g_packet_mem_multiply -1,cntr'length) and sync_i = '1' and drdy_i = '1') then
pgend <= '1';
elsif(write_on_sync = '1' and sync_i = '1') then
pgend <= '1';
end if;
end if;
if(pgreq_i = '1') then
mem_addr(g_mem_addr_width-1 downto g_page_addr_offset_width) <= pgaddr_i;
mem_addr(g_page_addr_offset_width-1 downto 0) <= (others => '0');
-- pgend <= '0';
-- next_page_loaded <= '1';
elsif(state_write = S_WRITE_DATA) then
if(mem_addr(g_page_addr_offset_width-1 downto 0) = allones(g_page_addr_offset_width-1 downto 0) ) then
-- pgend <= '1';
-- next_page_loaded <= '0';
else
mem_addr(g_page_addr_offset_width-1 downto 0) <= std_logic_vector(unsigned(mem_addr(g_page_addr_offset_width-1 downto 0)) + 1);
end if;
end if;
if(drdy_i = '1') then
-- if( cntr = 0 and pckstart_i = '1') then
-- pckstart <= '1';
-- end if;
-- if new address is set when the previous is
-- being written to Linked List, we need to remember
-- this to be able to come to it later
if(pgreq_i ='1' and state /= IDLE ) then
pgreq_reg <='1';
end if;
if(pckstart_i = '1' and state /=IDLE ) then
pckstart_reg <= '1';
end if;
for i in 0 to g_packet_mem_multiply-1 loop
if(i >= to_integer(cntr)) then
in_reg(i) <= (others => '0');
end if;
end loop;
in_reg(to_integer(cntr)) <= d_i;
-- wrap around the 'in_reg' indicating that the reg is full to the host
-- entity
-- if(state_write = S_IDLE) then
-- cntr <= (others =>'1');
-- elsif(cntr = to_unsigned(g_packet_mem_multiply -1,cntr'length)) then
if(cntr = to_unsigned(g_packet_mem_multiply -1,cntr'length)) then
cntr <= (others => '0');
elsif((state_write = S_READ_LAST_DATA_WORD) and sync_i = '1') then
cntr <= (others => '0');
-- elsif(reg_full = '1') then
-- cntr <= (others => '0');
else
cntr <= cntr + 1;
end if;
else
--if(((state_write = S_FLUSH or state_write = S_WAIT_LL_READY ) or flush_i = '1') and sync_i = '1') then
if(((state_write = S_FLUSH or state_write = S_WAIT_LL_READY) and sync_i = '1') or (flush_i = '1')) then --change by Tom
cntr <= (others => '0');
end if;
end if;
if(ll_wr_done_i = '1') then
pckstart_reg <= '0';
pgreq_reg <='0';
end if;
end if;
end if;
end process;
pg : process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
current_page_addr_int <= (others => '0');
previous_page_addr_int <= (others => '0');
else
if(pgreq_i = '1') then
current_page_addr_int <= pgaddr_i;
end if;
if(ll_wr_done_i = '1') then
previous_page_addr_int <= current_page_addr_int;
end if;
end if;
end if;
end process;
-- IMPORTANT, see below WR_EOP
pgreq_or <= pgreq_i or pgreq_reg;
pckstart_or <= pckstart_i or pckstart_reg;
fsm : process(clk_i, rst_n_i)
-- variable l:line;
-- file fout:text open write_mode is "stdout" ;
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
state <= IDLE;
ll_write_data <=(others =>'0');
ll_write_addr <=(others =>'0');
ll_wr_req <='0';
current_page_addr_fsm <=(others =>'0');
else
-- main finite state machine
case state is
when IDLE =>
--fprint(fout, l, "Jou, ziom!\n");
--if((pgreq_i = '1') and (pckstart = '0') and (pckstart_i = '0')) then
if((pgreq_or = '1') and (pckstart_or = '0') ) then
-- normal case: load new page within the package (not the
-- beginning of the package)
-- this will not happen during the staart of the frame
-- within the frame, pgaddr_i will have the appripriate value
state <= WR_NEXT;
ll_write_data <= pgaddr_i;
ll_write_addr <= previous_page_addr_int;
-- we remember the current (new address)
-- just in case, the pck finishes during NEXT OR EOP state
-- and new page is set, or just new page is set
current_page_addr_fsm <= pgaddr_i;
ll_wr_req <= '1';
elsif((pgreq_or = '1') and (pckstart_or = '1')) then
-- first package, page provided at the same time as pckstart_i strobe
-- so we remember the address from input
--if((pgreq_i = '1') and (pckstart = '0') and (pckstart_i = '1')) then
state <= WR_EOP;
ll_write_data <= (others =>'1');
ll_write_addr <= pgaddr_i;
ll_wr_req <= '1';
end if;
-- page provided not in the first cycle of the new package
--if((pgreq_i = '1') and (pckstart = '1') and (pckstart_i = '0')) then
-- state <= WR_EOP;
-- ll_write_data <= (others =>'1');
-- ll_write_addr <= pgaddr_i;
-- ll_wr_req <= '1';
--end if;
when WR_NEXT =>
if (ll_wr_done_i = '1') then
if((pgreq_or = '1') and (pckstart_or = '1') ) then
-- this means that the pck finished during NEXT state
--
state <= WR_LAST_EOP;
ll_write_data <= (others =>'1');
--ll_write_addr <= current_page_addr_int;
ll_write_addr <= current_page_addr_fsm;
ll_wr_req <= '1';
elsif((pgreq_or = '1') and (pckstart_or = '0') ) then
-- this means that new page was set during NEXT state
--
state <= WR_TRANS_EOP;
ll_write_data <= (others =>'1');
--ll_write_addr <= current_page_addr_int;
ll_write_addr <= current_page_addr_fsm;
ll_wr_req <= '1';
else
state <= WR_EOP;
ll_write_data <= (others =>'1');
--ll_write_addr <= current_page_addr_int;
ll_write_addr <= current_page_addr_fsm;
ll_wr_req <= '1';
end if;
end if;
when WR_EOP =>
if (ll_wr_done_i = '1') then
if((pgreq_or = '1') and (pckstart_or = '0') ) then
-- this foresees the situation when new page was set
-- while the linked list was being written, so
-- we don't go to idle, but write LL again.
-- in theory, should not get here, because the
-- writing FSM, waits for ll_FSM to be IDLE
state <= WR_NEXT;
ll_write_data <= pgaddr_i;
ll_write_addr <= previous_page_addr_int;
ll_wr_req <= '1';
elsif((pgreq_or = '1') and (pckstart_or = '1')) then
-- this foresees quite often situation when the
-- address of previous pck is written to LL while
-- new pck's first page is already being set,
-- so we remember the request and set the page as soon
-- as previous' pck's operations to LL are finished
state <= WR_EOP;
ll_write_data <= (others =>'1');
ll_write_addr <= pgaddr_i;
ll_wr_req <= '1';
else
-- normal functioning
state <= IDLE;
ll_write_data <= (others =>'0');
ll_write_addr <= (others =>'0');
ll_wr_req <= '0';
end if;
end if;
when WR_LAST_EOP =>
if (ll_wr_done_i = '1') then
state <= WR_EOP;
ll_write_data <= (others =>'1');
ll_write_addr <= current_page_addr_int;
ll_wr_req <= '1';
end if;
when WR_TRANS_EOP =>
if (ll_wr_done_i = '1') then
state <= WR_NEXT;
ll_write_data <= current_page_addr_int;
ll_write_addr <= previous_page_addr_int;
end if;
when others =>
state <= IDLE;
end case;
end if;
end if;
end process;
-- nasty_wait_full <= '1' when (state_write = S_NASTY_WAIT) else '0';
ll_idle <= '1' when (state = IDLE) else '0';
we_o <= we_int;
full_o <= reg_full;
--
-- (((reg_full -- obvous
-- or
-- (cnt_last_word and drdy_i)
-- or
-- (nasty_wait_full and drdy_i))
-- and
-- (not sync_i)) or(pgend and sync_i));-- or (sync_i and (not drdy_i)));-- and not before_sync;
--addr_o <= pgaddr_i & zeros (g_page_addr_offset_width-1 downto 0) when (we_int = '1' and pgreq_i = '1') else mem_addr;
addr_o <= mem_addr;
pgend_o <= pgend;
gen_q1 : for i in 0 to g_packet_mem_multiply-1 generate
q_o(g_pump_data_width * (i+1) - 1 downto g_pump_data_width * i) <= in_reg(i);
end generate gen_q1;
ll_addr_o <= ll_write_addr;
ll_data_o <= ll_write_data;
ll_wr_req_o <= ll_wr_req;
end rtl;
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