Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
wr-switch-hdl
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
white-rabbit
wr-switch-hdl
Commits
4e67ab38
Commit
4e67ab38
authored
Mar 26, 2012
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
modules/wrsw_swcore: removed obsolete files
parent
05efcd1e
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
0 additions
and
2653 deletions
+0
-2653
Makefile
modules/wrsw_swcore/Makefile
+0
-30
l0_init.mif
modules/wrsw_swcore/l0_init.mif
+0
-25
swc_core_signle_port.vhd
modules/wrsw_swcore/swc_core_signle_port.vhd
+0
-641
swc_packet_mem.vhd
modules/wrsw_swcore/swc_packet_mem.vhd
+0
-668
swc_packet_mem_read_pump.vhd
modules/wrsw_swcore/swc_packet_mem_read_pump.vhd
+0
-385
swc_packet_mem_write_pump.vhd
modules/wrsw_swcore/swc_packet_mem_write_pump.vhd
+0
-904
No files found.
modules/wrsw_swcore/Makefile
deleted
100644 → 0
View file @
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
modules/wrsw_swcore/l0_init.mif
deleted
100644 → 0
View file @
05efcd1e
-- 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;
modules/wrsw_swcore/swc_core_signle_port.vhd
deleted
100644 → 0
View file @
05efcd1e
-------------------------------------------------------------------------------
-- 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
;
modules/wrsw_swcore/swc_packet_mem.vhd
deleted
100644 → 0
View file @
05efcd1e
-------------------------------------------------------------------------------
-- 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
;
modules/wrsw_swcore/swc_packet_mem_read_pump.vhd
deleted
100644 → 0
View file @
05efcd1e
-------------------------------------------------------------------------------
-- 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
;
modules/wrsw_swcore/swc_packet_mem_write_pump.vhd
deleted
100644 → 0
View file @
05efcd1e
-------------------------------------------------------------------------------
-- 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
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment