From 8b83d05606fd09fac657960beb5fb0fad76615ef Mon Sep 17 00:00:00 2001 From: Erik Kooistra <kooistra@astron.nl> Date: Thu, 8 Jan 2015 07:03:49 +0000 Subject: [PATCH] SVN copied common_mem_pkg.vhd from $UNB to $RADIOHDL. --- libraries/base/common/hdllib.cfg | 2 +- .../base/common/src/vhdl/common_mem_pkg.vhd | 188 ++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 libraries/base/common/src/vhdl/common_mem_pkg.vhd diff --git a/libraries/base/common/hdllib.cfg b/libraries/base/common/hdllib.cfg index b5610d4767..c8cf1ec89b 100644 --- a/libraries/base/common/hdllib.cfg +++ b/libraries/base/common/hdllib.cfg @@ -9,7 +9,7 @@ build_dir_synth = $HDL_BUILD_DIR synth_files = $UNB/Firmware/modules/common/src/vhdl/common_pkg.vhd $UNB/Firmware/modules/common/src/vhdl/common_str_pkg.vhd - $UNB/Firmware/modules/common/src/vhdl/common_mem_pkg.vhd + src/vhdl/common_mem_pkg.vhd $UNB/Firmware/modules/common/src/vhdl/common_field_pkg.vhd $UNB/Firmware/modules/common/src/vhdl/common_lfsr_sequences_pkg.vhd src/vhdl/common_interface_layers_pkg.vhd diff --git a/libraries/base/common/src/vhdl/common_mem_pkg.vhd b/libraries/base/common/src/vhdl/common_mem_pkg.vhd new file mode 100644 index 0000000000..d8395d8e02 --- /dev/null +++ b/libraries/base/common/src/vhdl/common_mem_pkg.vhd @@ -0,0 +1,188 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2009 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE work.common_pkg.ALL; + +PACKAGE common_mem_pkg IS + + -- Memory access + -- + -- Assume the MM bus is for a 32 bit processor, therefore on the processor + -- side of a memory peripheral typcially use c_word_w = 32 for the address + -- and data fields in the MM bus records. However the MM bus can also be used + -- on the user side of a memory peripheral and there the data width should + -- not be limited by the processor type but rather by the maximum user data + -- width on the streaming interface. + -- + -- The std_logic_vector widths in the record need to be defined, because in + -- a record they can not be unconstrained. A signal that needs less address + -- or data width simply leaves the unused MSbits at 'X'. The actually used + -- width of a memory gets set via a generic record type t_c_mem. + -- + -- The alternative is to not put the std_logic_vector elements in the record, + -- and declare them seperately, however then the compact representation that + -- records provide gets lost, because the record then only contains wr_en and + -- rd_en. Another alternative is to define the address as a integer and the + -- data as an integer. However this limits their range to 32 bit numbers, + -- which can be too few for data. + + -- Do not change these widths, because c_word_w just fits in a VHDL INTEGER + -- Should wider address range or data width be needed, then define a new + -- record type t_mem_bus for that with sufficient widths. + + -- Choose smallest maximum slv lengths that fit all use cases, because unconstrained record fields slv is not allowed + CONSTANT c_mem_address_w : NATURAL := 32; -- address range (suits 32-bit processor) + CONSTANT c_mem_data_w : NATURAL := 72; -- data width (suit up to 8 bytes, that can also be 9 bit bytes) + CONSTANT c_mem_address_sz : NATURAL := c_mem_address_w/c_byte_w; + CONSTANT c_mem_data_sz : NATURAL := c_mem_data_w/c_byte_w; + + TYPE t_mem_miso IS RECORD -- Master In Slave Out + rddata : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); -- data width (suits 1, 2 or 4 bytes) + rdval : STD_LOGIC; + waitrequest : STD_LOGIC; + END RECORD; + + TYPE t_mem_mosi IS RECORD -- Master Out Slave In + address : STD_LOGIC_VECTOR(c_mem_address_w-1 DOWNTO 0); -- address range (suits 32-bit processor) + wrdata : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); -- data width (suits 1, 2 or 4 bytes) + wr : STD_LOGIC; + rd : STD_LOGIC; + END RECORD; + + CONSTANT c_mem_miso_rst : t_mem_miso := ((OTHERS=>'0'), '0', '0'); + CONSTANT c_mem_mosi_rst : t_mem_mosi := ((OTHERS=>'0'), (OTHERS=>'0'), '0', '0'); + + -- Multi port array for MM records + TYPE t_mem_miso_arr IS ARRAY (INTEGER RANGE <>) OF t_mem_miso; + TYPE t_mem_mosi_arr IS ARRAY (INTEGER RANGE <>) OF t_mem_mosi; + + TYPE t_c_mem IS RECORD + latency : NATURAL; -- read latency + adr_w : NATURAL; + dat_w : NATURAL; + nof_dat : NATURAL; -- optional, nof dat words <= 2**adr_w + init_sl : STD_LOGIC; -- optional, init all dat words to std_logic '0', '1' or 'X' + --init_file : STRING; -- "UNUSED", unconstrained length can not be in record + END RECORD; + + CONSTANT c_mem_ram_rd_latency : NATURAL := 2; -- note common_ram_crw_crw(stratix4) now also supports read latency 1 + CONSTANT c_mem_ram : t_c_mem := (c_mem_ram_rd_latency, 10, 9, 2**10, 'X'); -- 1 M9K + + CONSTANT c_mem_reg_rd_latency : NATURAL := 1; + CONSTANT c_mem_reg : t_c_mem := (c_mem_reg_rd_latency, 1, 32, 1, 'X'); + + CONSTANT c_mem_reg_init_w : NATURAL := 1*256*32; -- >= largest expected value of dat_w*nof_dat (256 * 32 bit = 1k byte) + + ------------------------------------------------------------------------------ + -- Resize functions to fit an integer or an SLV in the corresponding t_mem_miso or t_mem_mosi field width + ------------------------------------------------------------------------------ + FUNCTION TO_MEM_ADDRESS(n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, use integer to support 32 bit range + FUNCTION TO_MEM_DATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, alias of TO_MEM_DATA() + FUNCTION TO_MEM_UDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, use integer to support 32 bit range + FUNCTION TO_MEM_SDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- sign extended + FUNCTION RESIZE_MEM_ADDRESS(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned + FUNCTION RESIZE_MEM_DATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned, alias of RESIZE_MEM_UDATA + FUNCTION RESIZE_MEM_UDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned + FUNCTION RESIZE_MEM_SDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- sign extended + FUNCTION RESIZE_MEM_XDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- set unused MSBits to 'X' + + ------------------------------------------------------------------------------ + -- Functions to swap endianess + ------------------------------------------------------------------------------ + FUNCTION func_mem_swap_endianess(mm : t_mem_miso; sz : NATURAL) RETURN t_mem_miso; + FUNCTION func_mem_swap_endianess(mm : t_mem_mosi; sz : NATURAL) RETURN t_mem_mosi; + +END common_mem_pkg; + +PACKAGE BODY common_mem_pkg IS + + -- Resize functions to fit an integer or an SLV in the corresponding t_mem_miso or t_mem_mosi field width + FUNCTION TO_MEM_ADDRESS(n : INTEGER) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_mem_address_w); + END TO_MEM_ADDRESS; + + FUNCTION TO_MEM_DATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN TO_MEM_UDATA(n); + END TO_MEM_DATA; + + FUNCTION TO_MEM_UDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_mem_data_w); + END TO_MEM_UDATA; + + FUNCTION TO_MEM_SDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN RESIZE_SVEC(TO_SVEC(n, 32), c_mem_data_w); + END TO_MEM_SDATA; + + FUNCTION RESIZE_MEM_ADDRESS(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN RESIZE_UVEC(vec, c_mem_address_w); + END RESIZE_MEM_ADDRESS; + + FUNCTION RESIZE_MEM_DATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN RESIZE_MEM_UDATA(vec); + END RESIZE_MEM_DATA; + + FUNCTION RESIZE_MEM_UDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN RESIZE_UVEC(vec, c_mem_data_w); + END RESIZE_MEM_UDATA; + + FUNCTION RESIZE_MEM_SDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN RESIZE_SVEC(vec, c_mem_data_w); + END RESIZE_MEM_SDATA; + + FUNCTION RESIZE_MEM_XDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + VARIABLE v_vec : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0) := (OTHERS=>'X'); + BEGIN + v_vec(vec'LENGTH-1 DOWNTO 0) := vec; + RETURN v_vec; + END RESIZE_MEM_XDATA; + + -- Functions to swap endianess + FUNCTION func_mem_swap_endianess(mm : t_mem_miso; sz : NATURAL) RETURN t_mem_miso IS + VARIABLE v_mm : t_mem_miso; + BEGIN + -- Master In Slave Out + v_mm.rddata := hton(mm.rddata, sz); + RETURN v_mm; + END func_mem_swap_endianess; + + FUNCTION func_mem_swap_endianess(mm : t_mem_mosi; sz : NATURAL) RETURN t_mem_mosi IS + VARIABLE v_mm : t_mem_mosi; + BEGIN + -- Master Out Slave In + v_mm.address := mm.address; + v_mm.wrdata := hton(mm.wrdata, sz); + v_mm.wr := mm.wr; + v_mm.rd := mm.rd; + RETURN v_mm; + END func_mem_swap_endianess; + +END common_mem_pkg; -- GitLab