diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd new file mode 100644 index 0000000000000000000000000000000000000000..b517bdf4d2029d3ac159b409c4e708c054ac1f8f --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd @@ -0,0 +1,163 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2022 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- +-- Author: Job van Wee +-- Purpose: stopping the data steam into the SDRAM stick. +-- +-- Description: +-- +-- Remark: +-- Use VHDL coding template from: +-- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding +-- + +LIBRARY IEEE, dp_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE dp_lib.dp_stream_pkg.ALL; + + +ENTITY ddrctrl_controller IS + GENERIC ( + g_max_adr : NATURAL; + ); + PORT ( + clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + + -- ddrctrl_input + out_of : IN NATURAL; + out_sosi : IN t_dp_sosi; + out_adr : IN NATURAL; + + -- io_ddr + dvr_mosi : OUT t_mem_ctlr_mosi; + wr_sosi : OUT t_dp_sosi; + rd_siso : OUT t_dp_siso; + + -- ddrctrl + stop_in : IN STD_LOGIC; + ); +END ddrctrl_controller; + +ARCHITECTURE rtl OF ddrctrl_controller IS + + CONSTANT c_burstsize : NATURAL := 64; -- max burstsize for max troughput + CONSTANT c_bitshift_adr : NATURAL := ceil_log2(c_burstsize); + CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( g_tech_ddr ); -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27 + CONSTANT c_max_adr : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address + CONSTANT c_zeros : STD_LOGIC_VECTOR(c_bitshift_adr-1 DOWNTO 0) := (OTHERS => '0'); + + -- type for statemachine + TYPE t_state IS (RESET, WRITING, STOP_WRITING, READING, STOP_READING, IDLE); + + -- record for readability + TYPE t_reg IS RECORD + state : t_state; -- the state the process is currently in; + dvr_mosi : t_mem_ctlr_mosi; + wr_sosi : t_dp_sosi; + rd_siso : t_dp_siso; + END RECORD; + + CONSTANT c_t_reg_init : t_reg := (RESET, c_mem_ctlr_mosi_init, c_dp_sosi_init, c_dp_siso_rst); + + + -- signals for readability + SIGNAL d_reg : t_reg := c_t_reg_init; + SIGNAL q_reg : t_reg := c_t_reg_init; + +BEGIN + + q_reg <= d_reg WHEN rising_edge(clk); + + -- put the input data into c_v and fill the output vector from c_v + p_state : PROCESS(q_reg, rst) + + VARIABLE v : t_reg; + + BEGIN + + v := q_reg; + + CASE q_reg.state IS + WHEN RESET => + v := c_t_reg_init; + + WHEN + + END CASE; + + + + + + + + + + + + + + + + + p_burst : PROCESS(adr) + BEGIN + IF TO_UVEC(adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN + dvr_mosi.burstbegin <= '1'; + IF adr = 0 THEN + dvr_mosi.address <= TO_UVEC(c_max_adr-c_burstsize, dvr_mosi.address'length); + ELSE + dvr_mosi.address <= TO_UVEC(adr-c_burstsize, dvr_mosi.address'length); + END IF; + ELSE + dvr_mosi.burstbegin <= '0'; + END IF; + END PROCESS; + + dvr_mosi.burstsize <= TO_UVEC(c_burstsize, dvr_mosi.burstsize'length); + dvr_mosi.wr <= wr_not_rd; + dvr_mosi.rd <= NOT wr_not_rd; + + + + + + + + + + IF rising_edge(stop_in) THEN + IF (current_adr + (g_max_adr / 2) >= g_max_adr) + adr <= current_adr - (g_max_adr / 2); + ELSE + adr <= current_adr + (g_max_adr / 2); + + current_adr : PROCESS(current_adr) + BEGIN + + IF (stop_in = '1' AND current_adr = adr) THEN + stop_out <= '1'; + adr_out = current_adr; + ELSE + stop_out <= '0'; + END IF; + END PROCESS; +END rtl;