Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393
Commits
b482a8ea
Commit
b482a8ea
authored
Mar 24, 2019
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Compressor bypass for raw (uncompressed) data
parent
596bdb62
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
223 additions
and
0 deletions
+223
-0
cmprs_raw_buf_iface.v
compressor_jp/cmprs_raw_buf_iface.v
+223
-0
No files found.
compressor_jp/cmprs_raw_buf_iface.v
0 → 100644
View file @
b482a8ea
/*!
* <b>Module:</b>cmprs_raw_buf_iface
* @file cmprs_raw_buf_iface.v
* @date 2015-06-11
* @author Andrey Filippov
*
* @brief Communicates with compressor memory buffer in raw (uncompressed) mode
*
* @copyright Copyright (c) 2019 Elphel, Inc.
*
* <b>License:</b>
*
* cmprs_raw_buf_iface.v 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.
*
* cmprs_raw_buf_iface.v 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/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*/
`timescale
1
ns
/
1
ps
module
cmprs_raw_buf_iface
#(
// parameter DCT_PIPELINE_PAUSE = 48, // TODO: find really required value (minimal), adjust counter bits (now 6)
// // 48 seems to be OK (may be less)
parameter
FRAME_QUEUE_WIDTH
=
2
)(
input
xclk
,
// global clock input, compressor single clock rate
input
mclk
,
// global clock for commands (posedge) and write side of the memory buffer (negedge)
input
mrst
,
// @posedge mclk, sync reset
input
xrst
,
// @posedge xclk, sync reset
// Page is limited by 1kB or end of line
// buffer interface, DDR3 memory read
input
xfer_reset_page_rd
,
// @ negedge mclk - reset ddr3 memory buffer. Use it to reset the read buffer too
input
page_ready_chn
,
// single mclk (posedge)
output
next_page_chn
,
// single mclk (posedge): Done with the page in the buffer, memory controller may read more data
// will be externally combined with "uncompressed"
input
frame_en
,
// if 0 - will reset logic immediately (but not the page number)
input
frame_start_xclk
,
// frame parameters are valid after this pulse (re-clocked from the memory controller)
input
frame_go
,
// start frame: if idle, will start reading data (if available),
// if running - will not restart a new frame if 0.
input
cmprs_run_mclk
,
// 0 - off or stopping, reset frame_pre_run
// input [ 4:0] left_marg, // left margin (for not-yet-implemented) mono JPEG (8 lines tile row) can need 7 bits (mod 32 - tile)
input
[
12
:
0
]
n_blocks_in_row_m1
,
// number of macroblocks in a macroblock row minus 1
input
[
12
:
0
]
n_block_rows_m1
,
// number of macroblock rows in a frame minus 1
input
stuffer_running
,
// @xclk, active while bit stuffer or trailer are running
input
raw_be16
,
// 0: bytes 0-1-2-3-4-5..., 1: bytes 1-0-3-2-5-4...
output
[
11
:
0
]
buf_ra
,
// buffer read address (2 MSB - page number)
output
[
1
:
0
]
buf_rd
,
// buf {regen, re}
output
raw_start
,
// was color_first leading edge
output
raw_prefb
,
// input
output
raw_ts_copy
,
// input
output
raw_flush
// input
)
;
// TODO:
wire
reset_page_rd
;
// xfer_reset_page_rd @ xclk
wire
page_ready
;
// page_ready_chn @ xclk
wire
frame_en_w
;
reg
frame_en_r
;
wire
frame_pre_start_w
;
// start sequence for a new frame
reg
frame_pre_start_r
;
reg
frame_start_xclk_r
;
// next cycle after frame_start_xclk
reg
cmprs_run_xclk
;
reg
frame_pre_run
;
reg
[
FRAME_QUEUE_WIDTH
:
0
]
frame_que_cntr
;
// width+1
reg
[
1
:
0
]
frame_finish_r
;
// active after last macroblock in a frame
reg
[
2
:
0
]
next_valid
;
// number of next valid page (only 2 LSB are actual page number)
reg
[
2
:
0
]
needed_page
;
// calculate at MB start
wire
[
2
:
0
]
buf_diff
;
// difference between page needed and next valid - should be negative to have it ready
wire
buf_ready_w
;
// External memory buffer has all the pages needed
reg
[
14
:
0
]
quads_left
;
// number of quad bytes left in a row (after this)
reg
[
16
:
0
]
rows_left
;
// number of rows left (after this)
reg
[
1
:
0
]
rows_last
;
reg
page_run
;
reg
[
3
:
0
]
quad_r
;
reg
quad_last
;
// last quad byte in a row should be valid @quad_r[2]
wire
page_start
;
wire
page_end_w
;
wire
release_buf
;
// send required "next_page" pulses to buffer. Having rather long minimal latency in the memory
wire
frame_finish_w
;
wire
frames_pending
;
reg
starting
;
// from frame_start_r to first page start
assign
frame_en_w
=
frame_en
&&
frame_go
;
// both are inputs
// one extra at the end of frame is needed (sequence will be short) ???
//// assign mb_pre_start_w = mb_pre_end_in || (frame_start_xclk_r && !frame_pre_run); // && !starting);
// repeated start (if some are pending) and for the first frame
assign
frame_pre_start_w
=
(
frames_pending
&&
frame_finish_w
)
||
(
frame_start_xclk_r
&&
!
frame_pre_run
&&
!
starting
)
;
assign
buf_diff
=
needed_page
-
next_valid
;
assign
buf_ready_w
=
buf_diff
[
2
]
;
assign
page_start
=
!
page_run
&&
buf_ready_w
&&
frame_pre_run
&&
(
starting
&&
stuffer_running
)
;
// frame_pre_run should deassert in time with frame end
reg
page_end_r
;
assign
raw_start
=
frame_pre_start_r
;
// for JP - leading edge of color_first
assign
page_end_w
=
frame_en
&&
quad_r
[
2
]
&&
(
&
bufa_r
[
9
:
2
]
||
quad_last
)
;
assign
release_buf
=
page_end_w
;
assign
frame_finish_w
=
frame_finish_r
[
1
]
&&
!
frame_finish_r
[
0
]
;
assign
frames_pending
=
!
frame_que_cntr
[
FRAME_QUEUE_WIDTH
]
&&
(
|
frame_que_cntr
[
FRAME_QUEUE_WIDTH
-
1
:
0
])
;
assign
frame_en_w
=
frame_en
&&
frame_go
;
assign
raw_prefb
=
buf_rd_r
[
0
]
;
// delay if memory registered more. TODO Add parameter if it already used
assign
raw_ts_copy
=
frame_en_r
&&
rows_last
[
0
]
&&
!
rows_last
[
1
]
;
reg
[
11
:
0
]
bufa_r
;
// buffer read address (2 MSB - page number)
reg
[
1
:
0
]
buf_rd_r
;
assign
raw_flush
=
frame_finish_w
;
assign
buf_ra
=
bufa_r
;
assign
buf_rd
=
buf_rd_r
[
1
:
0
]
;
always
@
(
posedge
xclk
)
begin
// pages read from the external memory, previous one is the last in the buffer
if
(
reset_page_rd
)
next_valid
<=
0
;
else
if
(
page_ready
)
next_valid
<=
next_valid
+
1
;
cmprs_run_xclk
<=
cmprs_run_mclk
;
frame_pre_start_r
<=
frame_pre_start_w
;
// same time as mb_pre_start
if
(
!
frame_en
)
frame_start_xclk_r
<=
0
;
else
frame_start_xclk_r
<=
frame_start_xclk
;
if
(
!
frame_en
)
starting
<=
1'b0
;
else
if
(
frame_pre_start_w
)
starting
<=
1'b1
;
else
if
(
page_start
)
starting
<=
1'b0
;
if
(
!
frame_en
)
frame_en_r
<=
0
;
else
frame_en_r
<=
frame_en_w
;
// stays on?
if
(
!
cmprs_run_xclk
)
frame_que_cntr
<=
0
;
else
if
(
frame_start_xclk_r
&&
!
frame_pre_start_r
)
frame_que_cntr
<=
frame_que_cntr
+
1
;
else
if
(
!
frame_start_xclk_r
&&
frame_pre_start_r
)
frame_que_cntr
<=
frame_que_cntr
-
1
;
if
(
reset_page_rd
)
needed_page
[
2
:
0
]
<=
0
;
// together with next_valid, next_invalid
else
if
(
release_buf
)
begin
needed_page
<=
needed_page
+
1
;
end
page_end_r
<=
page_end_w
;
// quad_r[2] && (&bufa_r[9:2] || quad_last);
// page_run
if
(
!
frame_pre_run
)
page_run
<=
0
;
else
if
(
page_start
)
page_run
<=
1
;
else
if
(
quad_r
[
2
]
&&
page_end_r
)
page_run
<=
0
;
if
(
!
frame_pre_run
)
quad_r
<=
0
;
else
quad_r
<=
{
quad_r
[
2
:
0
]
,
page_start
|
(
quad_r
[
3
]
&
page_run
)
};
buf_rd_r
<=
{
buf_rd_r
[
0
]
,
page_start
|
(
|
quad_r
[
2
:
0
]
|
(
quad_r
[
3
]
&
page_run
))
};
if
(
!
frame_en
)
frame_finish_r
<=
0
;
else
frame_finish_r
<=
{
frame_finish_r
[
0
]
,
quad_r
[
2
]
&
quad_last
&
rows_last
[
0
]
};
//quads_left
if
(
frame_pre_start_r
||
(
quad_r
[
2
]
&&
quad_last
))
quads_left
<=
{
n_blocks_in_row_m1
,
2'b11
};
else
if
(
quad_r
[
2
])
quads_left
<=
quads_left
-
1
;
quad_last
<=
!
(
|
quads_left
)
;
// valid from 2 after frame_pre_start_r or after quad_r[3]
if
(
frame_pre_start_r
)
rows_left
<=
{
n_block_rows_m1
,
4'b1111
};
else
if
((
quad_r
[
2
]
&&
quad_last
))
rows_left
<=
rows_left
-
1
;
rows_last
<=
{
rows_last
[
0
]
,
~
(
|
rows_left
)
};
if
(
frame_pre_start_r
)
bufa_r
[
11
:
10
]
<=
needed_page
[
1
:
0
]
;
if
(
frame_pre_start_r
)
bufa_r
[
9
:
1
]
<=
0
;
else
if
(
quad_r
[
3
])
bufa_r
[
9
:
1
]
<=
bufa_r
[
9
:
1
]
+
1
;
if
(
frame_pre_start_r
)
bufa_r
[
0
]
<=
raw_be16
;
else
if
(
buf_rd_r
[
0
])
bufa_r
[
0
]
<=
~
bufa_r
[
0
]
;
if
(
!
frame_en
||
(
!
frames_pending
&&
frame_finish_w
))
frame_pre_run
<=
0
;
else
if
(
frame_pre_start_w
)
frame_pre_run
<=
1
;
end
reg
nmrst
;
always
@
(
negedge
mclk
)
nmrst
<=
mrst
;
// synchronization between mclk and xclk clock domains
// negedge mclk -> xclk (verify clock inversion is absorbed)
pulse_cross_clock
reset_page_rd_i
(
.
rst
(
nmrst
)
,
.
src_clk
(
~
mclk
)
,.
dst_clk
(
xclk
)
,
.
in_pulse
(
xfer_reset_page_rd
)
,
.
out_pulse
(
reset_page_rd
)
,
.
busy
())
;
// mclk -> xclk
pulse_cross_clock
page_ready_i
(
.
rst
(
mrst
)
,
.
src_clk
(
mclk
)
,
.
dst_clk
(
xclk
)
,
.
in_pulse
(
page_ready_chn
)
,
.
out_pulse
(
page_ready
)
,
.
busy
())
;
// xclk -> mclk
pulse_cross_clock
next_page_chn_i
(
.
rst
(
xrst
)
,
.
src_clk
(
xclk
)
,
.
dst_clk
(
mclk
)
,
.
in_pulse
(
page_end_r
)
,
.
out_pulse
(
next_page_chn
)
,
.
busy
())
;
endmodule
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment