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

Merge branch 'L2SDP-200' into 'master'

Resolve L2SDP-200

Closes L2SDP-200

See merge request desp/hdl!67
parents 1c0f217a 6466aa89
No related branches found
No related tags found
2 merge requests!100Removed text for XSub that is now written in Confluence Subband correlator...,!67Resolve L2SDP-200
...@@ -13,15 +13,18 @@ synth_files = ...@@ -13,15 +13,18 @@ synth_files =
src/vhdl/sdp_info_reg.vhd src/vhdl/sdp_info_reg.vhd
src/vhdl/sdp_info.vhd src/vhdl/sdp_info.vhd
src/vhdl/sdp_beamformer_output.vhd src/vhdl/sdp_beamformer_output.vhd
src/vhdl/sdp_statistics_offload.vhd
src/vhdl/node_sdp_adc_input_and_timing.vhd src/vhdl/node_sdp_adc_input_and_timing.vhd
src/vhdl/node_sdp_filterbank.vhd src/vhdl/node_sdp_filterbank.vhd
src/vhdl/node_sdp_beamformer.vhd src/vhdl/node_sdp_beamformer.vhd
test_bench_files = test_bench_files =
tb/vhdl/tb_sdp_info.vhd tb/vhdl/tb_sdp_info.vhd
tb/vhdl/tb_sdp_statistics_offload.vhd
regression_test_vhdl = regression_test_vhdl =
tb/vhdl/tb_sdp_info.vhd tb/vhdl/tb_sdp_info.vhd
tb/vhdl/tb_sdp_statistics_offload.vhd
[modelsim_project_file] [modelsim_project_file]
......
...@@ -96,6 +96,11 @@ PACKAGE sdp_pkg is ...@@ -96,6 +96,11 @@ PACKAGE sdp_pkg is
CONSTANT c_sdp_W_gn_id : NATURAL := 5; CONSTANT c_sdp_W_gn_id : NATURAL := 5;
CONSTANT c_sdp_N_pn_lb : NATURAL := 16; CONSTANT c_sdp_N_pn_lb : NATURAL := 16;
--
CONSTANT c_sdp_marker_sst : NATURAL := 83; -- = 0x53 = 'S'
CONSTANT c_sdp_marker_bst : NATURAL := 66; -- = 0x42 = 'B'
CONSTANT c_sdp_marker_xst : NATURAL := 88; -- = 0x58 = 'X'
-- AIT constants -- AIT constants
CONSTANT c_sdp_ait_buf_nof_data_jesd : NATURAL := 1024; -- 1024 14 bit samples fit in one M20k BRAM CONSTANT c_sdp_ait_buf_nof_data_jesd : NATURAL := 1024; -- 1024 14 bit samples fit in one M20k BRAM
CONSTANT c_sdp_ait_buf_nof_data_bsn : NATURAL := 1024; -- 1024 14 bit samples fit in one M20k BRAM CONSTANT c_sdp_ait_buf_nof_data_bsn : NATURAL := 1024; -- 1024 14 bit samples fit in one M20k BRAM
...@@ -199,6 +204,58 @@ PACKAGE sdp_pkg is ...@@ -199,6 +204,58 @@ PACKAGE sdp_pkg is
CONSTANT c_sdp_reg_nw_10GbE_mac_addr_w : NATURAL := 13; CONSTANT c_sdp_reg_nw_10GbE_mac_addr_w : NATURAL := 13;
CONSTANT c_sdp_reg_nw_10GbE_eth10g_addr_w : NATURAL := 1; CONSTANT c_sdp_reg_nw_10GbE_eth10g_addr_w : NATURAL := 1;
-- statistics offload
CONSTANT c_sdp_stat_nof_hdr_fields : NATURAL := 3+12+4+20+1; -- 592b; 9.25 64b words
CONSTANT c_sdp_stat_hdr_field_sel : STD_LOGIC_VECTOR(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"01000000000000000000"&"0"; -- 0=data path, 1=MM controlled TODO
CONSTANT c_sdp_stat_hdr_field_arr : t_common_field_arr(c_sdp_stat_nof_hdr_fields-1 DOWNTO 0) := (
( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"00074306C700") ), -- 00074306C700=DOP36-eth0
( field_name_pad("eth_src_mac" ), "RW", 48, field_default(0) ),
( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ),
( field_name_pad("ip_version" ), "RW", 4, field_default(4) ),
( field_name_pad("ip_header_length" ), "RW", 4, field_default(5) ),
( field_name_pad("ip_services" ), "RW", 8, field_default(0) ),
( field_name_pad("ip_total_length" ), "RW", 16, field_default(7868) ),
( field_name_pad("ip_identification" ), "RW", 16, field_default(0) ),
( field_name_pad("ip_flags" ), "RW", 3, field_default(2) ),
( field_name_pad("ip_fragment_offset" ), "RW", 13, field_default(0) ),
( field_name_pad("ip_time_to_live" ), "RW", 8, field_default(127) ),
( field_name_pad("ip_protocol" ), "RW", 8, field_default(17) ),
( field_name_pad("ip_header_checksum" ), "RW", 16, field_default(0) ),
( field_name_pad("ip_src_addr" ), "RW", 32, field_default(0) ),
( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"C0A80001") ), -- C0A80001=DOP36-eth0 '192.168.0.1'
( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ),
( field_name_pad("udp_dst_port" ), "RW", 16, field_default(0) ),
( field_name_pad("udp_total_length" ), "RW", 16, field_default(7848) ),
( field_name_pad("udp_checksum" ), "RW", 16, field_default(0) ),
( field_name_pad("sdp_marker" ), "RW", 8, field_default(0) ),
( field_name_pad("sdp_version_id" ), "RW", 8, field_default(5) ),
( field_name_pad("sdp_observation_id" ), "RW", 32, field_default(0) ),
( field_name_pad("sdp_station_id" ), "RW", 16, field_default(0) ),
( field_name_pad("sdp_source_info_antenna_band_id" ), "RW", 1, field_default(0) ),
( field_name_pad("sdp_source_info_nyquist_zone_id" ), "RW", 2, field_default(0) ),
( field_name_pad("sdp_source_info_f_adc" ), "RW", 1, field_default(0) ),
( field_name_pad("sdp_source_info_fsub_type" ), "RW", 1, field_default(0) ),
( field_name_pad("sdp_source_info_payload_error" ), "RW", 1, field_default(0) ),
( field_name_pad("sdp_source_info_beam_repositioning_flag" ), "RW", 1, field_default(0) ),
( field_name_pad("sdp_source_info_subband_calibrated_flag" ), "RW", 1, field_default(0) ),
( field_name_pad("sdp_source_info_reserved" ), "RW", 3, field_default(0) ),
( field_name_pad("sdp_source_info_gn_id" ), "RW", 5, field_default(0) ),
( field_name_pad("sdp_reserved" ), "RW", 8, field_default(0) ),
( field_name_pad("sdp_integration_interval" ), "RW", 24, field_default(0) ),
( field_name_pad("sdp_data_id" ), "RW", 32, field_default(0) ),
( field_name_pad("sdp_nof_signal_inputs" ), "RW", 8, field_default(0) ),
( field_name_pad("sdp_nof_bytes_per_statistics" ), "RW", 8, field_default(8) ),
( field_name_pad("sdp_nof_statistics_per_packet" ), "RW", 16, field_default(0) ),
( field_name_pad("sdp_block_period" ), "RW", 16, field_default(0) ),
( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) )
);
END PACKAGE sdp_pkg; END PACKAGE sdp_pkg;
PACKAGE BODY sdp_pkg IS PACKAGE BODY sdp_pkg IS
......
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- 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: P. Donker
-- Purpose:
-- . SDP statistics offload
-- Description:
-- https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Subband+filterbank
-- . See figure 4.3
-- https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
-- . See 2.9.4 Station Control (L3-SC) - SDP Firmware (L4-SDPFW)
--
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, mm_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE work.sdp_pkg.ALL;
ENTITY sdp_statistics_offload IS
GENERIC (
g_statistics_type : STRING := "SST";
g_offload_time : NATURAL := 13000; -- from wave window 62855nS / 5nS = 12571 cycles.
g_beamset_id : NATURAL := 0
);
PORT (
-- Clocks and reset
mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk
mm_clk : IN STD_LOGIC; -- memory-mapped bus clock
dp_clk : IN STD_LOGIC;
dp_rst : IN STD_LOGIC;
-- Memory access to statistics values
master_mosi : OUT t_mem_mosi; -- := c_mem_mosi_rst;
master_miso : IN t_mem_miso;
-- Memory access to read/write settings
reg_enable_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_enable_miso : OUT t_mem_miso;
reg_hdr_dat_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_hdr_dat_miso : OUT t_mem_miso;
-- Input timing regarding the integration interval of the statistics
in_sosi : IN t_dp_sosi;
-- Streaming output of offloaded statistics packets
out_sosi : OUT t_dp_sosi;
out_siso : IN t_dp_siso;
-- inputs from other blocks
eth_src_mac : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
udp_src_port : IN STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0);
ip_src_addr : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0);
sdp_info : IN t_sdp_info;
gn_index : IN NATURAL
);
END sdp_statistics_offload;
ARCHITECTURE str OF sdp_statistics_offload IS
CONSTANT c_step_size : NATURAL := 4;
CONSTANT c_nof_data : NATURAL := 512;
CONSTANT c_block_size : NATURAL := c_nof_data * c_step_size;
CONSTANT c_nof_streams : NATURAL := 1;
CONSTANT c_data_size : NATURAL := 2;
CONSTANT c_nof_data_per_step : NATURAL := 2;
CONSTANT c_nof_packets : NATURAL := sel_a_b(g_statistics_type="BST", 1,
sel_a_b(g_statistics_type="XST", c_sdp_S_pn,
c_sdp_S_pn)); -- SST
CONSTANT c_marker : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_marker_bst,
sel_a_b(g_statistics_type="XST", c_sdp_marker_xst,
c_sdp_marker_sst));
CONSTANT c_nof_signal_inputs : NATURAL := sel_a_b(g_statistics_type="BST", 0,
sel_a_b(g_statistics_type="XST", c_sdp_S_pn,
1)); -- SST
CONSTANT c_nof_statistics_per_packet : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_S_sub_bf,
sel_a_b(g_statistics_type="XST", (c_sdp_S_pn * c_sdp_S_pn * c_nof_complex),
c_sdp_N_sub)); -- SST
CONSTANT c_beamlet_id : NATURAL := g_beamset_id * c_sdp_S_sub_bf;
TYPE t_reg IS RECORD
block_count : NATURAL;
start_address : NATURAL;
start_pulse : STD_LOGIC;
dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0);
data_id : STD_LOGIC_VECTOR(31 DOWNTO 0);
nof_cycles_dly : NATURAL;
payload_err : STD_LOGIC;
interval_cnt : NATURAL;
END RECORD;
CONSTANT c_reg_rst : t_reg := (0, 0, '0', (OTHERS => '0'), (OTHERS => '0'), 0, '0', 0);
SIGNAL r : t_reg;
SIGNAL d : t_reg;
SIGNAL trigger : STD_LOGIC := '0';
SIGNAL mm_done : STD_LOGIC := '0';
SIGNAL dp_block_from_mm_src_out : t_dp_sosi;
SIGNAL dp_block_from_mm_src_in : t_dp_siso;
SIGNAL dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0');
SIGNAL integration_interval : NATURAL := 0;
SIGNAL bsn_at_sync : STD_LOGIC_VECTOR(63 DOWNTO 0) := (OTHERS => '0');
--SIGNAL sdp_data_id : STD_LOGIC_VECTOR(31 DOWNTO 0);
BEGIN
bsn_at_sync <= RESIZE_UVEC(in_sosi.bsn, 64) WHEN rising_edge(dp_clk) AND in_sosi.sync = '1';
-------------------------------------------------------------------------------
-- Assemble offload header info
-------------------------------------------------------------------------------
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "udp_src_port" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "udp_src_port" )) <= udp_src_port;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_marker" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_marker" )) <= TO_UVEC(c_marker, 8);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_observation_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_observation_id" )) <= sdp_info.observation_id;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_station_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_station_id" )) <= sdp_info.station_id;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id" )) <= SLV(sdp_info.antenna_band_index);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id" )) <= sdp_info.nyquist_zone_index;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc" )) <= SLV(sdp_info.f_adc);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type" )) <= SLV(sdp_info.fsub_type);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_payload_error" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_payload_error" )) <= SLV(r.payload_err);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" )) <= SLV(sdp_info.beam_repositioning_flag);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_subband_calibrated_flag" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_subband_calibrated_flag" )) <= SLV(sdp_info.subband_calibrated_flag);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_reserved" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_reserved" )) <= (OTHERS => '0');
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_source_info_gn_id" )) <= TO_UVEC(gn_index, 5);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_reserved" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_reserved" )) <= (OTHERS => '0');
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_integration_interval" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_integration_interval" )) <= TO_UVEC(integration_interval, 24);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_data_id" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_data_id" )) <= r.data_id;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_signal_inputs" )) <= TO_UVEC(c_nof_signal_inputs, 8);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_nof_statistics_per_packet" )) <= TO_UVEC(c_nof_statistics_per_packet, 16);
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_block_period" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "sdp_block_period" )) <= sdp_info.block_period;
dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr, "dp_bsn" )) <= bsn_at_sync;
p_reg : PROCESS(dp_rst, dp_clk)
BEGIN
IF dp_rst='1' THEN
r <= c_reg_rst;
ELSIF rising_edge(dp_clk) THEN
r <= d;
END IF;
END PROCESS;
p_control_packet_offload : PROCESS(r, gn_index, in_sosi, trigger, mm_done, dp_header_info)
BEGIN
d <= r;
d.start_pulse <= '0';
d.nof_cycles_dly <= gn_index * g_offload_time;
-- Count number of sop's in a sync interval and get payload errors and keep them till next sync.
IF in_sosi.sync = '1' THEN
integration_interval <= r.interval_cnt;
d.interval_cnt <= 0;
d.payload_err <= '0';
ELSE
IF in_sosi.eop = '1' THEN
d.payload_err <= r.payload_err OR in_sosi.err(0);
END IF;
IF in_sosi.sop = '1' THEN
d.interval_cnt <= r.interval_cnt + 1;
END IF;
END IF;
-- assign sdp_data_id for different statistic types
IF g_statistics_type = "SST" THEN
d.data_id <= x"000000" & TO_UVEC(r.block_count + c_sdp_S_pn * gn_index, 8);
ELSIF g_statistics_type = "BST" THEN
d.data_id <= x"0000" & TO_UVEC(c_beamlet_id, 16);
ELSIF g_statistics_type = "XST" THEN
d.data_id <= x"00" & TO_UVEC(0, 8) & TO_UVEC(0, 8) & TO_UVEC(0, 8); -- TODO: fill in right values for XST.
ELSE
d.data_id <= x"00000000";
END IF;
-- Issue start_pulse per packet offload
IF trigger = '1' THEN
-- Use trigger to start first packet
d.start_pulse <= '1';
d.start_address <= 0;
d.block_count <= 1;
ELSIF mm_done = '1' THEN
-- Use mm_done to start next packets
IF r.block_count < c_nof_packets THEN
IF r.block_count MOD c_nof_data_per_step = 0 THEN
d.start_address <= r.start_address + c_data_size; -- step to next packet within block
ELSE
d.start_address <= r.block_count / c_nof_data_per_step * c_block_size; -- jump to first packet in next block
END IF;
d.start_pulse <= '1';
d.block_count <= r.block_count + 1;
ELSE
-- Prepare for next trigger interval.
d.start_address <= 0;
d.block_count <= 0;
END IF;
END IF;
-- Release header info per packet offload
IF trigger = '1' OR mm_done = '1' THEN
d.dp_header_info <= dp_header_info;
END IF;
END PROCESS;
u_mms_common_variable_delay : ENTITY common_lib.mms_common_variable_delay
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
-- MM interface
reg_enable_mosi => reg_enable_mosi,
reg_enable_miso => reg_enable_miso,
delay => r.nof_cycles_dly,
trigger => in_sosi.sync,
trigger_dly => trigger
);
u_dp_block_from_mm : ENTITY dp_lib.dp_block_from_mm
GENERIC MAP (
g_data_size => c_data_size,
g_step_size => c_step_size,
g_nof_data => c_nof_data
)
PORT MAP(
rst => dp_rst,
clk => dp_clk,
start_pulse => r.start_pulse,
start_address => r.start_address,
mm_done => mm_done,
mm_mosi => master_mosi,
mm_miso => master_miso,
out_sosi => dp_block_from_mm_src_out,
out_siso => dp_block_from_mm_src_in
);
u_dp_offload_tx_v3: ENTITY dp_lib.dp_offload_tx_v3
GENERIC MAP (
g_nof_streams => c_nof_streams,
g_data_w => c_word_w,
g_symbol_w => c_word_w,
g_hdr_field_arr => c_sdp_stat_hdr_field_arr,
g_hdr_field_sel => c_sdp_stat_hdr_field_sel,
g_pipeline_ready => TRUE
)
PORT MAP(
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
reg_hdr_dat_mosi => reg_hdr_dat_mosi,
reg_hdr_dat_miso => reg_hdr_dat_miso,
snk_in_arr(0) => dp_block_from_mm_src_out,
snk_out_arr(0) => dp_block_from_mm_src_in,
src_out_arr(0) => out_sosi,
src_in_arr(0) => out_siso,
hdr_fields_in_arr(0) => r.dp_header_info
);
END str;
This diff is collapsed.
...@@ -57,7 +57,7 @@ ARCHITECTURE rtl OF common_variable_delay IS ...@@ -57,7 +57,7 @@ ARCHITECTURE rtl OF common_variable_delay IS
BEGIN BEGIN
out_val <= i_out_val; out_val <= i_out_val;
p_delay: PROCESS(enable, in_val, prev_in_val, delay, delay_cnt) p_delay: PROCESS(in_val, prev_in_val, delay, delay_cnt)
BEGIN BEGIN
nxt_out_val <= '0'; nxt_out_val <= '0';
nxt_delay_cnt <= 0; nxt_delay_cnt <= 0;
......
...@@ -42,7 +42,7 @@ ENTITY dp_block_from_mm IS ...@@ -42,7 +42,7 @@ ENTITY dp_block_from_mm IS
rst : IN STD_LOGIC; rst : IN STD_LOGIC;
clk : IN STD_LOGIC; clk : IN STD_LOGIC;
start_pulse : IN STD_LOGIC; start_pulse : IN STD_LOGIC;
start_address : IN NATURAL RANGE 0 TO g_step_size * g_nof_data; start_address : IN NATURAL;
mm_done : OUT STD_LOGIC; mm_done : OUT STD_LOGIC;
mm_mosi : OUT t_mem_mosi; mm_mosi : OUT t_mem_mosi;
mm_miso : IN t_mem_miso; mm_miso : IN t_mem_miso;
...@@ -72,7 +72,7 @@ ARCHITECTURE rtl OF dp_block_from_mm IS ...@@ -72,7 +72,7 @@ ARCHITECTURE rtl OF dp_block_from_mm IS
SIGNAL last_mm_address : NATURAL := 0; SIGNAL last_mm_address : NATURAL := 0;
BEGIN BEGIN
last_mm_address <= g_step_size * (g_nof_data - 1) + g_data_size + start_address; last_mm_address <= g_step_size * (g_nof_data - 1) + g_data_size + start_address - 1;
mm_address <= start_address + r.word_index + r.step_index; mm_address <= start_address + r.word_index + r.step_index;
mm_mosi.address <= TO_MEM_ADDRESS(mm_address); mm_mosi.address <= TO_MEM_ADDRESS(mm_address);
...@@ -82,7 +82,7 @@ BEGIN ...@@ -82,7 +82,7 @@ BEGIN
out_sosi.sop <= r.sop; -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so r.sop can be used for output sop out_sosi.sop <= r.sop; -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so r.sop can be used for output sop
out_sosi.eop <= r.eop; -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so r.eop can be used for output eop out_sosi.eop <= r.eop; -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so r.eop can be used for output eop
mm_done <= d.eop; mm_done <= r.eop;
p_reg : PROCESS(rst, clk) p_reg : PROCESS(rst, clk)
BEGIN BEGIN
......
...@@ -59,7 +59,7 @@ END tb_dp_block_from_mm; ...@@ -59,7 +59,7 @@ END tb_dp_block_from_mm;
ARCHITECTURE tb OF tb_dp_block_from_mm IS ARCHITECTURE tb OF tb_dp_block_from_mm IS
CONSTANT c_nof_blocks : NATURAL := g_step_size / g_data_size; CONSTANT c_nof_blocks : NATURAL := g_step_size / g_data_size;
CONSTANT c_ram_data_size : NATURAL := g_nof_data * g_data_size * c_nof_blocks; CONSTANT c_ram_data_size : NATURAL := g_nof_data * g_data_size * c_nof_blocks + g_data_size; -- Size is g_data_size addresses more than needed, to check for oversized blocks.
CONSTANT c_ram_adr_w : NATURAL := ceil_log2(c_ram_data_size); CONSTANT c_ram_adr_w : NATURAL := ceil_log2(c_ram_data_size);
CONSTANT c_ram : t_c_mem := (1, c_ram_adr_w, c_word_w, 2**c_ram_adr_w, '0'); CONSTANT c_ram : t_c_mem := (1, c_ram_adr_w, c_word_w, 2**c_ram_adr_w, '0');
...@@ -90,6 +90,12 @@ ARCHITECTURE tb OF tb_dp_block_from_mm IS ...@@ -90,6 +90,12 @@ ARCHITECTURE tb OF tb_dp_block_from_mm IS
SIGNAL ram_rd_adr : STD_LOGIC_VECTOR(c_ram.adr_w-1 DOWNTO 0); SIGNAL ram_rd_adr : STD_LOGIC_VECTOR(c_ram.adr_w-1 DOWNTO 0);
SIGNAL ram_rd_dat : STD_LOGIC_VECTOR(c_ram.dat_w-1 DOWNTO 0); SIGNAL ram_rd_dat : STD_LOGIC_VECTOR(c_ram.dat_w-1 DOWNTO 0);
SIGNAL ram_rd_val : STD_LOGIC; SIGNAL ram_rd_val : STD_LOGIC;
SIGNAL ram_prev_rd_val : STD_LOGIC;
SIGNAL rd_nxt_data : NATURAL := 0;
SIGNAL rd_data : NATURAL := 0;
SIGNAL stop_address : NATURAL := 0;
SIGNAL init_done : STD_LOGIC := '0'; SIGNAL init_done : STD_LOGIC := '0';
SIGNAL transfer_done : STD_LOGIC := '0'; SIGNAL transfer_done : STD_LOGIC := '0';
...@@ -129,18 +135,32 @@ BEGIN ...@@ -129,18 +135,32 @@ BEGIN
proc_common_wait_until_high(clk, init_done); proc_common_wait_until_high(clk, init_done);
FOR i IN 0 TO c_nof_blocks-1 LOOP FOR i IN 0 TO c_nof_blocks-1 LOOP
start_address <= i * g_data_size; start_address <= i * g_data_size;
start_pulse <= '1'; start_pulse <= '1';
proc_common_wait_some_cycles(clk, 1); proc_common_wait_some_cycles(clk, 1);
start_pulse <= '0'; start_pulse <= '0';
stop_address <= start_address + (g_nof_data - 1) * g_step_size + g_data_size - 1;
proc_common_wait_until_high(clk, block_done); proc_common_wait_until_high(clk, block_done);
END LOOP; END LOOP;
proc_common_wait_some_cycles(clk, 1); -- needed for dp_block_to_mm to proccess last word. proc_common_wait_some_cycles(clk, 1); -- Needed for dp_block_to_mm to proccess last word.
transfer_done <= '1'; transfer_done <= '1';
WAIT; WAIT;
END PROCESS; END PROCESS;
p_verify_read : PROCESS p_verify_transfer : PROCESS
BEGIN
proc_common_wait_until_high(clk, init_done);
WHILE tb_end = '0' LOOP
WAIT UNTIL rising_edge(clk);
IF block_done = '1' THEN
ASSERT stop_address = TO_UINT(wr_mosi.wrdata(c_ram.dat_w-1 DOWNTO 0)) REPORT "wrong data at mm_done signal, must be same as stop_address" SEVERITY ERROR;
END IF;
END LOOP;
WAIT;
END PROCESS;
p_read_ram : PROCESS
BEGIN BEGIN
ram_rd_en <= '0'; ram_rd_en <= '0';
ram_rd_adr <= TO_UVEC(0 , c_ram.adr_w); ram_rd_adr <= TO_UVEC(0 , c_ram.adr_w);
...@@ -157,15 +177,24 @@ BEGIN ...@@ -157,15 +177,24 @@ BEGIN
WAIT; WAIT;
END PROCESS; END PROCESS;
p_verify_check: PROCESS ram_prev_rd_val <= ram_rd_val WHEN rising_edge(clk);
VARIABLE v_cnt: NATURAL := 0;
p_verify_read_ram_data: PROCESS
BEGIN BEGIN
rd_nxt_data <= 1;
proc_common_wait_until_high(clk, transfer_done); proc_common_wait_until_high(clk, transfer_done);
WHILE tb_end = '0' LOOP WHILE tb_end = '0' LOOP
WAIT UNTIL rising_edge(clk); WAIT UNTIL rising_edge(clk);
rd_data <= TO_UINT(ram_rd_dat);
IF rd_data > 0 THEN
IF ram_rd_val = '1' THEN IF ram_rd_val = '1' THEN
ASSERT v_cnt = TO_UINT(ram_rd_dat) REPORT "RAM values not equal" SEVERITY ERROR; ASSERT rd_data = rd_nxt_data REPORT "wrong order of RAM values" SEVERITY ERROR;
v_cnt := v_cnt + 1; ASSERT rd_data <= stop_address REPORT "wrong RAM values, greater then block size" SEVERITY ERROR;
rd_nxt_data <= rd_nxt_data + 1;
END IF;
IF ram_rd_val = '0' AND ram_prev_rd_val = '1' THEN -- If ram_rd_val goes from hi tot lo.
ASSERT rd_data = stop_address REPORT "wrong last RAM values, not same as block size" SEVERITY ERROR;
END IF;
END IF; END IF;
END LOOP; END LOOP;
WAIT; WAIT;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment