Skip to content
GitLab
Explore
Sign in
Register
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
1cace676
Commit
1cace676
authored
10 years ago
by
Eric Kooistra
Browse files
Options
Downloads
Patches
Plain Diff
No need to use wr_fifo_usedw, because snk_in.valid does not need to remain active during the burst.
parent
cb55bd71
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
libraries/io/ddr/src/vhdl/io_ddr.vhd
+10
-12
10 additions, 12 deletions
libraries/io/ddr/src/vhdl/io_ddr.vhd
libraries/io/ddr/src/vhdl/io_ddr_driver.vhd
+61
-103
61 additions, 103 deletions
libraries/io/ddr/src/vhdl/io_ddr_driver.vhd
with
71 additions
and
115 deletions
libraries/io/ddr/src/vhdl/io_ddr.vhd
+
10
−
12
View file @
1cace676
...
...
@@ -44,14 +44,11 @@
-- Block diagram:
--
--
-- ctlr_wr_fifo_src ctlr_wr_snk ctlr_mosi
-- . . .
-- ________ . . _______ . ______
-- | |-----.-------------.->| | . | |
-- | | . ______ . | | . | |
-- wr_fifo_usedw <---|dp_fifo | . | | . | | . | |
-- wr_sosi --------->|dc_mixed|-+----->|dp |----->| io | . | tech |
-- wr_clk --------->|widths | | |flush | | ddr | . | ddr |
-- ctlr_wr_fifo_src ctlr_wr_snk ctlr_mosi
-- ________ . ______ . _______ . ______
-- wr_fifo_usedw <---|dp_fifo | . |dp | . | | . | |
-- wr_sosi --------->|dc_mixed|-+----->|flush |----->| io | . | tech |
-- wr_clk --------->|widths | | | | | ddr | . | ddr |
-- |________| | |______|<--\ | driver| . | |
-- | | | | . | |
-- | ctlr_wr_flush_en| | | . | |
...
...
@@ -199,7 +196,9 @@ ARCHITECTURE str OF io_ddr IS
SIGNAL
ctlr_rd_src_in
:
t_dp_siso
;
SIGNAL
ctlr_rd_src_out
:
t_dp_sosi
:
=
c_dp_sosi_rst
;
SIGNAL
ctlr_wr_fifo_usedw
:
STD_LOGIC_VECTOR
(
ceil_log2
(
g_wr_fifo_depth
)
-1
DOWNTO
0
);
-- read side depth of the write FIFO
-- Monitor only
SIGNAL
ctlr_wr_fifo_usedw
:
STD_LOGIC_VECTOR
(
ceil_log2
(
g_wr_fifo_depth
)
-1
DOWNTO
0
);
-- read side depth of the write FIFO
SIGNAL
ctlr_rd_fifo_usedw
:
STD_LOGIC_VECTOR
(
ceil_log2
(
g_rd_fifo_depth
)
-1
DOWNTO
0
);
-- write side depth of the read FIFO
BEGIN
...
...
@@ -312,7 +311,7 @@ BEGIN
dvr_wr_not_rd
=>
ctlr_dvr_wr_not_rd
,
dvr_wr_flush_en
=>
ctlr_dvr_wr_flush_en
,
wr_sosi
=>
ctlr_wr_flush_snk_in
,
ctlr_
wr_sosi
=>
ctlr_wr_flush_snk_in
,
ctlr_wr_flush_en
=>
ctlr_wr_flush_en
);
...
...
@@ -335,7 +334,7 @@ BEGIN
snk_out
=>
ctlr_rd_src_in
,
snk_in
=>
ctlr_rd_src_out
,
wr_usedw
=>
OPEN
,
wr_usedw
=>
ctlr_rd_fifo_usedw
,
rd_usedw
=>
rd_fifo_usedw
,
rd_emp
=>
OPEN
,
...
...
@@ -357,7 +356,6 @@ BEGIN
dvr_nof_data
=>
ctlr_dvr_nof_data
,
dvr_done
=>
ctlr_dvr_done
,
wr_fifo_usedw
=>
ctlr_wr_fifo_usedw
,
wr_snk_in
=>
ctlr_wr_snk_in
,
wr_snk_out
=>
ctlr_wr_snk_out
,
...
...
This diff is collapsed.
Click to expand it.
libraries/io/ddr/src/vhdl/io_ddr_driver.vhd
+
61
−
103
View file @
1cace676
...
...
@@ -27,10 +27,8 @@
-- 256 bits for DDR3 with 64 bit DQ data. The block of data is located from
-- dvr_start_address to dvr_nof_data.
-- The io_ddr_driver takes care that the access is done in a number of bursts.
-- The write burst size depends on the maximum burst size, the remaining
-- block size and on the number of words available in the (external) FIFO as
-- indicated by wr_fifo_usedw. The read burst size depends on the maximum
-- burst size and the remaining block size.
-- The burst size for both write and read depends on the maximum burst size
-- and the remaining block size.
-- Remarks:
-- .
...
...
@@ -53,9 +51,8 @@ ENTITY io_ddr_driver IS
dvr_wr_not_rd
:
IN
STD_LOGIC
;
dvr_start_address
:
IN
STD_LOGIC_VECTOR
;
dvr_nof_data
:
IN
STD_LOGIC_VECTOR
;
dvr_done
:
OUT
STD_LOGIC
;
-- Requested wr or rd sequence is done
.
dvr_done
:
OUT
STD_LOGIC
;
-- Requested wr or rd sequence is done
wr_fifo_usedw
:
IN
STD_LOGIC_VECTOR
;
wr_snk_in
:
IN
t_dp_sosi
;
wr_snk_out
:
OUT
t_dp_siso
;
...
...
@@ -73,101 +70,65 @@ ARCHITECTURE str OF io_ddr_driver IS
CONSTANT
c_ctlr_address_w
:
NATURAL
:
=
func_tech_ddr_ctlr_address_w
(
g_tech_ddr
);
CONSTANT
c_margin
:
NATURAL
:
=
2
;
-- wr_burst_size is updated one cycle after reading actual nof available words.
-- Subtract two (wr_fifo_usedw and wr_burst_size are both registered) so we cannot
-- post a request for a too large burst size, which could cause the wr_burst state
-- to be two valid words short.
TYPE
t_state_enum
IS
(
s_init
,
s_idle
,
s_wait1
,
s_wait2
,
s_wait3
,
s_rd_request
,
s_wr_request
,
s_wr_burst
);
TYPE
t_state_enum
IS
(
s_init
,
s_idle
,
s_wait
,
s_rd_request
,
s_wr_request
,
s_wr_burst
);
SIGNAL
state
:
t_state_enum
;
SIGNAL
nxt_state
:
t_state_enum
;
SIGNAL
prev_state
:
t_state_enum
;
SIGNAL
wr_burst_size
:
NATURAL
RANGE
0
TO
2
**
g_tech_ddr
.
maxburstsize_w
-1
;
SIGNAL
rd_burst_size
:
NATURAL
RANGE
0
TO
2
**
g_tech_ddr
.
maxburstsize_w
-1
;
SIGNAL
nxt_wr_burst_size
:
NATURAL
;
SIGNAL
nxt_rd_burst_size
:
NATURAL
;
SIGNAL
burst_wr_cnt
:
STD_LOGIC_VECTOR
(
g_tech_ddr
.
maxburstsize_w
-1
DOWNTO
0
);
-- count down from wr_burst_size to 0
SIGNAL
burst_size
:
POSITIVE
RANGE
1
TO
2
**
g_tech_ddr
.
maxburstsize_w
-1
;
-- burst size >= 1
SIGNAL
nxt_burst_size
:
POSITIVE
;
SIGNAL
burst_wr_cnt
:
STD_LOGIC_VECTOR
(
g_tech_ddr
.
maxburstsize_w
-1
DOWNTO
0
);
-- count down from burst_size to 0
SIGNAL
nxt_burst_wr_cnt
:
STD_LOGIC_VECTOR
(
g_tech_ddr
.
maxburstsize_w
-1
DOWNTO
0
);
SIGNAL
i_dvr_done
:
STD_LOGIC
;
SIGNAL
nxt_dvr_done
:
STD_LOGIC
;
SIGNAL
cur_address
:
STD_LOGIC_VECTOR
(
c_ctlr_address_w
-1
DOWNTO
0
);
SIGNAL
nxt_cur_address
:
STD_LOGIC_VECTOR
(
c_ctlr_address_w
-1
DOWNTO
0
);
SIGNAL
address_cnt
:
STD_LOGIC_VECTOR
(
c_ctlr_address_w
-1
DOWNTO
0
);
-- count down nof addresses = nof ctlr data words
SIGNAL
nxt_address_cnt
:
STD_LOGIC_VECTOR
(
c_ctlr_address_w
-1
DOWNTO
0
);
SIGNAL
reg_address_cnt
:
STD_LOGIC_VECTOR
(
c_ctlr_address_w
-1
DOWNTO
0
);
SIGNAL
reg_wr_fifo_usedw
:
STD_LOGIC_VECTOR
(
wr_fifo_usedw
'RANGE
);
-- available nof ctlr data words for a burst in at read side the write FIFO
BEGIN
dvr_done
<=
i_dvr_done
;
p_clk
:
PROCESS
(
rst
,
clk
)
BEGIN
IF
rst
=
'1'
THEN
state
<=
s_init
;
burst_wr_cnt
<=
(
OTHERS
=>
'0'
);
i_
dvr_done
<=
'0'
;
dvr_done
<=
'0'
;
cur_address
<=
(
OTHERS
=>
'0'
);
address_cnt
<=
(
OTHERS
=>
'0'
);
wr_burst_size
<=
0
;
rd_burst_size
<=
0
;
reg_address_cnt
<=
(
OTHERS
=>
'0'
);
reg_wr_fifo_usedw
<=
(
OTHERS
=>
'0'
);
burst_size
<=
1
;
prev_state
<=
s_idle
;
ELSIF
rising_edge
(
clk
)
THEN
state
<=
nxt_state
;
burst_wr_cnt
<=
nxt_burst_wr_cnt
;
i_
dvr_done
<=
nxt_dvr_done
;
dvr_done
<=
nxt_dvr_done
;
cur_address
<=
nxt_cur_address
;
address_cnt
<=
nxt_address_cnt
;
wr_burst_size
<=
nxt_wr_burst_size
;
rd_burst_size
<=
nxt_rd_burst_size
;
reg_address_cnt
<=
address_cnt
;
reg_wr_fifo_usedw
<=
wr_fifo_usedw
;
burst_size
<=
nxt_burst_size
;
prev_state
<=
state
;
END
IF
;
END
PROCESS
;
p_wr_burst_size
:
PROCESS
(
reg_address_cnt
,
reg_wr_fifo_usedw
)
VARIABLE
v_burst_size
:
POSITIVE
;
p_burst_size
:
PROCESS
(
address_cnt
)
BEGIN
-- Write burst size is at least 1 and if more then set to the smallest of g_tech_ddr.maxburstsize, address_cnt and wr_fifo_usedw
IF
UNSIGNED
(
reg_wr_fifo_usedw
)
>
c_margin
AND
UNSIGNED
(
reg_address_cnt
)
>
c_margin
THEN
v_burst_size
:
=
g_tech_ddr
.
maxburstsize
+
c_margin
;
IF
v_burst_size
>
UNSIGNED
(
reg_address_cnt
)
THEN
v_burst_size
:
=
TO_UINT
(
reg_address_cnt
);
END
IF
;
IF
v_burst_size
>
UNSIGNED
(
reg_wr_fifo_usedw
)
THEN
v_burst_size
:
=
TO_UINT
(
reg_wr_fifo_usedw
);
END
IF
;
v_burst_size
:
=
v_burst_size
-
c_margin
;
ELSE
v_burst_size
:
=
1
;
-- Access burst size is at least 1 and if more then set to the smallest of g_tech_ddr.maxburstsize and address_cnt
nxt_burst_size
<=
1
;
IF
UNSIGNED
(
address_cnt
)
>
0
THEN
nxt_burst_size
<=
g_tech_ddr
.
maxburstsize
;
IF
UNSIGNED
(
address_cnt
)
<
g_tech_ddr
.
maxburstsize
THEN
nxt_burst_size
<=
TO_UINT
(
address_cnt
);
END
IF
;
END
IF
;
nxt_wr_burst_size
<=
v_burst_size
;
END
PROCESS
;
p_rd_burst_size
:
PROCESS
(
reg_address_cnt
)
VARIABLE
v_burst_size
:
POSITIVE
;
BEGIN
-- Read burst size is at least 1 and if more then set to the smallest of g_tech_ddr.maxburstsize and address_cnt
IF
UNSIGNED
(
reg_address_cnt
)
>
0
THEN
v_burst_size
:
=
g_tech_ddr
.
maxburstsize
;
IF
v_burst_size
>
UNSIGNED
(
reg_address_cnt
)
THEN
v_burst_size
:
=
TO_UINT
(
reg_address_cnt
);
END
IF
;
ELSE
v_burst_size
:
=
1
;
END
IF
;
nxt_rd_burst_size
<=
v_burst_size
;
END
PROCESS
;
rd_src_out
.
valid
<=
ctlr_miso
.
rdval
;
rd_src_out
.
data
<=
RESIZE_DP_DATA
(
ctlr_miso
.
rddata
);
p_state
:
PROCESS
(
prev_state
,
state
,
ctlr_init_done
,
dvr_en
,
dvr_wr_not_rd
,
i_dvr_done
,
ctlr_miso
,
burst_wr_cnt
,
wr_snk_in
,
rd_src_in
,
wr_fifo_usedw
,
wr_
burst_size
,
rd_
burst_
size
,
reg_address
_cnt
,
dvr_start_address
,
cur_address
,
address_cnt
)
dvr_en
,
dvr_wr_not_rd
,
ctlr_miso
,
wr_snk_in
,
rd_src_in
,
burst_size
,
burst_
wr
_cnt
,
dvr_start_address
,
cur_address
,
address_cnt
)
BEGIN
nxt_state
<=
state
;
...
...
@@ -180,25 +141,26 @@ BEGIN
wr_snk_out
.
ready
<=
'0'
;
nxt_burst_wr_cnt
<=
burst_wr_cnt
;
nxt_dvr_done
<=
i_dvr_done
;
nxt_dvr_done
<=
'0'
;
nxt_cur_address
<=
cur_address
;
nxt_address_cnt
<=
address_cnt
;
CASE
state
IS
WHEN
s_wr_burst
=>
-- Performs the burst portion (word 2+)
ctlr_mosi
.
wr
<=
'1'
;
IF
ctlr_miso
.
waitrequest_n
=
'1'
THEN
nxt_burst_wr_cnt
<=
INCR_UVEC
(
burst_wr_cnt
,
-1
);
wr_snk_out
.
ready
<=
'1'
;
-- wr side uses latency of 0, so wr_snk_out.ready<='1' acknowledges a successful write request.
IF
UNSIGNED
(
burst_wr_cnt
)
=
1
THEN
-- check for the last cycle of this burst sequence
nxt_state
<=
s_wr_request
;
-- initiate a new wr burst or goto idle via the wr_request state
IF
wr_snk_in
.
valid
=
'1'
THEN
-- it is allowed that valid is not always active during a burst
wr_snk_out
.
ready
<=
'1'
;
-- wr side uses latency of 0, so wr_snk_out.ready<='1' acknowledges a successful write request.
ctlr_mosi
.
wr
<=
'1'
;
nxt_burst_wr_cnt
<=
INCR_UVEC
(
burst_wr_cnt
,
-1
);
IF
UNSIGNED
(
burst_wr_cnt
)
=
1
THEN
-- check for the last cycle of this burst sequence
nxt_state
<=
s_wr_request
;
-- initiate a new wr burst or goto idle via the wr_request state
END
IF
;
END
IF
;
END
IF
;
WHEN
s_wr_request
=>
-- Performs 1 write access and goes into s_wr_burst when requested write words >1
nxt_state
<=
s_wait3
;
IF
UNSIGNED
(
reg_address_cnt
)
=
0
THEN
-- end address reached
IF
UNSIGNED
(
address_cnt
)
=
0
THEN
-- end address reached
nxt_dvr_done
<=
'1'
;
nxt_state
<=
s_idle
;
ELSIF
ctlr_miso
.
waitrequest_n
=
'1'
THEN
...
...
@@ -206,61 +168,57 @@ BEGIN
-- Always perform 1st write here
wr_snk_out
.
ready
<=
'1'
;
ctlr_mosi
.
wr
<=
'1'
;
ctlr_mosi
.
burstbegin
<=
'1'
;
-- assert burstbegin,
ctlr_mosi
.
burstsize
<=
TO_DDR_CTLR_BURSTSIZE
(
wr_burst_size
);
-- burstsize >= 1
IF
wr_burst_size
>
1
THEN
-- Perform any remaining writes in a burst
ctlr_mosi
.
burstbegin
<=
'1'
;
-- assert burstbegin,
ctlr_mosi
.
burstsize
<=
TO_DDR_CTLR_BURSTSIZE
(
burst_size
);
-- burstsize >= 1
nxt_cur_address
<=
INCR_UVEC
(
cur_address
,
burst_size
);
nxt_address_cnt
<=
INCR_UVEC
(
address_cnt
,
-
burst_size
);
-- Return for next wr request or perform any remaining writes in this burst
nxt_state
<=
s_wait
;
IF
burst_size
>
1
THEN
nxt_state
<=
s_wr_burst
;
nxt_burst_wr_cnt
<=
TO_DDR_CTLR_BURSTSIZE
(
wr_burst_size
-1
);
-- first burst wr cycle is done here, the rest are done in s_wr_burst
END
IF
;
-- ELSE: there is only 1 word, so no need for remaining burst
nxt_cur_address
<=
INCR_UVEC
(
cur_address
,
wr_burst_size
);
nxt_address_cnt
<=
INCR_UVEC
(
address_cnt
,
-
wr_burst_size
);
nxt_burst_wr_cnt
<=
TO_DDR_CTLR_BURSTSIZE
(
burst_size
-1
);
-- first burst wr cycle is done here, the rest are done in s_wr_burst
END
IF
;
END
IF
;
END
IF
;
WHEN
s_rd_request
=>
-- Posts a read request for a burst (1...g_tech_ddr.maxburstsize)
nxt_state
<=
s_wait3
;
IF
UNSIGNED
(
reg_address_cnt
)
=
0
THEN
-- end address reached
IF
UNSIGNED
(
address_cnt
)
=
0
THEN
-- end address reached
nxt_dvr_done
<=
'1'
;
nxt_state
<=
s_idle
;
ELSE
IF
rd_src_in
.
ready
=
'1'
THEN
--
Fifo uses its internal
almost
_
full
signal to toggle
its snk_out.rdy
IF
rd_src_in
.
ready
=
'1'
THEN
--
the external FIFO uses
almost
full
level assert
its snk_out.r
ea
dy
and can then still accept the maximum rd burst of words
IF
ctlr_miso
.
waitrequest_n
=
'1'
THEN
ctlr_mosi
.
rd
<=
'1'
;
ctlr_mosi
.
burstbegin
<=
'1'
;
-- assert burstbegin,
ctlr_mosi
.
burstsize
<=
TO_DDR_CTLR_BURSTSIZE
(
rd_burst_size
);
-- burstsize >= 1
nxt_cur_address
<=
INCR_UVEC
(
cur_address
,
rd_burst_size
);
nxt_address_cnt
<=
INCR_UVEC
(
address_cnt
,
-
rd_burst_size
);
ctlr_mosi
.
burstbegin
<=
'1'
;
-- assert burstbegin,
ctlr_mosi
.
burstsize
<=
TO_DDR_CTLR_BURSTSIZE
(
burst_size
);
-- burstsize >= 1
nxt_cur_address
<=
INCR_UVEC
(
cur_address
,
burst_size
);
nxt_address_cnt
<=
INCR_UVEC
(
address_cnt
,
-
burst_size
);
-- Return for next rd request
nxt_state
<=
s_wait
;
END
IF
;
END
IF
;
END
IF
;
-- This wait state is inserted between two requests when necessary, e.g. when FSM enters wr_request
-- from the state wr_request, an extra cycle is needed for reg_address_cnt to be valid.
WHEN
s_wait3
=>
IF
prev_state
=
s_wr_request
THEN
nxt_state
<=
s_wr_request
;
END
IF
;
IF
prev_state
=
s_rd_request
THEN
nxt_state
<=
s_rd_request
;
END
IF
;
-- In this cycle reg_address_cnt is valid. This cycle is added so wr_burst_size and rd_burst_size
-- (derived from reg_address_cnt) are valid the next cycle.
WHEN
s_wait2
=>
IF
dvr_wr_not_rd
=
'1'
THEN
nxt_state
<=
s_wr_request
;
ELSE
nxt_state
<=
s_rd_request
;
END
IF
;
-- Wait a cycle so reg_address_cnt is valid the next cyle.
WHEN
s_wait1
=>
nxt_state
<=
s_wait2
;
-- In this state address_cnt is valid and in the next state burst_size (that depends on address_cnt) will be valid.
-- Therefore this wait state is inserted between any requests.
WHEN
s_wait
=>
IF
prev_state
=
s_wr_request
THEN
nxt_state
<=
s_wr_request
;
END
IF
;
-- between wr-wr burst requests
IF
prev_state
=
s_rd_request
THEN
nxt_state
<=
s_rd_request
;
END
IF
;
-- between rd-rd burst requests
IF
prev_state
=
s_idle
THEN
-- between wr and rd accesses
IF
dvr_wr_not_rd
=
'1'
THEN
nxt_state
<=
s_wr_request
;
ELSE
nxt_state
<=
s_rd_request
;
END
IF
;
END
IF
;
WHEN
s_idle
=>
nxt_dvr_done
<=
'1'
;
-- assert dvr_done after s_init or keep it asserted after a finished access
IF
dvr_en
=
'1'
THEN
nxt_cur_address
<=
dvr_start_address
;
nxt_address_cnt
<=
dvr_nof_data
;
nxt_dvr_done
<=
'0'
;
nxt_state
<=
s_wait
1
;
nxt_state
<=
s_wait
;
END
IF
;
WHEN
OTHERS
=>
-- s_init
...
...
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