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
8b1599eb
Commit
8b1599eb
authored
Jun 13, 2015
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on compressors interaction with external memory buffer
parent
72dc592d
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1045 additions
and
16 deletions
+1045
-16
membridge.v
axi/membridge.v
+1
-1
cmprs_macroblock_buf_iface.v
compressor_jp/cmprs_macroblock_buf_iface.v
+213
-0
cmprs_pixel_buf_iface.v
compressor_jp/cmprs_pixel_buf_iface.v
+256
-0
color_proc393.v
compressor_jp/color_proc393.v
+16
-10
multipulse_cross_clock.v
util_modules/multipulse_cross_clock.v
+64
-0
pulse_cross_clock.v
util_modules/pulse_cross_clock.v
+13
-5
ram18p_var_w_var_r.v
wrap/ram18p_var_w_var_r.v
+482
-0
No files found.
axi/membridge.v
View file @
8b1599eb
...
@@ -49,7 +49,7 @@ module membridge#(
...
@@ -49,7 +49,7 @@ module membridge#(
// mcntrl_linear_rw.v interface
// mcntrl_linear_rw.v interface
output
frame_start_chn
,
// input
output
frame_start_chn
,
// input
output
next_page_chn
,
// input
output
next_page_chn
,
// input
input
cmd_wrmem
,
//
input
cmd_wrmem
,
//
@mclk - writing to DDR3 mode (0 - reading from DDR3)
input
page_ready_chn
,
// output single mclk
input
page_ready_chn
,
// output single mclk
input
frame_done_chn
,
// output single mclk
input
frame_done_chn
,
// output single mclk
input
[
FRAME_HEIGHT_BITS
-
1
:
0
]
line_unfinished_chn1
,
// output[15:0] @SuppressThisWarning VEditor unused (yet)
input
[
FRAME_HEIGHT_BITS
-
1
:
0
]
line_unfinished_chn1
,
// output[15:0] @SuppressThisWarning VEditor unused (yet)
...
...
compressor_jp/cmprs_macroblock_buf_iface.v
0 → 100644
View file @
8b1599eb
/*******************************************************************************
* Module: cmprs_macroblock_buf_iface
* Date:2015-06-11
* Author: andrey
* Description: Communicates with compressor memory buffer, generates pixel
* stream matching selected color mode, accommodates for the buffer latency,
* acts as a pacemaker for the whole compressor (next stages are able to keep up).
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* cmprs_macroblock_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_macroblock_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/> .
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
cmprs_macroblock_buf_iface
#(
)(
input
rst
,
input
xclk
,
// global clock input, compressor single clock rate
input
mclk
,
// global clock for commands (posedge) and write side of the memory buffer (negedge)
// 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
input
frame_en
,
// if 0 - will reset logic immediately (but not page number)
input
frame_go
,
// start frame: if idle, will start reading data (if available),
// if running - will not restart a new frame if 0.
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
[
5
:
0
]
mb_w_m1
,
// macroblock width minus 1 // 3 LSB not used
input
[
4
:
0
]
mb_hper
,
// macroblock horizontal period (8/16) // 3 LSB not used
input
[
1
:
0
]
tile_width
,
// memory tile width (can be 128 for monochrome JPEG) Can be 32/64/128: 0 - 16, 1 - 32, 2 - 64, 3 - 128
input
mb_pre_end_in
,
// from cmprs_pixel_buf_iface - just in time to start a new macroblock w/o gaps
input
mb_release_buf
,
// send required "next_page" pulses to buffer. Having rather long minimal latency in the memory
// controller this can just be the same as mb_pre_end_in
output
mb_pre_start_out
,
// 1 clock cycle before stream of addresses to the buffer
output
[
1
:
0
]
start_page
,
// page to read next tile from (or first of several pages)
output
[
6
:
0
]
macroblock_x
// macroblock left pixel x relative to a tile (page) Maximal page - 128 bytes wide
)
;
wire
reset_page_rd
;
wire
page_ready
;
wire
frame_en_w
;
reg
frame_en_r
;
reg
[
12
:
0
]
mb_cols_left
;
// number of a macroblocks left in a row (after this)
reg
[
12
:
0
]
mb_rows_left
;
// number of a rows left in a row (after this)
wire
[
6
:
0
]
mbl_x
;
// macroblock left pixel x relative to a tile (page) Maximal page - 128 bytes wide
reg
[
6
:
3
]
mbl_x_r
;
// macroblock left pixel x relative to a tile (page) (3 low don't change)
reg
[
6
:
3
]
mbl_x_next_r
;
// macroblock left pixel x relative to a tile (page), not valid for first column (3 low don't change)
reg
[
7
:
3
]
mbl_x_inc_r
;
// intermediate register for calculating mbl_x_next_r and add_invalid
reg
[
7
:
3
]
mbl_x_last_r
;
// intermediate register for calculating needed_page
reg
[
1
:
0
]
pre_advance_tiles
;
// advance tiles by this for same row of macroblocks
wire
mb_pre_start_w
;
// start sequence for a macroblock
wire
frame_pre_start_w
;
// start sequence for a new frame
reg
frame_pre_start_r
;
reg
[
8
:
0
]
mb_pre_start
;
// 1-hot macroblock pre start calcualtions - TODO: adjust width
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
mb_first_in_row
;
reg
mb_last_in_row
;
reg
mb_last_row
;
wire
mb_last
;
reg
[
2
:
0
]
next_valid
;
// number of next valid page (only 2 LSB are actual page number)
reg
[
2
:
0
]
next_invalid
;
// oldest valid page
reg
[
1
:
0
]
add_invalid
;
// advance next_invalid pointer by this value, send next_page pulses
reg
[
2
:
0
]
used_pages
;
// number of pages simultaneously used for the last macroblock
reg
[
2
:
0
]
needed_page
;
// calculate at MB start
wire
starting
;
reg
frame_pre_run
;
assign
frame_en_w
=
frame_en
&&
frame_go
;
assign
mbl_x
={
mbl_x_r
[
6
:
3
]
,
left_marg
[
2
:
0
]
};
assign
buf_diff
=
needed_page
-
next_valid
;
assign
buf_ready_w
=
buf_diff
[
2
]
;
assign
mb_pre_start_out
=
mb_pre_start
[
5
]
;
// first after wait?
assign
macroblock_x
=
mbl_x
;
assign
mb_last
=
mb_last_row
&&
mb_last_in_row
;
assign
starting
=
|
mb_pre_start
;
assign
mb_pre_start_w
=
(
mb_pre_end_in
&&
(
!
mb_last
||
frame_en_w
))
||
(
!
frame_pre_run
&&
frame_en_w
&&
!
frame_en_r
&&
!
starting
)
;
assign
frame_pre_start_w
=
frame_en_w
&&
((
mb_pre_end_in
&&
mb_last
)
||
(
!
frame_pre_run
&&
!
frame_en_r
&&
!
starting
))
;
assign
start_page
=
next_invalid
[
1
:
0
]
;
// oldest page needed for this macroblock
always
@
(
posedge
xclk
)
begin
if
(
!
frame_en
)
frame_en_r
<=
0
;
else
frame_en_r
<=
frame_en_w
;
frame_pre_start_r
<=
frame_pre_start_w
;
// same time as mb_pre_start
if
(
!
frame_en
)
mb_first_in_row
<=
0
;
else
if
(
frame_pre_start_r
)
mb_first_in_row
<=
1
;
else
if
(
mb_pre_start
[
0
])
mb_first_in_row
<=
mb_last_in_row
;
if
(
!
frame_en
)
frame_pre_run
<=
0
;
else
if
(
mb_pre_start_w
)
frame_pre_run
<=
1
;
else
if
(
mb_pre_end_in
&&
mb_last
)
frame_pre_run
<=
0
;
if
(
frame_pre_start_r
)
mb_rows_left
<=
n_block_rows_m1
;
else
if
(
mb_pre_start
[
0
]
&&
mb_last_in_row
)
mb_rows_left
<=
mb_rows_left
-
1
;
if
(
frame_pre_start_r
||
(
mb_pre_start
[
0
]
&&
mb_last_in_row
))
mb_cols_left
<=
n_blocks_in_row_m1
;
else
if
(
mb_pre_start
[
0
])
mb_cols_left
<=
mb_cols_left
-
1
;
if
(
mb_pre_start
[
1
])
mb_last_row
<=
(
mb_rows_left
==
0
)
;
if
(
mb_pre_start
[
1
])
mb_last_in_row
<=
(
mb_cols_left
==
0
)
;
// 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
;
// calculate before starting each macroblock (will wait if buffer is not ready) (TODO: align mb_pre_start[0] to mb_pre_end[2] - same)
//mb_pre_start_w
if
(
mb_pre_start_w
)
mb_pre_start
<=
1
;
else
if
(
!
mb_pre_start
[
4
]
||
buf_ready_w
)
mb_pre_start
<=
mb_pre_start
<<
1
;
if
(
mb_pre_start
[
1
])
mbl_x_r
[
6
:
3
]
<=
mb_first_in_row
?
{
2'b0
,
left_marg
[
4
:
3
]
}
:
mbl_x_next_r
[
6
:
3
]
;
if
(
mb_pre_start
[
2
])
mbl_x_last_r
[
7
:
3
]
<=
{
1'b0
,
mbl_x_r
[
6
:
3
]
}
+
{
2'b0
,
mb_w_m1
[
5
:
3
]
};
if
(
mb_pre_start
[
3
])
begin
case
(
tile_width
)
2'b00
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
1'b0
,
mbl_x_last_r
[
5
:
4
]
};
2'b01
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
1'b0
,
mbl_x_last_r
[
6
:
5
]
};
2'b10
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
1'b0
,
mbl_x_last_r
[
7
:
6
]
};
2'b11
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
2'b0
,
mbl_x_last_r
[
7
]
};
endcase
end
// at the end of each macroblock - calculate start page increment (and after delay - advance invalidate_next)
// changed to after started:
// calculate next start X in page (regardless of emd of macroblock row - selection will be at macroblock start)
if
(
mb_pre_start
[
5
])
mbl_x_inc_r
[
7
:
3
]
<=
{
1'b0
,
mbl_x_r
[
6
:
3
]
}
+
{
3'b0
,
mb_hper
[
4
:
3
]
};
if
(
mb_pre_start
[
6
])
begin
case
(
tile_width
)
2'b00
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
3'b0
,
mbl_x_inc_r
[
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
mbl_x_inc_r
[
5
:
4
]
;
end
2'b01
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
2'b0
,
mbl_x_inc_r
[
4
:
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
mbl_x_inc_r
[
6
:
5
]
;
end
2'b10
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
1'b0
,
mbl_x_inc_r
[
5
:
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
mbl_x_inc_r
[
7
:
6
]
;
end
2'b11
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
mbl_x_inc_r
[
6
:
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
{
1'b0
,
mbl_x_inc_r
[
7
]
};
end
endcase
used_pages
<=
needed_page
-
next_invalid
+
1
;
end
if
(
mb_pre_start
[
7
])
begin
// TODO: apply after delay, regardless last or not
if
(
mb_last_in_row
)
add_invalid
<=
used_pages
[
1
:
0
]
;
else
add_invalid
<=
pre_advance_tiles
;
end
// pages already processed by compressor - they can be reused for reading new tiles
if
(
reset_page_rd
)
next_invalid
<=
0
;
else
if
(
mb_pre_start
[
8
])
next_invalid
<=
next_invalid
+
{
1'b0
,
add_invalid
};
// TODO: Send next_page after delay
// "next_page_ pulses will be sent near the end of the macroblock
end
// synchronization between mclk and xclk clock domains
// negedge mclk -> xclk (verify clock inversion is absorbed)
pulse_cross_clock
reset_page_rd_i
(
.
rst
(
rst
)
,
.
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
(
rst
)
,
.
src_clk
(
mclk
)
,
.
dst_clk
(
xclk
)
,
.
in_pulse
(
page_ready_chn
)
,
.
out_pulse
(
page_ready
)
,.
busy
())
;
multipulse_cross_clock
#(
.
WIDTH
(
3
)
,
.
EXTRA_DLY
(
0
)
)
multipulse_cross_clock_i
(
.
rst
(
rst
)
,
// input
.
src_clk
(
xclk
)
,
// input
.
dst_clk
(
mclk
)
,
// input
.
num_pulses
(
{
1'b0
,
add_invalid
}
)
,
// input[0:0]
.
we
(
mb_release_buf
)
,
// input
.
out_pulse
(
next_page_chn
)
,
// output
.
busy
()
// output
)
;
endmodule
compressor_jp/cmprs_pixel_buf_iface.v
0 → 100644
View file @
8b1599eb
/*******************************************************************************
* Module: cmprs_pixel_buf_iface
* Date:2015-06-11
* Author: andrey
* Description: Communicates with compressor memory buffer, generates pixel
* stream matching selected color mode, accommodates for the buffer latency,
* acts as a pacemaker for the whole compressor (next stages are able to keep up).
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* cmprs_pixel_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_pixel_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/> .
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
cmprs_pixel_buf_iface
#(
parameter
CMPRS_BUF_EXTRA_LATENCY
=
0
// extra register layers insered between the buffer and this module
)(
input
rst
,
input
xclk
,
// global clock input, compressor single clock rate
input
mclk
,
// global clock for commands (posedge) and write side of the memory buffer (negedge)
// 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
input
[
7
:
0
]
buf_di
,
// data from the buffer
output
[
11
:
0
]
buf_ra
,
// buffer read address (1 MSB - page number)
output
[
1
:
0
]
buf_rd
,
// buf {regen, re}
input
frame_en
,
// if 0 - will reset logic immediately (but not page number)
input
frame_go
,
// start frame: if idle, will start reading data (if available),
// if running - will not restart a new frame if 0.
input
[
6
:
0
]
mode
,
// TODO: adjust width. Color mode that determins address mapping
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
output
[
7
:
0
]
data_out
,
//
output
pre_first_out
,
// For each macroblock in a frame
output
data_valid
//
)
;
localparam
CMPRS_MB_DLY
=
5
;
wire
buf_re_w
;
reg
[
CMPRS_BUF_EXTRA_LATENCY
+
2
:
0
]
buf_re
;
reg
[
7
:
0
]
do_r
;
wire
reset_page_rd
;
wire
page_ready
;
// wire next_page; // @ posedge xclk - source
// wire busy_next_page; // do not send next_page -previous is crossing clock boundaries
wire
frame_end_w
;
// calculated
wire
frame_en_w
;
reg
frame_en_r
;
wire
pre_frame_start
;
wire
frame_start
;
wire
en
;
reg
pre_en
;
reg
[
11
:
0
]
mb_start
;
// full adderss of the next macroblock start;
reg
[
11
:
0
]
mbr_start
;
// start address of the next macroblock row
reg
[
11
:
0
]
buf_ra_r
;
// buffer read address
reg
[
5
:
0
]
mb_w_m1
;
// macroblock width minus 1
reg
[
5
:
0
]
mb_h_m1
;
// macroblock height minus 1
// reg [ 4:0] left_marg; // left margin of the leftmost macroblock column relative to read tiles (aligned to 32 bytes)
reg
[
4
:
3
]
mb_hper
;
// macroblock horizontal period (8/16)
reg
[
1
:
0
]
tile_width
;
// memory tile width (can be 128 for monochrome JPEG) Can be 32/64/128: 0 - 16, 1 - 32, 2 - 64, 3 - 128
reg
[
12
:
0
]
mb_col
;
// number of a macroblock in a row
reg
[
12
:
0
]
mb_row
;
// number of a macroblock row
wire
[
6
:
0
]
mbl_x
;
// macroblock left pixel x relative to a tile (page) Maximal page - 128 bytes wide
reg
[
6
:
3
]
mbl_x_r
;
// macroblock left pixel x relative to a tile (page) (3 low don't change)
reg
[
6
:
3
]
mbl_x_next_r
;
// macroblock left pixel x relative to a tile (page), not valid for first column (3 low don't change)
reg
[
7
:
3
]
mbl_x_inc_r
;
// intermediate register for calculating mbl_x_next_r and add_invalid
reg
[
7
:
3
]
mbl_x_last_r
;
// intermediate register for calculating needed_page
wire
mb_pre_end_w
;
// start mb_pre_end sequence
reg
[
3
:
0
]
mb_pre_end
;
// 1-hot macroblock pre end calcualtions
// wire mb_pre_end_done = mb_pre_end[2]; // overlap
reg
[
1
:
0
]
pre_advance_tiles
;
// advance tiles by this for same row of macroblocks
wire
mb_pre_start_w
;
// same timing as mb_pre_end[1]
reg
[
4
:
0
]
mb_pre_start
;
// 1-hot macroblock pre start calcualtions - TODO: adjust width
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
mb_first_in_row
;
reg
mb_last_in_row
;
reg
[
2
:
0
]
next_valid
;
// number of next valid page (only 2 LSB are actual page number)
reg
[
2
:
0
]
next_invalid
;
// oldest valid page
reg
[
1
:
0
]
add_invalid
;
// advance next_invalid pointer by this value, send next_page pulses
reg
we_invalid
;
// advance next_invalid pointer, send next_page pulses
reg
[
2
:
0
]
used_pages
;
// number of pages simultaneously used for the last macroblock
reg
[
2
:
0
]
needed_page
;
// calculate at MB start
// reg [ 1:0] need_pages_m1; // number of tiles needed for macroblock being started minus 1 (0 - just a single macroblock)
assign
buf_rd
=
buf_re
[
1
:
0
]
;
assign
data_out
=
do_r
;
assign
frame_en_w
=
frame_en
&&
frame_go
;
assign
pre_frame_start
=
frame_en_w
&&
(
en
?
frame_end_w
:
(
!
frame_en_r
))
;
assign
mbl_x
={
mbl_x_r
[
6
:
3
]
,
left_marg
[
2
:
0
]
};
assign
buf_diff
=
needed_page
-
next_valid
;
assign
buf_ready_w
=
buf_diff
[
2
]
;
always
@
(
posedge
xclk
)
begin
if
(
!
frame_en
)
frame_en_r
<=
0
;
else
frame_en_r
<=
frame_en_w
;
if
(
!
frame_en
)
pre_en
<=
0
;
else
if
(
frame_end_w
||
!
pre_en
)
pre_en
<=
frame_go
;
if
(
!
en
)
buf_re
<=
0
;
else
buf_re
<=
{
buf_re
[
CMPRS_BUF_EXTRA_LATENCY
+
1
:
0
]
,
buf_re_w
};
if
(
buf_re
[
CMPRS_BUF_EXTRA_LATENCY
+
2
])
do_r
<=
buf_di
;
// 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
;
// at the end of each macroblock - calculate start page increment (and after delay - advance invalidate_next)
// calculate next start X in page (regardless of emd of macroblock row - selection will be at macroblock start)
if
(
mb_pre_end_w
)
mb_pre_end
<=
1
;
else
mb_pre_end
<=
mb_pre_end
<<
1
;
if
(
mb_pre_end
[
0
])
mbl_x_inc_r
[
7
:
3
]
<=
{
1'b0
,
mbl_x_r
[
6
:
3
]
}
+
{
3'b0
,
mb_hper
[
4
:
3
]
};
if
(
mb_pre_end
[
1
])
begin
case
(
tile_width
)
2'b00
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
3'b0
,
mbl_x_inc_r
[
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
mbl_x_inc_r
[
5
:
4
]
;
end
2'b01
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
2'b0
,
mbl_x_inc_r
[
4
:
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
mbl_x_inc_r
[
6
:
5
]
;
end
2'b10
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
1'b0
,
mbl_x_inc_r
[
5
:
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
mbl_x_inc_r
[
7
:
6
]
;
end
2'b11
:
begin
mbl_x_next_r
[
6
:
3
]
<=
{
mbl_x_inc_r
[
6
:
3
]
};
pre_advance_tiles
[
1
:
0
]
<=
{
1'b0
,
mbl_x_inc_r
[
7
]
};
end
endcase
used_pages
<=
needed_page
-
next_invalid
+
1
;
end
if
(
mb_pre_end
[
2
])
begin
// TODO: apply after delay, regardless last or not
if
(
mb_last_in_row
)
add_invalid
<=
used_pages
[
1
:
0
]
;
else
add_invalid
<=
pre_advance_tiles
;
end
// pages already processed by compressor - they can be reused for reading new tiles
if
(
reset_page_rd
)
next_invalid
<=
0
;
else
if
(
mb_pre_end
[
3
])
next_invalid
<=
next_invalid
+
{
1'b0
,
add_invalid
};
// TODO: Send next_page after delay
// calculate before starting each macroblock (will wait if buffer is not ready) (TODO: align mb_pre_start[0] to mb_pre_end[2] - same)
//mb_pre_start_w
if
(
mb_pre_start_w
)
mb_pre_start
<=
1
;
else
if
(
!
mb_pre_start
[
3
]
||
buf_ready_w
)
mb_pre_start
<=
mb_pre_start
<<
1
;
if
(
mb_pre_start
[
0
])
mbl_x_r
[
6
:
3
]
<=
mb_first_in_row
?
{
2'b0
,
left_marg
[
4
:
3
]
}
:
mbl_x_next_r
[
6
:
3
]
;
if
(
mb_pre_start
[
1
])
mbl_x_last_r
[
7
:
3
]
<=
{
1'b0
,
mbl_x_r
[
6
:
3
]
}
+
{
2'b0
,
mb_w_m1
[
5
:
3
]
};
if
(
mb_pre_start
[
2
])
begin
case
(
tile_width
)
2'b00
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
1'b0
,
mbl_x_last_r
[
5
:
4
]
};
2'b01
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
1'b0
,
mbl_x_last_r
[
6
:
5
]
};
2'b10
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
1'b0
,
mbl_x_last_r
[
7
:
6
]
};
2'b11
:
needed_page
[
2
:
0
]
<=
next_invalid
[
2
:
0
]
+{
2'b0
,
mbl_x_last_r
[
7
]
};
endcase
end
//need_pages_m1[1:0] <= ;
/*
if (mb_pre_end_w) mb_pre_end <= 1;
else mb_pre_end <= mb_pre_end << 1;
reg [ 3:0] mb_pre_start; // 1-hot macroblock pre start calcualtions - TODO: adjust width
wire buf_ready_w; // External memory buffer has all the pages needed
reg mb_first_in_row;
reg [ 2:0] next_valid; // number of next valid page (only 2 LSB are actual page number)
reg [ 2:0] next_invalid; // oldest valid page
reg [ 2:0] needed_page; // calculate at MB start
reg [ 7:3] mbl_x_last_r; // intermediate register for calculating needed_page
reg [ 5:0] mb_w_m1; // macroblock width minus 1
wire [ 6:0] mbl_x; // macroblock left pixel x relative to a tile (page) Maximal page - 128 bytes wide
reg [ 6:3] mbl_x_r; // macroblock left pixel x relative to a tile (page) (3 low don't change)
reg [ 6:3] mbl_x_next_r; // macroblock left pixel x relative to a tile (page), not valid for first column (3 low don't change)
reg [ 1:0] add_invalid; // advance next_invalid pointer by this value, send next_page pulses
reg we_invalid; // advance next_invalid pointer, send next_page pulses
reg [ 4:3] mb_hper; // macroblock horizontal period (8/16)
reg [ 4:0] mb_pre_end; // 1-hot macroblock pre end calcualtions - TODO: adjust width
wire [ 6:0] mbl_x; // macroblock left pixel x relative to a tile (page) Maximal page - 128 bytes wide
reg [ 6:3] mbl_x_r; // macroblock left pixel x relative to a tile (page) (3 low don't change)
reg [ 6:3] mbl_x_next_r; // macroblock left pixel x relative to a tile (page), not valid for first column (3 low don't change)
reg [ 7:3] mbl_x_inc_r; // intermediate register for calculatingm bl_x_next_r and add_invalid
reg [ 4:0] mb_hper; // macroblock horizontal period (8/16)
reg [ 1:0] tile_width; // memory tile width (can be 128 for monochrome JPEG) Can be 32/64/128: 0 - 16, 1 - 32, 2 - 64, 3 - 128
reg mb_first_in_row;
reg mb_last_in_row;
reg [ 1:0] add_invalid; // advance next_invalid pointer by this value, send next_page pulses
reg we_invalid; // advance next_invalid pointer, send next_page pulses
*/
end
// synchronization between mclk and xclk clock domains
// negedge mclk -> xclk (verify clock inversion is absorbed)
pulse_cross_clock
reset_page_rd_i
(
.
rst
(
rst
)
,
.
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
(
rst
)
,
.
src_clk
(
mclk
)
,
.
dst_clk
(
xclk
)
,
.
in_pulse
(
page_ready_chn
)
,
.
out_pulse
(
page_ready
)
,.
busy
())
;
// xclk -> mclk
// pulse_cross_clock next_page_i (.rst(rst), .src_clk(xclk), .dst_clk(mclk), .in_pulse(next_page), .out_pulse(next_page_chn),.busy(busy_next_page));
dly_16
#(
.
WIDTH
(
1
))
dly_16_i
(
.
clk
(
xclk
)
,.
rst
(
rst
)
,
.
dly
(
CMPRS_MB_DLY
)
,
.
din
(
pre_frame_start
)
,
.
dout
(
frame_start
))
;
dly_16
#(
.
WIDTH
(
1
))
dly_16_i
(
.
clk
(
xclk
)
,.
rst
(
!
frame_en
)
,.
dly
(
CMPRS_MB_DLY
)
,
.
din
(
pre_en
)
,
.
dout
(
en
))
;
multipulse_cross_clock
#(
.
WIDTH
(
3
)
,
.
EXTRA_DLY
(
0
)
)
multipulse_cross_clock_i
(
.
rst
(
rst
)
,
// input
.
src_clk
(
xclk
)
,
// input
.
dst_clk
(
mclk
)
,
// input
.
num_pulses
(
{
1'b0
,
add_invalid
}
)
,
// input[0:0]
.
we
(
we_invalid
)
,
// input
.
out_pulse
(
next_page_chn
)
,
// output
.
busy
()
// output
)
;
endmodule
compressor_jp/color_proc393.v
View file @
8b1599eb
...
@@ -27,7 +27,13 @@ module color_proc393 (
...
@@ -27,7 +27,13 @@ module color_proc393 (
input
en
,
// Enable (0 will reset states)
input
en
,
// Enable (0 will reset states)
input
en_sdc
,
// enable subtracting of DC component
input
en_sdc
,
// enable subtracting of DC component
input
go
,
// pulse to star/restart (needed for each frame, repeat generated by the caller)
input
go
,
// pulse to star/restart (needed for each frame, repeat generated by the caller)
// TODO: Remove
input
[
25
:
0
]
nblocks
,
// ***** was [17:0] number of 16x16 blocks to read (valid @ "go" pulse)
input
[
25
:
0
]
nblocks
,
// ***** was [17:0] number of 16x16 blocks to read (valid @ "go" pulse)
// NEW: Now number of SDRAM blobks (tiles) is not equal to number of macroblocks
input
[
12
:
0
]
n_blocks_in_row
,
// number of macroblocks in a macroblock row
input
[
12
:
0
]
n_block_rows
,
// number of macroblock rows in a frame
// input reset_sdram_page, // SDRAM buffer page may be reset (normally just increments for each new tile
// end of NEW
output
eot
,
// single-cycle end of transfer pulse
output
eot
,
// single-cycle end of transfer pulse
input
[
9
:
0
]
m_cb
,
// [9:0] scale for CB - default 0.564 (10'h90)
input
[
9
:
0
]
m_cb
,
// [9:0] scale for CB - default 0.564 (10'h90)
input
[
9
:
0
]
m_cr
,
// [9:0] scale for CB - default 0.713 (10'hb6)
input
[
9
:
0
]
m_cr
,
// [9:0] scale for CB - default 0.713 (10'hb6)
...
@@ -114,7 +120,7 @@ module color_proc393 (
...
@@ -114,7 +120,7 @@ module color_proc393 (
reg
[
2
:
0
]
sdrama_line_inc
;
// increment amount when proceeding to next tile line
reg
[
2
:
0
]
sdrama_line_inc
;
// increment amount when proceeding to next tile line
reg
[
1
:
0
]
inc_sdrama_r
;
reg
[
1
:
0
]
inc_sdrama_r
;
reg
last_from_sdram
;
// reading last_r byte from SDRAM
reg
last_from_sdram
;
// reading last_r byte from SDRAM
reg
first_pixel
;
// reading first_r pixel to color converter (di will be
e
vailable next cycle)
reg
first_pixel
;
// reading first_r pixel to color converter (di will be
a
vailable next cycle)
reg
tim2next
;
reg
tim2next
;
reg
[
8
:
0
]
y_in
,
c_in
;
reg
[
8
:
0
]
y_in
,
c_in
;
reg
[
7
:
0
]
yaddrw
,
caddrw
;
reg
[
7
:
0
]
yaddrw
,
caddrw
;
...
@@ -471,7 +477,7 @@ module color_proc393 (
...
@@ -471,7 +477,7 @@ module color_proc393 (
wire
limit_diff
=
1'b1
;
wire
limit_diff
=
1'b1
;
csconvert18
i_csconvert18
(
csconvert18
a
i_csconvert18
(
.
RST
(
!
en_converters
[
0
])
,
.
RST
(
!
en_converters
[
0
])
,
.
CLK
(
clk
)
,
.
CLK
(
clk
)
,
.
mono
(
ignore_color_r
)
,
.
mono
(
ignore_color_r
)
,
...
@@ -536,39 +542,39 @@ assign conv20_pre_first_out= conv18_pre_first_out;
...
@@ -536,39 +542,39 @@ assign conv20_pre_first_out= conv18_pre_first_out;
// currently only 8 bits are used in the memories
// currently only 8 bits are used in the memories
ramp_var_w_var_r
#(
ram
18
p_var_w_var_r
#(
.
REGISTERS
(
1
)
,
// will need to delay output strobe(s) by 1
.
REGISTERS
(
1
)
,
// will need to delay output strobe(s) by 1
.
LOG2WIDTH_WR
(
3
)
,
.
LOG2WIDTH_WR
(
3
)
,
.
LOG2WIDTH_RD
(
3
)
,
.
LOG2WIDTH_RD
(
3
)
,
.
DUMMY
(
0
)
.
DUMMY
(
0
)
)
i_y_buff
(
)
i_y_buff
(
.
rclk
(
clk
)
,
// input
.
rclk
(
clk
)
,
// input
.
raddr
(
{
2
'b0
,
rpage
[
1
:
0
]
,
raddr
[
7
:
0
]
}
)
,
// input[11:0]
.
raddr
(
{
1
'b0
,
rpage
[
1
:
0
]
,
raddr
[
7
:
0
]
}
)
,
// input[11:0]
.
ren
(
!
raddr
[
8
])
,
// input
.
ren
(
!
raddr
[
8
])
,
// input
.
regen
(
!
raddr8_d
)
,
// input
.
regen
(
!
raddr8_d
)
,
// input
.
data_out
(
y_out
[
8
:
0
])
,
// output[8:0]
.
data_out
(
y_out
[
8
:
0
])
,
// output[8:0]
.
wclk
(
clk
)
,
// input
.
wclk
(
clk
)
,
// input
.
waddr
(
{
2
'b0
,
wpage
[
1
:
0
]
,
yaddrw
[
7
:
0
]
}
)
,
// input[11:0]
.
waddr
(
{
1
'b0
,
wpage
[
1
:
0
]
,
yaddrw
[
7
:
0
]
}
)
,
// input[11:0]
.
we
(
ywe
)
,
// input
.
we
(
ywe
)
,
// input
.
web
(
8
'hf
)
,
// input[7:0]
.
web
(
4
'hf
)
,
// input[7:0]
.
data_in
(
y_in
[
8
:
0
])
// input[9:0]
.
data_in
(
y_in
[
8
:
0
])
// input[9:0]
)
;
)
;
ramp_var_w_var_r
#(
ram
18
p_var_w_var_r
#(
.
REGISTERS
(
1
)
,
// will need to delay output strobe(s) by 1
.
REGISTERS
(
1
)
,
// will need to delay output strobe(s) by 1
.
LOG2WIDTH_WR
(
3
)
,
.
LOG2WIDTH_WR
(
3
)
,
.
LOG2WIDTH_RD
(
3
)
,
.
LOG2WIDTH_RD
(
3
)
,
.
DUMMY
(
0
)
.
DUMMY
(
0
)
)
i_CrCb_buff
(
)
i_CrCb_buff
(
.
rclk
(
clk
)
,
// input
.
rclk
(
clk
)
,
// input
.
raddr
(
{
2
'b0
,
rpage
[
1
:
0
]
,
raddr
[
7
:
0
]
}
)
,
// input[11:0]
.
raddr
(
{
1
'b0
,
rpage
[
1
:
0
]
,
raddr
[
7
:
0
]
}
)
,
// input[11:0]
.
ren
(
raddr
[
8
])
,
// input
.
ren
(
raddr
[
8
])
,
// input
.
regen
(
raddr8_d
)
,
// input
.
regen
(
raddr8_d
)
,
// input
.
data_out
(
c_out
[
8
:
0
])
,
// output[8:0]
.
data_out
(
c_out
[
8
:
0
])
,
// output[8:0]
.
wclk
(
clk
)
,
// input
.
wclk
(
clk
)
,
// input
.
waddr
(
{
2
'b0
,
wpage
[
1
:
0
]
,
yaddrw
[
7
:
0
]
}
)
,
// input[11:0]
.
waddr
(
{
1
'b0
,
wpage
[
1
:
0
]
,
yaddrw
[
7
:
0
]
}
)
,
// input[11:0]
.
we
(
ywe
)
,
// input
.
we
(
ywe
)
,
// input
.
web
(
8
'hf
)
,
// input[7:0]
.
web
(
4
'hf
)
,
// input[7:0]
.
data_in
(
y_in
[
8
:
0
])
// input[71:0]
.
data_in
(
y_in
[
8
:
0
])
// input[71:0]
)
;
)
;
...
...
util_modules/multipulse_cross_clock.v
0 → 100644
View file @
8b1599eb
/*******************************************************************************
* Module: multipulse_cross_clock
* Date:2015-04-27
* Author: andrey
* Description: Generate a train of pulses through clock domains boundary
* Maximal duty cycle (with EXTRA_DLY=0 and Fdst << Fsrc) = 50%
* same frequencies - ~1/3 (with EXTRA_DLY=0) and 1/5 (with EXTRA_DLY=1)
* Lowering Fsrc reduces duty cycle proportianally as counter is in src_clk
* domain.
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* multipulse_cross_clock.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.
*
* multipulse_cross_clock.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/> .
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
multipulse_cross_clock
#(
parameter
WIDTH
=
1
,
// width of the pulse counter (assign MSB of input to 0 to
// have more pending that possible input)
parameter
EXTRA_DLY
=
0
)(
// 0 or 1 - output duty cycle control
input
rst
,
input
src_clk
,
input
dst_clk
,
input
[
WIDTH
-
1
:
0
]
num_pulses
,
// single-cycle positive pulse
input
we
,
output
out_pulse
,
output
busy
)
;
reg
[
WIDTH
-
1
:
0
]
pend_cntr
=
0
;
wire
busy_single
;
wire
single_rq_w
;
reg
single_rq_r
=
0
;
assign
busy
=
busy_single
&&
(
|
pend_cntr
)
;
assign
single_rq_w
=
busy_single
&&
(
|
pend_cntr
)
;
always
@
(
posedge
src_clk
)
begin
single_rq_r
<=
single_rq_w
;
pend_cntr
<=
pend_cntr
+
(
we
?
num_pulses
:
{
WIDTH
{
1'b0
}}
)
+
(
single_rq_r
?
{
WIDTH
{
1'b1
}}:{
WIDTH
{
1'b0
}}
)
;
end
pulse_cross_clock
#(
.
EXTRA_DLY
(
EXTRA_DLY
)
)
pulse_cross_clock_i
(
.
rst
(
rst
)
,
// input
.
src_clk
(
src_clk
)
,
// input
.
dst_clk
(
dst_clk
)
,
// input
.
in_pulse
(
single_rq_w
)
,
// input
.
out_pulse
(
out_pulse
)
,
// output
.
busy
(
busy_single
)
// output
)
;
endmodule
util_modules/pulse_cross_clock.v
View file @
8b1599eb
...
@@ -3,6 +3,8 @@
...
@@ -3,6 +3,8 @@
* Date:2015-04-27
* Date:2015-04-27
* Author: andrey
* Author: andrey
* Description: Propagate a single pulse through clock domain boundary
* Description: Propagate a single pulse through clock domain boundary
* For same frequencies input pulses can have 1:3 duty cycle EXTRA_DLY=0
* and 1:5 for EXTRA_DLY=1
*
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* pulse_cross_clock.v is free software; you can redistribute it and/or modify
* pulse_cross_clock.v is free software; you can redistribute it and/or modify
...
@@ -20,7 +22,9 @@
...
@@ -20,7 +22,9 @@
*******************************************************************************/
*******************************************************************************/
`timescale
1
ns
/
1
ps
`timescale
1
ns
/
1
ps
module
pulse_cross_clock
(
module
pulse_cross_clock
#(
parameter
EXTRA_DLY
=
0
// for
)(
input
rst
,
input
rst
,
input
src_clk
,
input
src_clk
,
input
dst_clk
,
input
dst_clk
,
...
@@ -28,13 +32,17 @@ module pulse_cross_clock(
...
@@ -28,13 +32,17 @@ module pulse_cross_clock(
output
out_pulse
,
output
out_pulse
,
output
busy
output
busy
)
;
)
;
reg
in_reg
;
localparam
EXTRA_DLY_SAFE
=
EXTRA_DLY
?
1
:
0
;
reg
[
2
:
0
]
out_reg
;
reg
in_reg
=
0
;
reg
[
2
:
0
]
out_reg
=
0
;
reg
busy_r
=
0
;
assign
out_pulse
=
out_reg
[
2
]
;
assign
out_pulse
=
out_reg
[
2
]
;
assign
busy
=
in_reg
;
assign
busy
=
busy_r
;
//
in_reg;
always
@
(
posedge
src_clk
or
posedge
rst
)
begin
always
@
(
posedge
src_clk
or
posedge
rst
)
begin
if
(
rst
)
in_reg
<=
0
;
if
(
rst
)
in_reg
<=
0
;
else
in_reg
<=
in_pulse
||
(
in_reg
&&
!
out_reg
[
1
])
;
else
in_reg
<=
in_pulse
||
(
in_reg
&&
!
out_reg
[
EXTRA_DLY_SAFE
])
;
if
(
rst
)
busy_r
<=
0
;
else
busy_r
<=
in_pulse
||
in_reg
||
(
busy_r
&&
out_reg
[
EXTRA_DLY_SAFE
])
;
end
end
always
@
(
posedge
dst_clk
or
posedge
rst
)
begin
always
@
(
posedge
dst_clk
or
posedge
rst
)
begin
if
(
rst
)
out_reg
<=
0
;
if
(
rst
)
out_reg
<=
0
;
...
...
wrap/ram18p_var_w_var_r.v
0 → 100644
View file @
8b1599eb
/*******************************************************************************
* Copyright (c) 2015 Elphel, Inc.
* Dual port memory wrapper, with variable width write and variable width read
* using "SDP" or "TDP" mode of RAMB18E1 (half of RAMB18E1)
* Uses parity bits to extend total data width (minimal width should be >=8).
* ram18p_var_w_var_r.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.
*
* ram18p_var_w_var_r.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/>.
*******************************************************************************/
/*
Address/data widths
Connect unused data to 1b0, unused addresses - to 1'b1
RAMB18E1 in True Dual Port (TDP) Mode - each port individually
+-----------+---------+---------+---------+
|Data Width | Address | Data | Parity |
+-----------+---------+---------+---------+
| 1 | A[13:0] | D[0] | --- |
| 2 | A[13:1] | D[1:0] | --- |
| 4 | A[13:2] | D[3:0[ | --- |
| 9 | A[13:3] | D[7:0] | DP[0] |
| 18 | A[13:4] | D[15:0] | DP[1:0] |
+-----------+---------+---------+---------+
RAMB18E1 in Simple Dual Port (SDP) Mode
one of the ports (r or w) - 32/36 bits, other - variable
+------------+---------+---------+---------+
|Data Widths | Address | Data | Parity |
+------------+---------+---------+---------+
| 32/ 1 | A[13:0] | D[0] | --- |
| 32/ 2 | A[13:1] | D[1:0] | --- |
| 32/ 4 | A[13:2] | D[3:0[ | --- |
| 36/ 9 | A[13:3] | D[7:0] | DP[0] |
| 36/ 18 | A[13:4] | D[15:0] | DP[1:0] |
| 36/ 36 | A[13:5] | D[31:0] | DP[3:0] |
+------------+---------+---------+---------+
RAMB36E1 in True Dual Port (TDP) Mode - each port individually
+-----------+---------+---------+---------+
|Data Width | Address | Data | Parity |
+-----------+---------+---------+---------+
| 1 | A[14:0] | D[0] | --- |
| 2 | A[14:1] | D[1:0] | --- |
| 4 | A[14:2] | D[3:0[ | --- |
| 9 | A[14:3] | D[7:0] | DP[0] |
| 18 | A[14:4] | D[15:0] | DP[1:0] |
| 36 | A[14:5] | D[31:0] | DP[3:0] |
|1(Cascade) | A[15:0] | D[0] | --- |
+-----------+---------+---------+---------+
RAMB36E1 in Simple Dual Port (SDP) Mode
one of the ports (r or w) - 64/72 bits, other - variable
+------------+---------+---------+---------+
|Data Widths | Address | Data | Parity |
+------------+---------+---------+---------+
| 64/ 1 | A[14:0] | D[0] | --- |
| 64/ 2 | A[14:1] | D[1:0] | --- |
| 64/ 4 | A[14:2] | D[3:0[ | --- |
| 64/ 9 | A[14:3] | D[7:0] | DP[0] |
| 64/ 18 | A[14:4] | D[15:0] | DP[1:0] |
| 64/ 36 | A[14:5] | D[31:0] | DP[3:0] |
| 64/ 72 | A[14:6] | D[63:0] | DP[7:0] |
+------------+---------+---------+---------+
*/
module
ram18p_var_w_var_r
#(
parameter
integer
REGISTERS
=
0
,
// 1 - registered output
parameter
integer
LOG2WIDTH_WR
=
5
,
// WIDTH= 9 << (LOG2WIDTH - 3)
parameter
integer
LOG2WIDTH_RD
=
5
,
// WIDTH= 9 << (LOG2WIDTH - 3)
parameter
DUMMY
=
0
)
(
input
rclk
,
// clock for read port
// input [ 9:0] raddr, // read address
input
[
13
-
LOG2WIDTH_RD
:
0
]
raddr
,
// read address
input
ren
,
// read port enable
input
regen
,
// output register enable
output
[(
9
<<
(
LOG2WIDTH_RD
-
3
))
-
1
:
0
]
data_out
,
// data out
input
wclk
,
// clock for read port
input
[
13
-
LOG2WIDTH_WR
:
0
]
waddr
,
// write address
input
we
,
// write port enable
input
[
3
:
0
]
web
,
// write byte enable
input
[(
9
<<
(
LOG2WIDTH_WR
-
3
))
-
1
:
0
]
data_in
// data out
)
;
generate
if
(
DUMMY
)
ram18p_dummy
#(
.
LOG2WIDTH_RD
(
LOG2WIDTH_RD
)
)
ram18p_dummy_i
(
.
data_out
(
data_out
)
)
;
else
if
((
LOG2WIDTH_WR
==
5
)
&&
(
LOG2WIDTH_RD
==
5
))
ramp_32w_32r
#(
.
REGISTERS
(
REGISTERS
)
)
ram_i
(
.
rclk
(
rclk
)
,
// input
.
raddr
(
raddr
)
,
// input[8:0]
.
ren
(
ren
)
,
// input
.
regen
(
regen
)
,
// input
.
data_out
(
data_out
)
,
// output[35:0]
.
wclk
(
wclk
)
,
// input
.
waddr
(
waddr
)
,
// input[8:0]
.
we
(
we
)
,
// input
.
web
(
web
)
,
// input[3:0]
.
data_in
(
data_in
)
// input[35:0]
)
;
else
if
((
LOG2WIDTH_WR
==
5
)
&&
(
LOG2WIDTH_RD
<
5
))
ram18p_32w_lt32r
#(
.
REGISTERS
(
REGISTERS
)
,
.
LOG2WIDTH_RD
(
LOG2WIDTH_RD
)
)
ram_i
(
.
rclk
(
rclk
)
,
// input
.
raddr
(
raddr
)
,
// input[(>8):0]
.
ren
(
ren
)
,
// input
.
regen
(
regen
)
,
// input
.
data_out
(
data_out
)
,
// output[(<35):0]
.
wclk
(
wclk
)
,
// input
.
waddr
(
waddr
)
,
// input[8:0]
.
we
(
we
)
,
// input
.
web
(
web
)
,
// input[3:0]
.
data_in
(
data_in
)
// input[35:0]
)
;
else
if
((
LOG2WIDTH_WR
<
5
)
&&
(
LOG2WIDTH_RD
==
5
))
ramp_lt32w_32r
#(
.
REGISTERS
(
REGISTERS
)
,
.
LOG2WIDTH_WR
(
LOG2WIDTH_WR
)
)
ram_i
(
.
rclk
(
rclk
)
,
// input
.
raddr
(
raddr
)
,
// input[8:0]
.
ren
(
ren
)
,
// input
.
regen
(
regen
)
,
// input
.
data_out
(
data_out
)
,
// output[35:0]
.
wclk
(
wclk
)
,
// input
.
waddr
(
waddr
)
,
// input[(>8):0]
.
we
(
we
)
,
// input
.
web
(
web
)
,
// input[3:0]
.
data_in
(
data_in
)
// input[(<35):0]
)
;
else
if
((
LOG2WIDTH_WR
<
5
)
&&
(
LOG2WIDTH_RD
<
5
))
ramp_lt32w_lt32r
#(
.
REGISTERS
(
REGISTERS
)
,
.
LOG2WIDTH_WR
(
LOG2WIDTH_WR
)
,
.
LOG2WIDTH_RD
(
LOG2WIDTH_RD
)
)
ram_i
(
.
rclk
(
rclk
)
,
// input
.
raddr
(
raddr
)
,
// input[(>8):0]
.
ren
(
ren
)
,
// input
.
regen
(
regen
)
,
// input
.
data_out
(
data_out
)
,
// output[(<35):0]
.
wclk
(
wclk
)
,
// input
.
waddr
(
waddr
)
,
// input[(>8):0]
.
we
(
we
)
,
// input
.
web
(
web
)
,
// input[7:0]
.
data_in
(
data_in
)
// input[(<35):0]
)
;
endgenerate
endmodule
// Both ports with 32 bit widths
module
ramp_32w_32r
#(
parameter
integer
REGISTERS
=
0
// 1 - registered output
)
(
input
rclk
,
// clock for read port
input
[
8
:
0
]
raddr
,
// read address
input
ren
,
// read port enable
input
regen
,
// output register enable
output
[
35
:
0
]
data_out
,
// data out
input
wclk
,
// clock for read port
input
[
8
:
0
]
waddr
,
// write address
input
we
,
// write port enable
input
[
3
:
0
]
web
,
// write byte enable
input
[
35
:
0
]
data_in
// data out
)
;
localparam
PWIDTH_WR
=
72
;
localparam
PWIDTH_RD
=
72
;
RAMB18E1
#(
.
RSTREG_PRIORITY_A
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
RSTREG_PRIORITY_B
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
DOA_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
DOB_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
READ_WIDTH_A
(
PWIDTH_RD
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
READ_WIDTH_B
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_A
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_B
(
PWIDTH_WR
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
RAM_MODE
(
"SDP"
)
,
// Valid "TDP" (true dual-port) and "SDP" - simple dual-port
.
WRITE_MODE_A
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
WRITE_MODE_B
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
RDADDR_COLLISION_HWCONFIG
(
"DELAYED_WRITE"
)
,
// Valid: "DELAYED_WRITE","PERFORMANCE" (no access to the same page)
.
SIM_COLLISION_CHECK
(
"ALL"
)
,
// Valid: "ALL", "GENERATE_X_ONLY", "NONE", and "WARNING_ONLY"
.
INIT_FILE
(
"NONE"
)
,
// "NONE" or filename with initialization data
.
SIM_DEVICE
(
"7SERIES"
)
// Simulation device family - "VIRTEX6", "VIRTEX5" and "7_SERIES" // "7SERIES"
)
RAMB36E1_i
(
// Port A (Read port in SDP mode):
.
DOADO
(
data_out
[
15
:
0
])
,
// Port A data/LSB data[15:0], output
.
DOPADOP
(
data_out
[
17
:
16
])
,
// Port A parity/LSB parity[2:0], output
.
DIADI
(
data_in
[
15
:
0
])
,
// Port A data/LSB data[15:0], input
.
DIPADIP
(
data_in
[
17
:
16
])
,
// Port A parity/LSB parity[2:0], input
.
ADDRARDADDR
(
{
raddr
[
8
:
0
]
,
5'b11111
}
)
,
// Port A (read port in SDP) address [13:0], unused should be high, input
.
CLKARDCLK
(
rclk
)
,
// Port A (read port in SDP) clock, input
.
ENARDEN
(
ren
)
,
// Port A (read port in SDP) Enable, input
.
REGCEAREGCE
(
regen
)
,
// Port A (read port in SDP) register enable, input
.
RSTRAMARSTRAM
(
1'b0
)
,
// Port A (read port in SDP) set/reset, input
.
RSTREGARSTREG
(
1'b0
)
,
// Port A (read port in SDP) register set/reset, input
.
WEA
(
2'b0
)
,
// Port A (read port in SDP) Write Enable[2:0], input
// Port B
.
DOBDO
(
data_out
[
33
:
18
])
,
// Port B data/MSB data[15:0], output
.
DOPBDOP
(
data_out
[
35
:
34
])
,
// Port B parity/MSB parity[2:0], output
.
DIBDI
(
data_in
[
33
:
18
])
,
// Port B data/MSB data[31:0], input
.
DIPBDIP
(
data_in
[
35
:
34
])
,
// Port B parity/MSB parity[1:0], input
.
ADDRBWRADDR
(
{
waddr
[
8
:
0
]
,
5'b11111
}
)
,
// Port B (write port in SDP) address [13:0], unused should be high, input
.
CLKBWRCLK
(
wclk
)
,
// Port B (write port in SDP) clock, input
.
ENBWREN
(
we
)
,
// Port B (write port in SDP) Enable, input
.
REGCEB
(
1'b0
)
,
// Port B (write port in SDP) register enable, input
.
RSTRAMB
(
1'b0
)
,
// Port B (write port in SDP) set/reset, input
.
RSTREGB
(
1'b0
)
,
// Port B (write port in SDP) register set/reset, input
.
WEBWE
(
web
)
// Port B (write port in SDP) Write Enable[7:0], input
)
;
endmodule
// Both ports with less than 32 bit widths
module
ramp_lt32w_lt32r
#(
parameter
integer
REGISTERS
=
0
,
// 1 - registered output
parameter
integer
LOG2WIDTH_WR
=
4
,
// WIDTH= 1 << LOG2WIDTH
parameter
integer
LOG2WIDTH_RD
=
4
// WIDTH= 1 << LOG2WIDTH
)
(
input
rclk
,
// clock for read port
input
[
13
-
LOG2WIDTH_RD
:
0
]
raddr
,
// read address
input
ren
,
// read port enable
input
regen
,
// output register enable
output
[(
9
<<
(
LOG2WIDTH_RD
-
3
))
-
1
:
0
]
data_out
,
// data out
input
wclk
,
// clock for read port
input
[
13
-
LOG2WIDTH_WR
:
0
]
waddr
,
// write address
input
we
,
// write port enable
input
[
3
:
0
]
web
,
// write byte enable
input
[(
9
<<
(
LOG2WIDTH_WR
-
3
))
-
1
:
0
]
data_in
// data out
)
;
localparam
PWIDTH_WR
=
(
LOG2WIDTH_WR
>
2
)
?
(
9
<<
(
LOG2WIDTH_WR
-
3
))
:
(
1
<<
LOG2WIDTH_WR
)
;
localparam
PWIDTH_RD
=
(
LOG2WIDTH_RD
>
2
)
?
(
9
<<
(
LOG2WIDTH_RD
-
3
))
:
(
1
<<
LOG2WIDTH_RD
)
;
localparam
WIDTH_WR
=
1
<<
LOG2WIDTH_WR
;
localparam
WIDTH_WRP
=
1
<<
(
LOG2WIDTH_WR
-
3
)
;
localparam
WIDTH_RD
=
1
<<
LOG2WIDTH_RD
;
localparam
WIDTH_RDP
=
1
<<
(
LOG2WIDTH_RD
-
3
)
;
wire
[
15
:
0
]
data_out16
;
wire
[
1
:
0
]
datap_out2
;
assign
data_out
={
datap_out2
[
WIDTH_RDP
-
1
:
0
]
,
data_out16
[
WIDTH_RD
-
1
:
0
]
};
wire
[
WIDTH_WR
+
15
:
0
]
data_in_ext
=
{
16'b0
,
data_in
[
WIDTH_WR
-
1
:
0
]
};
wire
[
15
:
0
]
data_in16
=
data_in_ext
[
15
:
0
]
;
wire
[
WIDTH_WRP
+
1
:
0
]
datap_in_ext
=
{
2'b0
,
data_in
[
WIDTH_WR
+:
WIDTH_WRP
]
};
wire
[
1
:
0
]
datap_in2
=
datap_in_ext
[
1
:
0
]
;
RAMB18E1
#(
.
RSTREG_PRIORITY_A
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
RSTREG_PRIORITY_B
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
DOA_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
DOB_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
READ_WIDTH_A
(
PWIDTH_RD
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
READ_WIDTH_B
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_A
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_B
(
PWIDTH_WR
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
RAM_MODE
(
"TDP"
)
,
// Valid "TDP" (true dual-port) and "SDP" - simple dual-port
.
WRITE_MODE_A
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
WRITE_MODE_B
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
RDADDR_COLLISION_HWCONFIG
(
"DELAYED_WRITE"
)
,
// Valid: "DELAYED_WRITE","PERFORMANCE" (no access to the same page)
.
SIM_COLLISION_CHECK
(
"ALL"
)
,
// Valid: "ALL", "GENERATE_X_ONLY", "NONE", and "WARNING_ONLY"
.
INIT_FILE
(
"NONE"
)
,
// "NONE" or filename with initialization data
.
SIM_DEVICE
(
"7SERIES"
)
// Simulation device family - "VIRTEX6", "VIRTEX5" and "7_SERIES" // "7SERIES"
)
RAMB36E1_i
(
// Port A (Read port in SDP mode):
.
DOADO
(
data_out16
)
,
// Port A data/LSB data[15:0], output
.
DOPADOP
(
datap_out2
)
,
// Port A parity/LSB parity[1:0], output
.
DIADI
(
16'h0
)
,
// Port A data/LSB data[15:0], input
.
DIPADIP
(
2'h0
)
,
// Port A parity/LSB parity[1:0], input
.
ADDRARDADDR
(
{
raddr
,{
LOG2WIDTH_RD
{
1'b1
}}}
)
,
// Port A (read port in SDP) address [13:0], unused should be high, input
.
CLKARDCLK
(
rclk
)
,
// Port A (read port in SDP) clock, input
.
ENARDEN
(
ren
)
,
// Port A (read port in SDP) Enable, input
.
REGCEAREGCE
(
regen
)
,
// Port A (read port in SDP) register enable, input
.
RSTRAMARSTRAM
(
1'b0
)
,
// Port A (read port in SDP) set/reset, input
.
RSTREGARSTREG
(
1'b0
)
,
// Port A (read port in SDP) register set/reset, input
.
WEA
(
2'b0
)
,
// Port A (read port in SDP) Write Enable[3:0], input
// Port B
.
DOBDO
()
,
// Port B data/MSB data[31:0], output
.
DOPBDOP
()
,
// Port B parity/MSB parity[3:0], output
.
DIBDI
(
data_in16
)
,
// Port B data/MSB data[31:0], input
.
DIPBDIP
(
datap_in2
)
,
// Port B parity/MSB parity[3:0], input
.
ADDRBWRADDR
(
{
waddr
,{
LOG2WIDTH_WR
{
1'b1
}}}
)
,
// Port B (write port in SDP) address [13:0], unused should be high, input
.
CLKBWRCLK
(
wclk
)
,
// Port B (write port in SDP) clock, input
.
ENBWREN
(
we
)
,
// Port B (write port in SDP) Enable, input
.
REGCEB
(
1'b0
)
,
// Port B (write port in SDP) register enable, input
.
RSTRAMB
(
1'b0
)
,
// Port B (write port in SDP) set/reset, input
.
RSTREGB
(
1'b0
)
,
// Port B (write port in SDP) register set/reset, input
.
WEBWE
(
web
[
3
:
0
])
// Port B (write port in SDP) Write Enable[3:0], input
)
;
endmodule
// Write port less than 32bits, read port 32 bit widths
module
ramp_lt32w_32r
#(
parameter
integer
REGISTERS
=
0
,
// 1 - registered output
parameter
integer
LOG2WIDTH_WR
=
4
// WIDTH= 1 << LOG2WIDTH
)
(
input
rclk
,
// clock for read port
input
[
8
:
0
]
raddr
,
// read address
input
ren
,
// read port enable
input
regen
,
// output register enable
output
[
35
:
0
]
data_out
,
// data out
input
wclk
,
// clock for read port
input
[
13
-
LOG2WIDTH_WR
:
0
]
waddr
,
// write address
input
we
,
// write port enable
input
[
3
:
0
]
web
,
// write byte enable
input
[(
9
<<
(
LOG2WIDTH_WR
-
3
))
-
1
:
0
]
data_in
// data out
)
;
localparam
PWIDTH_WR
=
(
LOG2WIDTH_WR
>
2
)
?
(
9
<<
(
LOG2WIDTH_WR
-
3
))
:
(
1
<<
LOG2WIDTH_WR
)
;
localparam
PWIDTH_RD
=
36
;
localparam
WIDTH_WR
=
1
<<
LOG2WIDTH_WR
;
localparam
WIDTH_WRP
=
1
<<
(
LOG2WIDTH_WR
-
3
)
;
wire
[
WIDTH_WR
+
15
:
0
]
data_in_ext
=
{
16'b0
,
data_in
[
WIDTH_WR
-
1
:
0
]
};
wire
[
15
:
0
]
data_in16
=
data_in_ext
[
15
:
0
]
;
wire
[
WIDTH_WRP
+
1
:
0
]
datap_in_ext
=
{
2'b0
,
data_in
[
WIDTH_WR
+:
WIDTH_WRP
]
};
wire
[
1
:
0
]
datap_in2
=
datap_in_ext
[
1
:
0
]
;
RAMB18E1
#(
.
RSTREG_PRIORITY_A
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
RSTREG_PRIORITY_B
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
DOA_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
DOB_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
READ_WIDTH_A
(
PWIDTH_RD
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
READ_WIDTH_B
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_A
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_B
(
PWIDTH_WR
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
RAM_MODE
(
"SDP"
)
,
// Valid "TDP" (true dual-port) and "SDP" - simple dual-port
.
WRITE_MODE_A
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
WRITE_MODE_B
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
RDADDR_COLLISION_HWCONFIG
(
"DELAYED_WRITE"
)
,
// Valid: "DELAYED_WRITE","PERFORMANCE" (no access to the same page)
.
SIM_COLLISION_CHECK
(
"ALL"
)
,
// Valid: "ALL", "GENERATE_X_ONLY", "NONE", and "WARNING_ONLY"
.
INIT_FILE
(
"NONE"
)
,
// "NONE" or filename with initialization data
.
SIM_DEVICE
(
"7SERIES"
)
// Simulation device family - "VIRTEX6", "VIRTEX5" and "7_SERIES" // "7SERIES"
)
RAMB36E1_i
(
// Port A (Read port in SDP mode):
.
DOADO
(
data_out
[
15
:
0
])
,
// Port A data/LSB data[15:0], output
.
DOPADOP
(
data_out
[
17
:
16
])
,
// Port A parity/LSB parity[3:0], output
.
DIADI
(
16'h0
)
,
// Port A data/LSB data[31:0], input
.
DIPADIP
(
2'h0
)
,
// Port A parity/LSB parity[3:0], input
.
ADDRARDADDR
(
{
raddr
[
8
:
0
]
,
5'b11111
}
)
,
// Port A (read port in SDP) address [15:0]. used from [14] down, unused should be high, input
.
CLKARDCLK
(
rclk
)
,
// Port A (read port in SDP) clock, input
.
ENARDEN
(
ren
)
,
// Port A (read port in SDP) Enable, input
.
REGCEAREGCE
(
regen
)
,
// Port A (read port in SDP) register enable, input
.
RSTRAMARSTRAM
(
1'b0
)
,
// Port A (read port in SDP) set/reset, input
.
RSTREGARSTREG
(
1'b0
)
,
// Port A (read port in SDP) register set/reset, input
.
WEA
(
2'b0
)
,
// Port A (read port in SDP) Write Enable[3:0], input
// Port B
.
DOBDO
(
data_out
[
33
:
18
])
,
// Port B data/MSB data[31:0], output
.
DOPBDOP
(
data_out
[
35
:
34
])
,
// Port B parity/MSB parity[3:0], output
.
DIBDI
(
data_in16
)
,
// Port B data/MSB data[31:0], input
.
DIPBDIP
(
datap_in2
)
,
// Port B parity/MSB parity[3:0], input
.
ADDRBWRADDR
(
{
waddr
,{
LOG2WIDTH_WR
{
1'b1
}}}
)
,
// Port B (write port in SDP) address [15:0]. used from [14] down, unused should be high, input
.
CLKBWRCLK
(
wclk
)
,
// Port B (write port in SDP) clock, input
.
ENBWREN
(
we
)
,
// Port B (write port in SDP) Enable, input
.
REGCEB
(
1'b0
)
,
// Port B (write port in SDP) register enable, input
.
RSTRAMB
(
1'b0
)
,
// Port B (write port in SDP) set/reset, input
.
RSTREGB
(
1'b0
)
,
// Port B (write port in SDP) register set/reset, input
.
WEBWE
(
web
[
3
:
0
])
// Port B (write port in SDP) Write Enable[7:0], input
)
;
endmodule
// Write port 64 bita, read port - less than 64 bits
module
ram18p_32w_lt32r
#(
parameter
integer
REGISTERS
=
0
,
// 1 - registered output
// parameter integer LOG2WIDTH_WR = 4, // WIDTH= 1 << LOG2WIDTH
parameter
integer
LOG2WIDTH_RD
=
4
// WIDTH= 1 << LOG2WIDTH
)
(
input
rclk
,
// clock for read port
input
[
13
-
LOG2WIDTH_RD
:
0
]
raddr
,
// read address
input
ren
,
// read port enable
input
regen
,
// output register enable
output
[(
9
<<
(
LOG2WIDTH_RD
-
3
))
-
1
:
0
]
data_out
,
// data out
input
wclk
,
// clock for read port
input
[
8
:
0
]
waddr
,
// write address
input
we
,
// write port enable
input
[
3
:
0
]
web
,
// write byte enable
input
[
35
:
0
]
data_in
// data out
)
;
localparam
PWIDTH_WR
=
72
;
localparam
PWIDTH_RD
=
(
LOG2WIDTH_RD
>
2
)
?
(
9
<<
(
LOG2WIDTH_RD
-
3
))
:
(
1
<<
LOG2WIDTH_RD
)
;
localparam
WIDTH_RD
=
1
<<
LOG2WIDTH_RD
;
localparam
WIDTH_RDP
=
1
<<
(
LOG2WIDTH_RD
-
3
)
;
wire
[
15
:
0
]
data_out16
;
wire
[
1
:
0
]
datap_out2
;
assign
data_out
={
datap_out2
[
WIDTH_RDP
-
1
:
0
]
,
data_out16
[
WIDTH_RD
-
1
:
0
]
};
RAMB18E1
#(
.
RSTREG_PRIORITY_A
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
RSTREG_PRIORITY_B
(
"RSTREG"
)
,
// Valid: "RSTREG" or "REGCE"
.
DOA_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
DOB_REG
(
REGISTERS
)
,
// Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 18)
.
READ_WIDTH_A
(
PWIDTH_RD
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
READ_WIDTH_B
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_A
(
0
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
WRITE_WIDTH_B
(
PWIDTH_WR
)
,
// Valid: 0,1,2,4,9,18 and in SDP mode - 36 (should be 0 if port is not used)
.
RAM_MODE
(
"SDP"
)
,
// Valid "TDP" (true dual-port) and "SDP" - simple dual-port
.
WRITE_MODE_A
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
WRITE_MODE_B
(
"WRITE_FIRST"
)
,
// Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.
RDADDR_COLLISION_HWCONFIG
(
"DELAYED_WRITE"
)
,
// Valid: "DELAYED_WRITE","PERFORMANCE" (no access to the same page)
.
SIM_COLLISION_CHECK
(
"ALL"
)
,
// Valid: "ALL", "GENERATE_X_ONLY", "NONE", and "WARNING_ONLY"
.
INIT_FILE
(
"NONE"
)
,
// "NONE" or filename with initialization data
.
SIM_DEVICE
(
"7SERIES"
)
// Simulation device family - "VIRTEX6", "VIRTEX5" and "7_SERIES" // "7SERIES"
)
RAMB36E1_i
(
// Port A (Read port in SDP mode):
.
DOADO
(
data_out16
)
,
// Port A data/LSB data[15:0], output
.
DOPADOP
(
datap_out2
)
,
// Port A parity/LSB parity[1:0], output
.
DIADI
(
data_in
[
15
:
0
])
,
// Port A data/LSB data[15:0], input
.
DIPADIP
(
data_in
[
17
:
16
])
,
// Port A parity/LSB parity[1:0], input
.
ADDRARDADDR
(
{
raddr
,{
LOG2WIDTH_RD
{
1'b1
}}}
)
,
// Port A (read port in SDP) address [13:0], unused should be high, input
.
CLKARDCLK
(
rclk
)
,
// Port A (read port in SDP) clock, input
.
ENARDEN
(
ren
)
,
// Port A (read port in SDP) Enable, input
.
REGCEAREGCE
(
regen
)
,
// Port A (read port in SDP) register enable, input
.
RSTRAMARSTRAM
(
1'b0
)
,
// Port A (read port in SDP) set/reset, input
.
RSTREGARSTREG
(
1'b0
)
,
// Port A (read port in SDP) register set/reset, input
.
WEA
(
2'b0
)
,
// Port A (read port in SDP) Write Enable[1:0], input
// Port B
.
DOBDO
()
,
// Port B data/MSB data[15:0], output
.
DOPBDOP
()
,
// Port B parity/MSB parity[1:0], output
.
DIBDI
(
data_in
[
33
:
18
])
,
// Port B data/MSB data[15:0], input
.
DIPBDIP
(
data_in
[
35
:
34
])
,
// Port B parity/MSB parity[1:0], input
.
ADDRBWRADDR
(
{
waddr
[
8
:
0
]
,
5'b11111
}
)
,
// Port B (write port in SDP) address [13:0], unused should be high, input
.
CLKBWRCLK
(
wclk
)
,
// Port B (write port in SDP) clock, input
.
ENBWREN
(
we
)
,
// Port B (write port in SDP) Enable, input
.
REGCEB
(
1'b0
)
,
// Port B (write port in SDP) register enable, input
.
RSTRAMB
(
1'b0
)
,
// Port B (write port in SDP) set/reset, input
.
RSTREGB
(
1'b0
)
,
// Port B (write port in SDP) register set/reset, input
.
WEBWE
(
web
[
3
:
0
])
// Port B (write port in SDP) Write Enable[7:0], input
)
;
endmodule
module
ram18p_dummy
#(
parameter
integer
LOG2WIDTH_RD
=
4
// WIDTH= 1 << LOG2WIDTH
)
(
output
[(
9
<<
(
LOG2WIDTH_RD
-
3
))
-
1
:
0
]
data_out
// data out
)
;
assign
data_out
=
0
;
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