Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
HDL
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
RTSD
HDL
Commits
7d5d0076
Commit
7d5d0076
authored
8 years ago
by
Pepping
Browse files
Options
Downloads
Patches
Plain Diff
Initial commit
parent
7fd88755
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
libraries/base/diag/src/vhdl/diag_data_buffer_dev.vhd
+373
-0
373 additions, 0 deletions
libraries/base/diag/src/vhdl/diag_data_buffer_dev.vhd
with
373 additions
and
0 deletions
libraries/base/diag/src/vhdl/diag_data_buffer_dev.vhd
0 → 100644
+
373
−
0
View file @
7d5d0076
-------------------------------------------------------------------------------
--
-- Copyright (C) 2011
-- 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/>.
--
-------------------------------------------------------------------------------
-- Purpose : Capture a block of streaming data for analysis via MM access
-- Description :
-- The first g_nof_data valid streaming data input words are stored in the
-- data buffer. Then they can be read via the MM interface. Dependend on
-- g_use_in_sync the nxt block of valid streaming data input words gets
-- stored when a new in_sync occurs or when the last word was read from via
-- the MM interface.
--
-- There are 3 modes of operation in the _dev version:
--
-- (1) NON-SYNC MODE: g_use_in_sync = FALSE
-- In this mode the first g_nof_data valid data input words are stored in the
-- data buffer. A new set of data will be stored when the last word is read
-- from the buffer via the MM interface.
--
-- (2) SYNC-MODE: g_use_in_sync = TRUE and reg_sync_delay = 0
-- On every received sync pulse a number of g_nof_data valid words are written
-- to the databuffer. Data will be overwritten on every new sync pulse. It is
-- up to the user to read out the data in time in between two sync pulses
--
-- (3) ARM-MODE: g_use_in_sync = TRUE and reg_sync_delay > 0
-- First the reg_sync_delay should be written with a desired delay value. Then
-- the arm register must be written. After being armed the databuffer will wait
-- for the first sync pulse to arrive. When it has arrived it will wait for
-- reg_sync_delay valid cycles before g_nof_data valid words are written to the
-- databuffer. The data can then be read out through the MM interface. New data
-- will only be written if the databuffer is being armed again.
--
-- Remarks:
-- . The actual RAM usage depends on g_data_w. Unused bits are forced to '0'
-- when read.
-- . The c_mm_factor must be a power of 2 factor. Typically c_mm_factor=1 is
-- sufficient for most purposes. If the application only requires
-- eg. c_mm_factor=3 then it needs to extend the data to c_mm_factor=4.
-- . If c_mm_factor=2 then in_data[g_data_w/2-1:0] will appear at MM address
-- even and in_data[g_data_w-1:g_data_w/2] at address odd.
-- The advantage of splitting at g_data_w/2 instead of at c_word_w=32 is
-- that streaming 36b data can then map on 18b RAM still fit in a single
-- RAM block. Whereas mapping the LS 32b part at even address and the MS 4b
-- part at odd address would require using c_word_w=32b RAM that could
-- require two RAM blocks. For g_data_w=2*c_word_w=64b there is no
-- difference between these 2 schemes. Hence by rising the g_data_w to a
-- power of 2 multiple of 32b the user can enforce using splitting the data
-- a c_word_w parts.
LIBRARY
IEEE
,
common_lib
,
technology_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
work
.
diag_pkg
.
ALL
;
USE
technology_lib
.
technology_select_pkg
.
ALL
;
ENTITY
diag_data_buffer_dev
IS
GENERIC
(
g_technology
:
NATURAL
:
=
c_tech_select_default
;
g_data_w
:
NATURAL
:
=
32
;
g_nof_data
:
NATURAL
:
=
1024
;
g_use_in_sync
:
BOOLEAN
:
=
FALSE
-- when TRUE start filling the buffer at the in_sync, else after the last word was read
);
PORT
(
-- Memory-mapped clock domain
mm_rst
:
IN
STD_LOGIC
;
mm_clk
:
IN
STD_LOGIC
;
ram_mm_mosi
:
IN
t_mem_mosi
;
-- read and overwrite access to the data buffer
ram_mm_miso
:
OUT
t_mem_miso
;
reg_mm_mosi
:
IN
t_mem_mosi
:
=
c_mem_mosi_rst
;
reg_mm_miso
:
OUT
t_mem_miso
;
-- Streaming clock domain
st_rst
:
IN
STD_LOGIC
;
st_clk
:
IN
STD_LOGIC
;
in_data
:
IN
STD_LOGIC_VECTOR
(
g_data_w
-1
DOWNTO
0
);
in_sync
:
IN
STD_LOGIC
:
=
'0'
;
in_val
:
IN
STD_LOGIC
);
END
diag_data_buffer_dev
;
ARCHITECTURE
rtl
OF
diag_data_buffer_dev
IS
CONSTANT
c_mm_factor
:
NATURAL
:
=
ceil_div
(
g_data_w
,
c_word_w
);
-- must be a power of 2 multiple
CONSTANT
c_nof_data_mm
:
NATURAL
:
=
g_nof_data
*
c_mm_factor
;
CONSTANT
g_data_mm_w
:
NATURAL
:
=
g_data_w
/
c_mm_factor
;
CONSTANT
c_buf_mm
:
t_c_mem
:
=
(
latency
=>
1
,
adr_w
=>
ceil_log2
(
c_nof_data_mm
),
dat_w
=>
g_data_mm_w
,
nof_dat
=>
c_nof_data_mm
,
init_sl
=>
'0'
);
CONSTANT
c_buf_st
:
t_c_mem
:
=
(
latency
=>
1
,
adr_w
=>
ceil_log2
(
g_nof_data
),
dat_w
=>
g_data_w
,
nof_dat
=>
g_nof_data
,
init_sl
=>
'0'
);
CONSTANT
c_reg
:
t_c_mem
:
=
(
latency
=>
1
,
adr_w
=>
c_diag_db_dev_reg_adr_w
,
dat_w
=>
c_word_w
,
-- Use MM bus data width = c_word_w = 32 for all MM registers
nof_dat
=>
c_diag_db_dev_reg_nof_dat
,
--3: reg_sync_delay 2: valid_cnt 1: word_cnt; 0:sync_cnt
init_sl
=>
'0'
);
SIGNAL
i_ram_mm_miso
:
t_mem_miso
:
=
c_mem_miso_rst
;
-- used to avoid vsim-8684 error "No drivers exist" for the unused fields
SIGNAL
rd_last
:
STD_LOGIC
;
SIGNAL
rd_last_st
:
STD_LOGIC
;
SIGNAL
wr_sync
:
STD_LOGIC
;
SIGNAL
wr_done
:
STD_LOGIC
;
SIGNAL
nxt_wr_done
:
STD_LOGIC
;
SIGNAL
wr_data
:
STD_LOGIC_VECTOR
(
c_buf_st
.
dat_w
-1
DOWNTO
0
);
SIGNAL
nxt_wr_data
:
STD_LOGIC_VECTOR
(
c_buf_st
.
dat_w
-1
DOWNTO
0
);
SIGNAL
wr_addr
:
STD_LOGIC_VECTOR
(
c_buf_st
.
adr_w
-1
DOWNTO
0
);
SIGNAL
nxt_wr_addr
:
STD_LOGIC_VECTOR
(
c_buf_st
.
adr_w
-1
DOWNTO
0
);
SIGNAL
wr_en
:
STD_LOGIC
;
SIGNAL
nxt_wr_en
:
STD_LOGIC
;
SIGNAL
reg_rd_arr
:
STD_LOGIC_VECTOR
(
c_reg
.
nof_dat
-1
DOWNTO
0
);
SIGNAL
reg_wr_arr
:
STD_LOGIC_VECTOR
(
c_reg
.
nof_dat
-1
DOWNTO
0
);
SIGNAL
reg_slv_rd
:
STD_LOGIC_VECTOR
(
c_reg
.
nof_dat
*
c_word_w
-1
DOWNTO
0
);
SIGNAL
reg_slv_wr
:
STD_LOGIC_VECTOR
(
c_reg
.
nof_dat
*
c_word_w
-1
DOWNTO
0
);
SIGNAL
arm_enable
:
STD_LOGIC
:
=
'0'
;
SIGNAL
sync_cnt_clr
:
STD_LOGIC
:
=
'0'
;
SIGNAL
sync_cnt
:
STD_LOGIC_VECTOR
(
c_word_w
-1
DOWNTO
0
);
-- Nof times buffer has been written
SIGNAL
word_cnt
:
STD_LOGIC_VECTOR
(
c_word_w
-1
DOWNTO
0
)
:
=
(
OTHERS
=>
'0'
);
SIGNAL
valid_cnt
:
STD_LOGIC_VECTOR
(
c_word_w
-1
DOWNTO
0
)
:
=
(
OTHERS
=>
'0'
);
SIGNAL
reg_sync_delay
:
STD_LOGIC_VECTOR
(
c_word_w
-1
DOWNTO
0
)
:
=
(
OTHERS
=>
'0'
);
TYPE
state_type
is
(
s_idle
,
s_sync_count
,
s_wait_for_rd_last
,
s_armed
);
TYPE
reg_type
IS
RECORD
wr_sync
:
STD_LOGIC
;
state
:
state_type
;
-- The state machine.
END
RECORD
;
SIGNAL
r
,
rin
:
reg_type
;
BEGIN
ASSERT
c_mm_factor
=
2
**
true_log2
(
c_mm_factor
)
REPORT
"Only support mixed width data that uses a power of 2 multiple."
SEVERITY
FAILURE
;
ram_mm_miso
<=
i_ram_mm_miso
;
rd_last
<=
'1'
WHEN
UNSIGNED
(
ram_mm_mosi
.
address
(
c_buf_mm
.
adr_w
-1
DOWNTO
0
))
=
c_nof_data_mm
-1
AND
ram_mm_mosi
.
rd
=
'1'
ELSE
'0'
;
u_rd_last_clock_cross
:
ENTITY
common_lib
.
common_spulse
GENERIC
MAP
(
g_delay_len
=>
c_meta_delay_len
)
PORT
MAP
(
in_rst
=>
mm_rst
,
in_clk
=>
mm_clk
,
in_pulse
=>
rd_last
,
out_rst
=>
st_rst
,
out_clk
=>
st_clk
,
out_pulse
=>
rd_last_st
);
-- Determine the write trigger in NON-SYNC MODE
use_rd_last
:
IF
g_use_in_sync
=
FALSE
GENERATE
wr_sync
<=
rd_last_st
;
END
GENERATE
;
-- Determine the write trigger in SYNC MODE and ARM MODE
use_in_sync
:
IF
g_use_in_sync
=
TRUE
GENERATE
comb
:
PROCESS
(
st_rst
,
r
,
in_sync
,
rd_last_st
,
reg_sync_delay
,
arm_enable
,
valid_cnt
)
VARIABLE
v
:
reg_type
;
BEGIN
v
:
=
r
;
v
.
wr_sync
:
=
'0'
;
CASE
r
.
state
IS
WHEN
s_idle
=>
IF
arm_enable
=
'1'
THEN
v
.
state
:
=
s_armed
;
END
IF
;
WHEN
s_armed
=>
IF
(
in_sync
=
'1'
AND
TO_UINT
(
reg_sync_delay
)
=
1
)
THEN
v
.
wr_sync
:
=
'1'
;
v
.
state
:
=
s_wait_for_rd_last
;
ELSIF
(
in_sync
=
'1'
AND
TO_UINT
(
reg_sync_delay
)
>
1
)
THEN
v
.
state
:
=
s_sync_count
;
END
IF
;
WHEN
s_sync_count
=>
IF
((
TO_UINT
(
valid_cnt
)
+
2
)
>=
TO_UINT
(
reg_sync_delay
))
THEN
v
.
wr_sync
:
=
'1'
;
v
.
state
:
=
s_wait_for_rd_last
;
END
IF
;
WHEN
s_wait_for_rd_last
=>
IF
rd_last_st
=
'1'
THEN
v
.
state
:
=
s_idle
;
ELSIF
arm_enable
=
'1'
THEN
v
.
state
:
=
s_armed
;
END
IF
;
WHEN
OTHERS
=>
v
.
state
:
=
s_idle
;
END
CASE
;
IF
st_rst
=
'1'
THEN
v
.
wr_sync
:
=
'0'
;
v
.
state
:
=
s_idle
;
END
IF
;
rin
<=
v
;
END
PROCESS
comb
;
regs
:
PROCESS
(
st_clk
)
BEGIN
IF
rising_edge
(
st_clk
)
THEN
r
<=
rin
;
END
IF
;
END
PROCESS
;
-- Choose between SYNC MODE and ARM MODE.
wr_sync
<=
in_sync
WHEN
TO_UINT
(
reg_sync_delay
)
=
0
ELSE
r
.
wr_sync
;
END
GENERATE
;
p_st_clk
:
PROCESS
(
st_clk
,
st_rst
)
BEGIN
IF
st_rst
=
'1'
THEN
wr_data
<=
(
OTHERS
=>
'0'
);
wr_addr
<=
(
OTHERS
=>
'0'
);
wr_en
<=
'0'
;
wr_done
<=
'0'
;
ELSIF
rising_edge
(
st_clk
)
THEN
wr_data
<=
nxt_wr_data
;
wr_addr
<=
nxt_wr_addr
;
wr_en
<=
nxt_wr_en
;
wr_done
<=
nxt_wr_done
;
END
IF
;
END
PROCESS
;
-- Write access control
nxt_wr_data
<=
in_data
;
nxt_wr_en
<=
in_val
AND
NOT
nxt_wr_done
;
p_wr_addr
:
PROCESS
(
wr_done
,
wr_addr
,
wr_sync
,
wr_en
)
BEGIN
nxt_wr_done
<=
wr_done
;
nxt_wr_addr
<=
wr_addr
;
IF
wr_sync
=
'1'
THEN
nxt_wr_done
<=
'0'
;
nxt_wr_addr
<=
(
OTHERS
=>
'0'
);
ELSIF
wr_en
=
'1'
THEN
IF
UNSIGNED
(
wr_addr
)
=
g_nof_data
-1
THEN
nxt_wr_done
<=
'1'
;
-- keep wr_addr, do not allow wr_addr increment >= g_nof_data to avoid RAM address out-of-bound warning in Modelsim in case c_buf.nof_dat < 2**c_buf.adr_w
ELSE
nxt_wr_addr
<=
INCR_UVEC
(
wr_addr
,
1
);
END
IF
;
END
IF
;
END
PROCESS
;
u_buf
:
ENTITY
common_lib
.
common_ram_crw_crw_ratio
GENERIC
MAP
(
g_technology
=>
g_technology
,
g_ram_a
=>
c_buf_mm
,
g_ram_b
=>
c_buf_st
,
g_init_file
=>
"UNUSED"
)
PORT
MAP
(
-- MM read/write port clock domain
rst_a
=>
mm_rst
,
clk_a
=>
mm_clk
,
wr_en_a
=>
ram_mm_mosi
.
wr
,
wr_dat_a
=>
ram_mm_mosi
.
wrdata
(
c_buf_mm
.
dat_w
-1
DOWNTO
0
),
adr_a
=>
ram_mm_mosi
.
address
(
c_buf_mm
.
adr_w
-1
DOWNTO
0
),
rd_en_a
=>
ram_mm_mosi
.
rd
,
rd_dat_a
=>
i_ram_mm_miso
.
rddata
(
c_buf_mm
.
dat_w
-1
DOWNTO
0
),
rd_val_a
=>
i_ram_mm_miso
.
rdval
,
-- ST write only port clock domain
rst_b
=>
st_rst
,
clk_b
=>
st_clk
,
wr_en_b
=>
wr_en
,
wr_dat_b
=>
wr_data
,
adr_b
=>
wr_addr
,
rd_en_b
=>
'0'
,
rd_dat_b
=>
OPEN
,
rd_val_b
=>
OPEN
);
u_reg
:
ENTITY
common_lib
.
common_reg_r_w_dc
GENERIC
MAP
(
g_reg
=>
c_reg
)
PORT
MAP
(
-- Clocks and reset
mm_rst
=>
mm_rst
,
mm_clk
=>
mm_clk
,
st_rst
=>
st_rst
,
st_clk
=>
st_clk
,
-- Memory Mapped Slave in mm_clk domain
sla_in
=>
reg_mm_mosi
,
sla_out
=>
reg_mm_miso
,
-- MM registers in st_clk domain
reg_wr_arr
=>
reg_wr_arr
,
reg_rd_arr
=>
reg_rd_arr
,
in_reg
=>
reg_slv_rd
,
out_reg
=>
reg_slv_wr
);
arm_enable
<=
reg_wr_arr
(
2
);
reg_sync_delay
<=
reg_slv_wr
(
4
*
c_word_w
-1
DOWNTO
3
*
c_word_w
);
reg_slv_rd
<=
reg_sync_delay
&
valid_cnt
&
word_cnt
&
sync_cnt
;
u_word_cnt
:
ENTITY
common_lib
.
common_counter
PORT
MAP
(
rst
=>
st_rst
,
clk
=>
st_clk
,
cnt_en
=>
wr_en
,
cnt_clr
=>
wr_sync
,
count
=>
word_cnt
);
u_sync_cnt
:
ENTITY
common_lib
.
common_counter
PORT
MAP
(
rst
=>
st_rst
,
clk
=>
st_clk
,
cnt_en
=>
wr_sync
,
cnt_clr
=>
sync_cnt_clr
,
count
=>
sync_cnt
);
u_valid_cnt
:
ENTITY
common_lib
.
common_counter
PORT
MAP
(
rst
=>
st_rst
,
clk
=>
st_clk
,
cnt_en
=>
in_val
,
cnt_clr
=>
in_sync
,
count
=>
valid_cnt
);
END
rtl
;
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment