Skip to content
Snippets Groups Projects
Commit 6ffde369 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Let mms_remu.vhd and mms_epcs use the flash access IP via the technology IP wrappers.

parent 4870f6cc
No related branches found
No related tags found
No related merge requests found
hdl_lib_name = epcs
hdl_library_clause_name = epcs_lib
hdl_lib_uses = common tech_flash
build_sim_dir = $HDL_BUILD_DIR
build_synth_dir =
synth_files =
$UNB/Firmware/modules/epcs/src/vhdl/epcs_reg.vhd
src/vhdl/mms_epcs.vhd
test_bench_files =
-------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- 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/>.
--
-------------------------------------------------------------------------------
-- Note: To simulate this module, I've added an M25P128 simulation model (source: Numonyx)
-- to the generated ALTASMI_PARALLEL megafunction code, and hooked it up to the correct signals
-- internally.
-- Note 2: The simulation model requires real-life (long) powerup delays to be used. Refer to
-- /tb/vhdl/m25p128_model/lib/TimingData.vhd for the delays and references to the corresponding
-- table in the data sheet. These constants can be modified for faster simulation, but I've left them
-- as they were as simulating one page write and read is sufficient.
LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_flash_lib;;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
ENTITY mms_epcs IS
GENERIC (
g_technology : NATURAL := c_tech_select_default
g_sim : BOOLEAN := FALSE
);
PORT (
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
epcs_clk : IN STD_LOGIC;
-- General MM control:
epcs_mosi : IN t_mem_mosi := c_mem_mosi_rst;
epcs_miso : OUT t_mem_miso;
-- Data path (epcs) -> MM status and data
dpmm_ctrl_mosi : IN t_mem_mosi := c_mem_mosi_rst;
dpmm_ctrl_miso : OUT t_mem_miso := c_mem_miso_rst;
dpmm_data_mosi : IN t_mem_mosi := c_mem_mosi_rst;
dpmm_data_miso : OUT t_mem_miso := c_mem_miso_rst;
-- MM -> data path (epcs) status and data
mmdp_ctrl_mosi : IN t_mem_mosi := c_mem_mosi_rst;
mmdp_ctrl_miso : OUT t_mem_miso := c_mem_miso_rst;
mmdp_data_mosi : IN t_mem_mosi := c_mem_mosi_rst;
mmdp_data_miso : OUT t_mem_miso := c_mem_miso_rst
);
END mms_epcs;
ARCHITECTURE str OF mms_epcs IS
-- ASMI_PARALLEL supports page write mode of 256 bytes
CONSTANT c_epcs_page_size : NATURAL := 256;
CONSTANT c_user_data_w : NATURAL := c_word_w;
CONSTANT c_epcs_data_w : NATURAL := 8;
CONSTANT c_epcs_addr_w : NATURAL := 24;
CONSTANT c_fifo_depth_bits : NATURAL := c_epcs_page_size*c_epcs_data_w;
-- FIFO depths relative to epcs and user data widths
CONSTANT c_epcs_fifo_depth : NATURAL := c_fifo_depth_bits / c_epcs_data_w *2; -- *2 because we need the full depth (without the *2) but we can't 'max out' the FIFO.
CONSTANT c_user_fifo_depth : NATURAL := c_fifo_depth_bits / c_user_data_w;
-- We want to monitor FIFO contents on the user side
SIGNAL user_to_epcs_fifo_usedw : STD_LOGIC_VECTOR(ceil_log2(c_user_fifo_depth)-1 DOWNTO 0);
SIGNAL epcs_to_user_fifo_usedw : STD_LOGIC_VECTOR(ceil_log2(c_epcs_fifo_depth/(c_word_w/c_epcs_data_w))-1 DOWNTO 0);
-- Signal to stop reading data from epcs flash when we've read one page size
SIGNAL epcs_to_user_fifo_wr_usedw : STD_LOGIC_VECTOR(ceil_log2(c_epcs_fifo_depth)-1 DOWNTO 0);
SIGNAL epcs_rst : STD_LOGIC;
-- Signals between FIFOs and ASMI_PARALLEL
SIGNAL epcs_in_addr : STD_LOGIC_VECTOR(c_epcs_addr_w-1 DOWNTO 0);
SIGNAL epcs_in_datain : STD_LOGIC_VECTOR(c_epcs_data_w-1 DOWNTO 0);
SIGNAL epcs_in_rden : STD_LOGIC;
SIGNAL epcs_in_read : STD_LOGIC;
SIGNAL epcs_in_shift_bytes : STD_LOGIC;
SIGNAL epcs_in_wren : STD_LOGIC;
SIGNAL epcs_in_write : STD_LOGIC;
SIGNAL epcs_in_sector_erase : STD_LOGIC;
SIGNAL epcs_out_busy : STD_LOGIC;
SIGNAL epcs_out_data_valid : STD_LOGIC;
SIGNAL epcs_out_dataout : STD_LOGIC_VECTOR(c_epcs_data_w-1 DOWNTO 0);
SIGNAL nxt_epcs_in_addr : STD_LOGIC_VECTOR(c_epcs_addr_w-1 DOWNTO 0);
SIGNAL nxt_epcs_in_datain : STD_LOGIC_VECTOR(c_epcs_data_w-1 DOWNTO 0);
SIGNAL nxt_epcs_in_rden : STD_LOGIC;
SIGNAL nxt_epcs_in_read : STD_LOGIC;
SIGNAL nxt_epcs_in_shift_bytes : STD_LOGIC;
SIGNAL nxt_epcs_in_wren : STD_LOGIC;
SIGNAL nxt_epcs_in_write : STD_LOGIC;
SIGNAL nxt_epcs_in_sector_erase : STD_LOGIC;
SIGNAL nxt_epcs_out_data_valid : STD_LOGIC;
SIGNAL nxt_epcs_out_dataout : STD_LOGIC_VECTOR(c_epcs_data_w-1 DOWNTO 0);
SIGNAL epcs_wr_sosi : t_dp_sosi;
SIGNAL epcs_wr_siso : t_dp_siso;
SIGNAL epcs_rd_sosi : t_dp_sosi;
SIGNAL epcs_rd_siso : t_dp_siso;
SIGNAL user_wr_sosi : t_dp_sosi;
SIGNAL user_wr_siso : t_dp_siso;
SIGNAL user_rd_sosi : t_dp_sosi;
SIGNAL user_rd_siso : t_dp_siso;
SIGNAL epcs_in_addr_from_reg : STD_LOGIC_VECTOR(c_epcs_addr_w-1 DOWNTO 0);
SIGNAL epcs_in_read_from_reg : STD_LOGIC;
SIGNAL epcs_in_rden_from_reg : STD_LOGIC;
SIGNAL epcs_in_write_from_reg : STD_LOGIC;
SIGNAL epcs_in_sector_erase_from_reg : STD_LOGIC;
BEGIN
u_epcs_reg: ENTITY work.epcs_reg
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
epcs_rst => epcs_rst,
epcs_clk => epcs_clk,
sla_in => epcs_mosi,
sla_out => epcs_miso,
epcs_in_addr => epcs_in_addr_from_reg,
epcs_in_read_evt => epcs_in_read_from_reg,
epcs_in_rden => epcs_in_rden_from_reg,
epcs_in_write_evt => epcs_in_write_from_reg,
epcs_in_sector_erase_evt => epcs_in_sector_erase_from_reg,
epcs_out_busy => epcs_out_busy
);
epcs_wr_siso.ready <= '1';
u_fifo_user_to_epcs : ENTITY dp_lib.dp_fifo_dc_mixed_widths
GENERIC MAP (
g_wr_data_w => c_user_data_w,
g_rd_data_w => c_epcs_data_w,
g_use_ctrl => FALSE,
g_wr_fifo_size => c_user_fifo_depth
)
PORT MAP (
wr_rst => mm_rst,
wr_clk => mm_clk,
rd_rst => epcs_rst,
rd_clk => epcs_clk,
-- ST sink
snk_out => user_wr_siso,
snk_in => user_wr_sosi,
-- Monitor FIFO filling
wr_usedw => user_to_epcs_fifo_usedw,
rd_emp => OPEN,
-- ST source
src_in => epcs_wr_siso,
src_out => epcs_wr_sosi
);
u_fifo_epcs_to_user : ENTITY dp_lib.dp_fifo_dc_mixed_widths
GENERIC MAP (
g_wr_data_w => c_epcs_data_w,
g_rd_data_w => c_user_data_w,
g_use_ctrl => FALSE,
g_wr_fifo_size => c_epcs_fifo_depth
)
PORT MAP (
wr_rst => epcs_rst,
wr_clk => epcs_clk,
rd_rst => mm_rst,
rd_clk => mm_clk,
-- ST sink
snk_out => epcs_rd_siso,
snk_in => epcs_rd_sosi,
-- Monitor FIFO filling
wr_usedw => epcs_to_user_fifo_wr_usedw,
rd_usedw => epcs_to_user_fifo_usedw,
rd_emp => OPEN,
-- ST source
src_in => user_rd_siso,
src_out => user_rd_sosi
);
u_asmi_parallel: ENTITY tech_flash_lib.tech_flash_asmi_parallel
GENERIC MAP (
g_technology => g_technology
)
PORT MAP (
addr => epcs_in_addr,
clkin => epcs_clk,
datain => epcs_in_datain,
rden => epcs_in_rden,
read => epcs_in_read,
shift_bytes => epcs_in_shift_bytes,
wren => epcs_in_wren,
write => epcs_in_write,
sector_erase => epcs_in_sector_erase,
busy => epcs_out_busy,
data_valid => nxt_epcs_out_data_valid,
dataout => nxt_epcs_out_dataout,
illegal_write => OPEN,
illegal_erase => OPEN
);
u_mms_dp_fifo_to_mm: ENTITY dp_lib.mms_dp_fifo_to_mm
GENERIC MAP(
g_rd_fifo_depth => c_epcs_fifo_depth/(c_word_w/c_epcs_data_w)
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
rd_sosi => user_rd_sosi,
rd_siso => user_rd_siso,
ctrl_mosi => dpmm_ctrl_mosi,
ctrl_miso => dpmm_ctrl_miso,
data_mosi => dpmm_data_mosi,
data_miso => dpmm_data_miso,
rd_usedw => epcs_to_user_fifo_usedw
);
u_mms_dp_fifo_from_mm: ENTITY dp_lib.mms_dp_fifo_from_mm
GENERIC MAP(
g_wr_fifo_depth => c_user_fifo_depth
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
wr_sosi => user_wr_sosi,
ctrl_mosi => mmdp_ctrl_mosi,
ctrl_miso => mmdp_ctrl_miso,
data_mosi => mmdp_data_mosi,
data_miso => mmdp_data_miso,
wr_usedw => user_to_epcs_fifo_usedw
);
-- Looking at the timing diagrams of the ALTASMI_PARALLEL megafunction, the interface actually
-- maps quite well on a DP streaming interface:
nxt_epcs_in_addr <= epcs_in_addr_from_reg;
nxt_epcs_in_datain <= epcs_wr_sosi.data(c_epcs_data_w-1 DOWNTO 0);
-- We only want to read out one page at a time. Our EPCS->user data FIFO is oversized (*2), so
-- we need to de-assert the read signal towards the EPCS based on usedw.
nxt_epcs_in_rden <= epcs_in_rden_from_reg WHEN UNSIGNED(epcs_to_user_fifo_wr_usedw)<c_epcs_page_size-1 ELSE '0';
nxt_epcs_in_read <= epcs_in_read_from_reg;
nxt_epcs_in_shift_bytes <= epcs_wr_sosi.valid;
nxt_epcs_in_wren <= (epcs_wr_sosi.valid OR epcs_in_write_from_reg) OR epcs_in_sector_erase_from_reg;
nxt_epcs_in_sector_erase <= epcs_in_sector_erase_from_reg;
nxt_epcs_in_write <= epcs_in_write_from_reg;
epcs_rd_sosi.data(c_epcs_data_w-1 DOWNTO 0) <= epcs_out_dataout;
epcs_rd_sosi.valid <= epcs_out_data_valid;
-- The ASMI_PARALLEL requires that data is set up on the falling edge. The following rising
-- edge of the ASMI_PARALLEL's 20MHz clkin clocks in the data. The data is required to be held until
-- the next falling edge:
-- __ __ __ __ __ __
-- _||_||_||_||_||_||_
-- ____
-- ________| |_______
--
-- All used components expect rising edge clocked signals, so we're reclocking the relevant signals
-- with falling-edge clocked registers:
p_epcs_clk: PROCESS(epcs_clk, epcs_rst)
BEGIN
IF epcs_rst='1' THEN
epcs_in_addr <= (OTHERS=>'0');
epcs_in_datain <= (OTHERS=>'0');
epcs_in_rden <= '0';
epcs_in_read <= '0';
epcs_in_shift_bytes <= '0';
epcs_in_wren <= '0';
epcs_in_write <= '0';
epcs_in_sector_erase <= '0';
epcs_out_dataout <= (OTHERS=>'0');
epcs_out_data_valid <= '0';
ELSIF falling_edge(epcs_clk) THEN
epcs_in_addr <= nxt_epcs_in_addr;
epcs_in_datain <= nxt_epcs_in_datain;
epcs_in_rden <= nxt_epcs_in_rden;
epcs_in_read <= nxt_epcs_in_read;
epcs_in_shift_bytes <= nxt_epcs_in_shift_bytes;
epcs_in_wren <= nxt_epcs_in_wren;
epcs_in_write <= nxt_epcs_in_write;
epcs_in_sector_erase <= nxt_epcs_in_sector_erase;
epcs_out_dataout <= nxt_epcs_out_dataout;
epcs_out_data_valid <= nxt_epcs_out_data_valid;
END IF;
END PROCESS;
u_common_areset: ENTITY common_lib.common_areset
PORT MAP (
in_rst => mm_rst,
clk => epcs_clk,
out_rst => epcs_rst
);
END str;
hdl_lib_name = remu hdl_lib_name = remu
hdl_library_clause_name = remu_lib hdl_library_clause_name = remu_lib
hdl_lib_uses = common hdl_lib_uses = common tech_flash
build_sim_dir = $HDL_BUILD_DIR build_sim_dir = $HDL_BUILD_DIR
build_synth_dir = build_synth_dir =
synth_files = synth_files =
src/ip/megawizard/remote_update/remote_update.vhd $UNB/Firmware/modules/remu/src/vhdl/remu_reg.vhd
src/vhdl/remu_reg.vhd
src/vhdl/mms_remu.vhd src/vhdl/mms_remu.vhd
test_bench_files = test_bench_files =
-------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- 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, common_lib, technology_lib, tech_flash_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
ENTITY mms_remu IS
GENERIC MAP (
g_technology : NATURAL := c_tech_select_default
);
PORT (
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
epcs_clk : IN STD_LOGIC;
-- MM registers
remu_mosi : IN t_mem_mosi := c_mem_mosi_rst;
remu_miso : OUT t_mem_miso
);
END mms_remu;
ARCHITECTURE str OF mms_remu IS
CONSTANT c_param_w : NATURAL := 3;
CONSTANT c_data_w : NATURAL := 24;
SIGNAL epcs_rst : STD_LOGIC;
SIGNAL remu_busy : STD_LOGIC;
SIGNAL remu_data_out : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL fall_remu_reconfigure : STD_LOGIC;
SIGNAL fall_remu_read_param : STD_LOGIC;
SIGNAL fall_remu_write_param : STD_LOGIC;
SIGNAL fall_remu_param : STD_LOGIC_VECTOR(c_param_w-1 DOWNTO 0);
SIGNAL fall_remu_data_in : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL nxt_fall_remu_reconfigure : STD_LOGIC;
SIGNAL nxt_fall_remu_read_param : STD_LOGIC;
SIGNAL nxt_fall_remu_write_param : STD_LOGIC;
SIGNAL nxt_fall_remu_param : STD_LOGIC_VECTOR(c_param_w-1 DOWNTO 0);
SIGNAL nxt_fall_remu_data_in : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
BEGIN
u_remu: ENTITY tech_flash_lib.tech_flash_remote_update
GENERIC MAP (
g_technology => g_technology
)
PORT MAP (
clock => epcs_clk,
param => fall_remu_param,
read_param => fall_remu_read_param,
reconfig => fall_remu_reconfigure,
reset => epcs_rst,
reset_timer => '0',
busy => remu_busy,
data_out => remu_data_out,
write_param => fall_remu_write_param,
data_in => fall_remu_data_in
);
u_remu_reg: ENTITY work.remu_reg
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
epcs_rst => epcs_rst,
epcs_clk => epcs_clk,
sla_in => remu_mosi,
sla_out => remu_miso,
reconfigure => nxt_fall_remu_reconfigure,
read_param => nxt_fall_remu_read_param,
param => nxt_fall_remu_param,
busy => remu_busy,
data_out => remu_data_out,
write_param => nxt_fall_remu_write_param,
data_in => nxt_fall_remu_data_in
);
-- The Remote Upgrade megafunction uses an ASMI_PARALLEL instance internally and therefore requires
-- the same clocking scheme as the EPCS module:
-- The ASMI_PARALLEL requires that data is set up on the falling edge. The following rising
-- edge of the ASMI_PARALLEL's 20MHz clkin clocks in the data. The data is required to be held until
-- the next falling edge:
-- __ __ __ __ __ __
-- _||_||_||_||_||_||_
-- ____
-- ________| |_______
--
-- All used components expect rising edge clocked signals, so we're reclocking the relevant signals
-- with falling-edge clocked registers:
p_epcs_clk: PROCESS(epcs_clk, epcs_rst)
BEGIN
IF epcs_rst='1' THEN
fall_remu_reconfigure <= '0';
fall_remu_read_param <= '0';
fall_remu_write_param <= '0';
fall_remu_param <= (OTHERS=>'0');
fall_remu_data_in <= (OTHERS=>'0');
ELSIF falling_edge(epcs_clk) THEN
fall_remu_reconfigure <= nxt_fall_remu_reconfigure;
fall_remu_read_param <= nxt_fall_remu_read_param;
fall_remu_write_param <= nxt_fall_remu_write_param;
fall_remu_param <= nxt_fall_remu_param;
fall_remu_data_in <= nxt_fall_remu_data_in;
END IF;
END PROCESS;
u_common_areset: ENTITY common_lib.common_areset
PORT MAP (
in_rst => mm_rst,
clk => epcs_clk,
out_rst => epcs_rst
);
END str;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment