------------------------------------------------------------------------------- -- -- Copyright (C) 2015 -- 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/>. -- ------------------------------------------------------------------------------- -- -- Register definition: -- -- wi Bits R/W Name Default Description -- ============================================================================= -- 0 [0] WE burstbegin 0x0 -- 1 [0] WO wr_not_rd 0x0 -- 2 [0] RO done 0x1 -- 3 not used -- 4 not used -- 5 [31..0] WO address 0x0 -- 6 [31..0] WO burstsize 0x0 -- 7 [0] WR flush 0x0 -- ============================================================================= -- -- Legenda: -- -- RO read only (no VHDL present to access HW in write mode) -- WO write only (no VHDL present to access HW in read mode) -- WE write event (=WO) -- WR write control, read control -- RW read status, write control -- RC read, clear on read -- FR FIFO read -- FW FIFO write -- -- Remarks: -- . Clock domain crossing between mm_clk and the DDR controller clock domain -- needs to be done by io_ddr_cross_domain.vhd in io_ddr. library IEEE, common_lib, diag_lib; use IEEE.std_logic_1164.all; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use diag_lib.diag_pkg.all; entity io_ddr_reg is port ( -- Clocks and reset mm_rst : in std_logic; -- reset synchronous with mm_clk mm_clk : in std_logic; -- memory-mapped bus clock -- Memory Mapped Slave in mm_clk domain sla_in : in t_mem_mosi; -- actual ranges defined by c_mm_reg sla_out : out t_mem_miso; -- actual ranges defined by c_mm_reg -- MM registers in st_clk domain dvr_miso : in t_mem_ctlr_miso; dvr_mosi : out t_mem_ctlr_mosi ); end io_ddr_reg; architecture rtl of io_ddr_reg is constant c_mm_reg : t_c_mem := ( latency => 1, adr_w => ceil_log2(8), dat_w => c_word_w, -- Use MM bus data width = c_word_w = 32 for all MM registers nof_dat => 8, init_sl => '0' ); signal i_dvr_mosi : t_mem_ctlr_mosi; begin dvr_mosi <= i_dvr_mosi; ------------------------------------------------------------------------------ -- MM register access in the mm_clk domain -- . Hardcode the shared MM slave register directly in RTL instead of using -- the common_reg_r_w instance. Directly using RTL is easier when the large -- MM register has multiple different fields and with different read and -- write options per field in one MM register. ------------------------------------------------------------------------------ p_mm_reg : process (mm_rst, mm_clk) begin if mm_rst = '1' then sla_out <= c_mem_miso_rst; i_dvr_mosi <= c_mem_ctlr_mosi_rst; elsif rising_edge(mm_clk) then -- Read access defaults sla_out.rdval <= '0'; -- Write access defaults i_dvr_mosi.burstbegin <= '0'; -- Write access: set register value if sla_in.wr = '1' then case TO_UINT(sla_in.address(c_mm_reg.adr_w - 1 downto 0)) is -- Write Block Sync when 0 => i_dvr_mosi.burstbegin <= sla_in.wrdata(0); -- default to '0' so MM write '1' will yield a pulse of one mm_clk clock cycle when 1 => i_dvr_mosi.wr <= sla_in.wrdata(0); -- = wr_not_rd, so no need to control i_dvr_mosi.rd when 5 => i_dvr_mosi.address <= sla_in.wrdata(c_mem_ctlr_address_w - 1 downto 0); when 6 => i_dvr_mosi.burstsize <= sla_in.wrdata(c_mem_ctlr_burstsize_w - 1 downto 0); when 7 => i_dvr_mosi.flush <= sla_in.wrdata(0); when others => null; -- unused MM addresses end case; -- Read access: get register value elsif sla_in.rd = '1' then sla_out <= c_mem_miso_rst; -- set unused rddata bits to '0' when read sla_out.rdval <= '1'; -- c_mm_reg.latency = 1 case TO_UINT(sla_in.address(c_mm_reg.adr_w - 1 downto 0)) is -- Read Block Sync when 2 => sla_out.rddata(0) <= dvr_miso.done; -- read only when 7 => sla_out.rddata(0) <= i_dvr_mosi.flush; -- readback when others => null; -- unused MM addresses end case; end if; end if; end process; end rtl;