Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
P
Platform-independent core collection
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
18
Issues
18
List
Board
Labels
Milestones
Merge Requests
5
Merge Requests
5
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Platform-independent core collection
Commits
ba4bbfd2
Commit
ba4bbfd2
authored
Dec 15, 2022
by
Dimitris Lampridis
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'proposed_master'
parents
97bc6910
074d4468
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
1854 additions
and
187 deletions
+1854
-187
Manifest.py
Manifest.py
+1
-0
README.md
README.md
+11
-1
Manifest.py
modules/axi/Manifest.py
+1
-0
Manifest.py
modules/axi/axi4lite_axi4full_bridge/Manifest.py
+3
-0
axi4lite_axi4full_bridge.vhd
...axi/axi4lite_axi4full_bridge/axi4lite_axi4full_bridge.vhd
+316
-0
Manifest.py
modules/common/Manifest.py
+0
-1
gc_pulse_synchronizer2.vhd
modules/common/gc_pulse_synchronizer2.vhd
+31
-24
gc_sync_word_rd.vhd
modules/common/gc_sync_word_rd.vhd
+8
-5
gc_reset_multi_aasd.xdc
modules/common/xdc/gc_reset_multi_aasd.xdc
+5
-0
gc_sync.xdc
modules/common/xdc/gc_sync.xdc
+21
-0
gc_sync_register.xdc
modules/common/xdc/gc_sync_register.xdc
+22
-0
gc_sync_word_rd.xdc
modules/common/xdc/gc_sync_word_rd.xdc
+17
-0
gc_sync_word_wr.xdc
modules/common/xdc/gc_sync_word_wr.xdc
+17
-0
memory_loader_pkg.vhd
modules/genrams/memory_loader_pkg.vhd
+1
-1
Manifest.py
modules/radtol/Manifest.py
+5
-0
secded_32b_pkg.vhd
modules/radtol/secded_32b_pkg.vhd
+128
-0
secded_ecc.vhd
modules/radtol/secded_ecc.vhd
+279
-0
voter_status.vhd
modules/radtol/voter_status.vhd
+39
-0
voter_vec_status.vhd
modules/radtol/voter_vec_status.vhd
+54
-0
xwb_axi4lite_bridge.vhd
modules/wishbone/wb_axi4lite_bridge/xwb_axi4lite_bridge.vhd
+1
-1
Manifest.py
modules/wishbone/wb_fine_pulse_gen/Manifest.py
+13
-8
fine_pulse_gen_kintexultrascale_shared.vhd
...fine_pulse_gen/fine_pulse_gen_kintexultrascale_shared.vhd
+1
-1
Manifest.py
modules/wishbone/wb_register/Manifest.py
+1
-0
wb_skidpad2.vhd
modules/wishbone/wb_register/wb_skidpad2.vhd
+124
-0
wb_tics.vhd
modules/wishbone/wb_simple_timer/wb_tics.vhd
+2
-2
spi_wb.cheby
modules/wishbone/wb_spi/spi_wb.cheby
+190
-0
Manifest.py
modules/wishbone/wb_xc7_fw_update/Manifest.py
+9
-3
xwb_xc7_fw_update.vhd
modules/wishbone/wb_xc7_fw_update/xwb_xc7_fw_update.vhd
+29
-61
xwb_xc7_fw_update_v2.vhd
modules/wishbone/wb_xc7_fw_update/xwb_xc7_fw_update_v2.vhd
+111
-0
pcie_wb.vhd
platform/altera/wb_pcie/pcie_wb.vhd
+45
-44
if_wb_master.svh
sim/if_wb_master.svh
+31
-29
if_wishbone_accessor.svh
sim/if_wishbone_accessor.svh
+7
-6
if_wishbone_types.svh
sim/if_wishbone_types.svh
+1
-0
simdrv_wb_spi.svh
sim/simdrv_wb_spi.svh
+87
-0
tb_secded_32b_pkg.vhd
testbench/radtol/tb_secded_32b_pkg.vhd
+83
-0
tb_secded_ecc.vhd
testbench/radtol/tb_secded_ecc.vhd
+160
-0
No files found.
Manifest.py
View file @
ba4bbfd2
...
...
@@ -4,6 +4,7 @@ modules = {
"modules/common"
,
"modules/genrams"
,
"modules/wishbone"
,
"modules/radtol"
,
"platform"
]
}
README.md
View file @
ba4bbfd2
...
...
@@ -44,6 +44,13 @@ In [modules/common](modules/common) there are general purpose cores:
contains a complex handling for asynchronous signals (crossing clock
domains, deglitcher, edge detection, pulse extension...)
*
CDC modules come also with specific timing contraints in
[
modules/common/xdc
](
modules/common/xdc
)
.
These constraints can be used in Vivado projects (so-called "module-bound" constraints)
to automatically derive proper timing constraints for CDC paths in each module.
To use it, add specific constraint file to your project and set
`SCOPED_TO_REF`
property in GUI or your TCL file.
(e.g. add
`gc_sync.xdc`
if you use
`gc_sync.vhd`
and set
`SCOPED_TO_REF=gc_sync`
)
*
For reset generation, you can use
[
gc_reset
](
modules/common/gc_reset.vhd
)
which generate synchronous resets once all the PLL lock signals are set.
The module
[
gc_reset_multi_aasd
](
modules/common/gc_reset_multi_aasd.vhd
)
...
...
@@ -202,7 +209,10 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
*
There are utilities to handle a wishbone bus:
-
[
wb_clock_crossing
](
modules/wishbone/wb_clock_crossing
)
handle clock domain
crossing.
-
[
wb_register
](
modules/wishbone/wb_register
)
add a pipeline register.
-
[
wb_register
](
modules/wishbone/wb_register
)
adds a pipeline register.
-
[
wb_skidpad2
](
modules/wishbone/wb_register
)
adds a pipeline register to
a pipelined wishbone bus (in one direction only) without downgrading
the throughput.
*
There are modules to convert to a different bus
-
[
wb_async_bridge
](
modules/wishbone/wb_async_bridge
)
is a bridge with the
...
...
modules/axi/Manifest.py
View file @
ba4bbfd2
...
...
@@ -2,6 +2,7 @@ modules = { "local" : [
"z7_axi_gpio_expander"
,
"axi4lite_wb_bridge"
,
"axi4lite32_axi4full64_bridge"
,
"axi4lite_axi4full_bridge"
,
]}
files
=
[
...
...
modules/axi/axi4lite_axi4full_bridge/Manifest.py
0 → 100644
View file @
ba4bbfd2
files
=
[
"axi4lite_axi4full_bridge.vhd"
,
];
modules/axi/axi4lite_axi4full_bridge/axi4lite_axi4full_bridge.vhd
0 → 100644
View file @
ba4bbfd2
This diff is collapsed.
Click to expand it.
modules/common/Manifest.py
View file @
ba4bbfd2
...
...
@@ -42,5 +42,4 @@ files = [
"gc_async_counter_diff.vhd"
,
"gc_sync_word_wr.vhd"
,
"gc_sync_word_rd.vhd"
,
"gc_simple_spi_master.vhd"
];
modules/common/gc_pulse_synchronizer2.vhd
View file @
ba4bbfd2
...
...
@@ -89,31 +89,38 @@ begin -- rtl
p_input_ack
:
process
(
clk_in_i
)
begin
if
rising_edge
(
clk_in_i
)
then
d_p_d0
<=
d_p_i
;
d_ack_d0
<=
d_ack
;
if
ready
=
'1'
and
d_p_i
=
'1'
and
d_p_d0
=
'0'
then
-- Incoming pulse detected and the system is ready.
-- Transfer it.
in_ext
<=
'1'
;
-- Clear ack and ready!
d_ack
<=
'0'
;
ready
<=
'0'
;
elsif
in_ext
=
'1'
and
out_feedback
=
'1'
then
-- Pulse has been transfered, clear the input.
in_ext
<=
'0'
;
elsif
in_ext
=
'0'
and
out_feedback
=
'0'
then
-- Clear transfered. Done.
-- This is also the steady state.
d_ack
<=
'1'
;
if
rst_in_n_i
=
'0'
then
d_p_d0
<=
'0'
;
d_ack
<=
'0'
;
d_ack_d0
<=
'0'
;
ready
<=
'1'
;
end
if
;
if
ready
=
'0'
then
assert
d_p_i
=
'0'
or
(
d_p_i
=
'1'
and
d_p_d0
=
'1'
)
report
"request while previous one not completed"
severity
ERROR
;
in_ext
<=
'0'
;
else
d_p_d0
<=
d_p_i
;
d_ack_d0
<=
d_ack
;
if
ready
=
'1'
and
d_p_i
=
'1'
and
d_p_d0
=
'0'
then
-- Incoming pulse detected and the system is ready.
-- Transfer it.
in_ext
<=
'1'
;
-- Clear ack and ready!
d_ack
<=
'0'
;
ready
<=
'0'
;
elsif
in_ext
=
'1'
and
out_feedback
=
'1'
then
-- Pulse has been transfered, clear the input.
in_ext
<=
'0'
;
elsif
in_ext
=
'0'
and
out_feedback
=
'0'
then
-- Clear transfered. Done.
-- This is also the steady state.
d_ack
<=
'1'
;
ready
<=
'1'
;
end
if
;
if
ready
=
'0'
then
assert
d_p_i
=
'0'
or
(
d_p_i
=
'1'
and
d_p_d0
=
'1'
)
report
"request while previous one not completed"
severity
ERROR
;
end
if
;
end
if
;
end
if
;
end
process
p_input_ack
;
...
...
modules/common/gc_sync_word_rd.vhd
View file @
ba4bbfd2
...
...
@@ -67,6 +67,7 @@ architecture arch of gc_sync_word_rd is
signal
d_ready
:
std_logic
;
signal
wr_in
:
std_logic
;
signal
rd_out
:
std_logic
;
begin
cmp_pulse_sync
:
entity
work
.
gc_pulse_synchronizer2
port
map
(
...
...
@@ -88,18 +89,20 @@ begin
end
if
;
end
process
;
p_writer
:
process
(
clk_out_i
)
p_writer
:
process
(
clk_out_i
)
begin
if
rising_edge
(
clk_out_i
)
then
if
rst_in_n_i
=
'0'
then
ack_out_o
<=
'0'
;
elsif
wr_in
=
'1'
then
if
wr_in
=
'1'
then
-- Data is stable.
data_out_o
<=
gc_sync_word_data
;
ack_out_o
<=
'1'
;
ack_out_o
<=
'1'
;
else
ack_out_o
<=
'0'
;
end
if
;
if
rst_out_n_i
=
'0'
then
ack_out_o
<=
'0'
;
end
if
;
end
if
;
end
process
;
end
arch
;
modules/common/xdc/gc_reset_multi_aasd.xdc
0 → 100644
View file @
ba4bbfd2
# the "-quiet" option is added for the use case where this module is added to
# the project, but not instatiated (e.g. because of generic settings)
# in that case Vivado would throw critical warnings during P&$
set_false_path -quiet -to [get_pins -hierarchical *rst_chains_reg[*]/CLR]
modules/common/xdc/gc_sync.xdc
0 → 100644
View file @
ba4bbfd2
# Timing constrains for basic 1 bit synchroniser.
# In many cases this could be solved with simple set_false_path, but in some
# cases this module is used in more time-critical applications, eg. inferred FIFO.
# In that case it makes sense to apply some max_delay constraint.
#
# You can always override any of these max_delay constraints in your global XDC
# with set_false_path because it has the highest priority.
set clk [get_clocks -of_objects [get_ports clk_i]]
set clk_period [get_property PERIOD $clk]
# ATTENTION: we can't use "all_fanin" to find the source register because
# apparently this command doesn't traverse outside of scoped reference (even with -flat switch)
# This method won't work properly if there's a combinational path between a source and target FF;
# but in a proper CDC circuit it's forbidded to have logic between FFs anyway!
set dst_ff [get_pins sync_*.sync0_*/D]
set src_ff [get_cells -of_objects [get_pins -filter {IS_LEAF && DIRECTION == OUT} -of_objects [get_nets -segments -of_objects $dst_ff]]]
# We use -quiet switch, because otherwise Vivado will throw critical warning
# if module is not used in the project (e.g. due to generics)
set_max_delay $clk_period -quiet -datapath_only -from $src_ff -to $dst_ff
modules/common/xdc/gc_sync_register.xdc
0 → 100644
View file @
ba4bbfd2
# Timing constrains for basic bit vector synchroniser.
#
# This is similar to gc_sync, but vector synchronisation is usually more tricky.
# Usually you really want to limit bus skew and delay to one clock cycle.
#
# You can always override any of these max_delay constraints in your global XDC
# with set_false_path because it has the highest priority.
set clk [get_clocks -of_objects [get_ports clk_i]]
set clk_period [get_property PERIOD $clk]
# ATTENTION: we can't use "all_fanin" to find the source register because
# apparently this command doesn't traverse outside of scoped reference (even with -flat switch)
# This method won't work properly if there's a combinational path between a source and target FF;
# but in a proper CDC circuit it's forbidded to have logic between FFs anyway!
set dst_ff [get_pins sync0_*[*]/D]
set src_ff [get_cells -of_objects [get_pins -filter {IS_LEAF && DIRECTION == OUT} -of_objects [get_nets -segments -of_objects $dst_ff]]]
# We use -quiet switch, because otherwise Vivado will throw critical warning
# if module is not used in the project (e.g. due to generics)
set_max_delay $clk_period -quiet -datapath_only -from $src_ff -to $dst_ff
set_bus_skew $clk_period -quiet -from $src_ff -to $dst_ff
modules/common/xdc/gc_sync_word_rd.xdc
0 → 100644
View file @
ba4bbfd2
# Timing constrains for read word synchronizer.
# Flag handskaking is done by pulse synchroniser submodule which should have its
# own constraint file and thus isn't covered here
set src_clk [get_clocks -of_objects [get_ports clk_in_i]]
set dst_clk [get_clocks -of_objects [get_ports clk_out_i]]
set src_clk_period [get_property PERIOD $src_clk]
set dst_clk_period [get_property PERIOD $dst_clk]
set skew_value [expr {(($src_clk_period < $dst_clk_period) ? $src_clk_period : $dst_clk_period)}]
set src_ff [get_pins gc_sync_word_data*[*]/C]
set dst_ff [get_pins data_out*[*]/D]
# We use -quiet switch, because otherwise Vivado will throw critical warning
# if module is not used in the project (e.g. due to generics)
set_max_delay $skew_value -quiet -datapath_only -from $src_ff -to $dst_ff
set_bus_skew $skew_value -quiet -from $src_ff -to $dst_ff
modules/common/xdc/gc_sync_word_wr.xdc
0 → 100644
View file @
ba4bbfd2
# Timing constrains for write word synchronizer.
# Flag handskaking is done by pulse synchroniser submodule which should have its
# own constraint file and thus isn't covered here
set src_clk [get_clocks -of_objects [get_ports clk_in_i]]
set dst_clk [get_clocks -of_objects [get_ports clk_out_i]]
set src_clk_period [get_property PERIOD $src_clk]
set dst_clk_period [get_property PERIOD $dst_clk]
set skew_value [expr {(($src_clk_period < $dst_clk_period) ? $src_clk_period : $dst_clk_period)}]
set src_ff [get_pins gc_sync_word_data*[*]/C]
set dst_ff [get_pins dat_out*[*]/D]
# We use -quiet switch, because otherwise Vivado will throw critical warning
# if module is not used in the project (e.g. due to generics)
set_max_delay $skew_value -quiet -datapath_only -from $src_ff -to $dst_ff
set_bus_skew $skew_value -quiet -from $src_ff -to $dst_ff
modules/genrams/memory_loader_pkg.vhd
View file @
ba4bbfd2
...
...
@@ -88,7 +88,7 @@ package body memory_loader_pkg is
open_status
:
in
file_open_status
;
fail_if_notfound
:
in
boolean
)
is
begin
if
open_status
/=
OPEN_OK
then
if
not
(
open_status
=
OPEN_OK
)
then
if
fail_if_notfound
then
report
"f_load_mem_from_file(): can't open file '"
&
file_name
&
"'"
severity
FAILURE
;
...
...
modules/radtol/Manifest.py
0 → 100644
View file @
ba4bbfd2
files
=
[
"secded_32b_pkg.vhd"
,
"voter_status.vhd"
,
"voter_vec_status.vhd"
,
]
modules/radtol/secded_32b_pkg.vhd
0 → 100644
View file @
ba4bbfd2
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: secded_32b_pkg
--
-- description: ECC on 32b
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020-2021
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
package
secded_32b_pkg
is
subtype
data_word_t
is
std_logic_vector
(
31
downto
0
);
subtype
ecc_word_t
is
std_logic_vector
(
6
downto
0
);
-- Compute the ECC bits for DATA.
-- The ECC is a xor of some DATA bits.
function
f_calc_ecc
(
data
:
data_word_t
)
return
ecc_word_t
;
-- SYNDROME is the xor of read ECC and recomputed ECC.
-- The xor should be 0, except in case of errors.
-- Return '1' if there is a difference (so if SYNDROME is not 0)
function
f_ecc_errors
(
syndrome
:
ecc_word_t
)
return
std_logic
;
-- Return '1' if the number of SYNDOME bits set to 1 is odd.
-- (a one bit error results in 1 or 3 bits set in the syndrome)
function
f_ecc_one_error
(
syndrome
:
ecc_word_t
)
return
std_logic
;
-- Fix the error (if any).
-- Returns new ecc + data, from syndrome and original ecc + data.
function
f_fix_error
(
syndrome
:
ecc_word_t
;
ecc
:
ecc_word_t
;
data
:
data_word_t
)
return
std_logic_vector
;
end
secded_32b_pkg
;
package
body
secded_32b_pkg
is
function
f_xor
(
x
:
std_logic_vector
)
return
std_logic
is
variable
result
:
std_logic
:
=
'0'
;
begin
for
i
in
x
'range
loop
result
:
=
result
xor
x
(
i
);
end
loop
;
return
result
;
end
f_xor
;
type
syndrome_mask_array
is
array
(
0
to
6
)
of
data_word_t
;
constant
syndrome_masks
:
syndrome_mask_array
:
=
(
0
=>
"11000001010010000100000011111111"
,
1
=>
"00100001001001001111111110010000"
,
2
=>
"01101100111111110000100000001000"
,
3
=>
"11111111000000011010010001000100"
,
4
=>
"00010110111100001001001010100110"
,
5
=>
"00010000000111110111000101100001"
,
6
=>
"10001010100000100000111100011011"
);
function
f_calc_ecc
(
data
:
data_word_t
)
return
ecc_word_t
is
variable
result
:
ecc_word_t
;
begin
for
i
in
result
'range
loop
result
(
i
)
:
=
f_xor
(
data
and
syndrome_masks
(
i
));
end
loop
;
return
result
;
end
f_calc_ecc
;
function
f_ecc_errors
(
syndrome
:
ecc_word_t
)
return
std_logic
is
variable
result
:
std_logic
:
=
'0'
;
begin
-- There is at least one error if the syndrome is not 0.
for
i
in
syndrome
'range
loop
result
:
=
result
or
syndrome
(
i
);
end
loop
;
return
result
;
end
f_ecc_errors
;
function
f_ecc_one_error
(
syndrome
:
ecc_word_t
)
return
std_logic
is
begin
-- If there is no error, syndrome is 0 so it will return 0.
-- If there is one error, 1 or 3 bits are set in the syndrome, so returns 1.
-- If there are 2 errors, 2, 4 or 6 bits are set in the syncrome, so returns 0.
-- If there are more than 2 errors, all bets are off (it's a secded).
return
f_xor
(
syndrome
);
end
f_ecc_one_error
;
function
f_fix_error
(
syndrome
:
ecc_word_t
;
ecc
:
ecc_word_t
;
data
:
data_word_t
)
return
std_logic_vector
is
variable
result
:
data_word_t
:
=
(
others
=>
'1'
);
begin
-- Compute which data bits have been altered.
-- If a data bit is altered, its corresponding ECC bits are altered too.
-- So, conversely (and because there is only one error), the altered ECC bits
-- designate the altered data bit.
for
i
in
0
to
31
loop
for
k
in
0
to
6
loop
if
syndrome_masks
(
k
)(
i
)
=
'1'
then
result
(
i
)
:
=
result
(
i
)
and
syndrome
(
k
);
end
if
;
end
loop
;
end
loop
;
-- Return the fixed ecc+data.
if
result
/=
(
data_word_t
'range
=>
'0'
)
then
return
ecc
&
(
data
xor
result
);
else
return
(
syndrome
xor
ecc
)
&
(
data
xor
result
);
end
if
;
end
f_fix_error
;
end
secded_32b_pkg
;
modules/radtol/secded_ecc.vhd
0 → 100644
View file @
ba4bbfd2
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: secded_ecc
--
-- description: SECDED RAM controller
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020-2021
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
work
.
secded_32b_pkg
.
all
;
entity
secded_ecc
is
generic
(
g_addr_width
:
natural
:
=
16
);
port
(
clk_i
:
in
std_logic
;
rst_i
:
in
std_logic
;
-- to the processor/bus
a_i
:
in
std_logic_vector
(
g_addr_width
-1
downto
0
);
d_i
:
in
std_logic_vector
(
31
downto
0
);
we_i
:
in
std_logic
;
bwe_i
:
in
std_logic_vector
(
3
downto
0
);
re_i
:
in
std_logic
;
q_o
:
out
std_logic_vector
(
31
downto
0
);
done_r_o
:
out
std_logic
;
done_w_o
:
out
std_logic
;
--to the BRAM
a_ram_o
:
out
std_logic_vector
(
g_addr_width
-1
downto
0
);
d_ram_i
:
in
std_logic_vector
(
38
downto
0
);
q_ram_o
:
out
std_logic_vector
(
38
downto
0
);
we_ram_o
:
out
std_logic
;
re_ram_o
:
out
std_logic
;
valid_ram_i
:
in
std_logic
;
lock_req_o
:
out
std_logic
;
lock_grant_i
:
in
std_logic
;
single_error_p_o
:
out
std_logic
;
double_error_p_o
:
out
std_logic
);
end
secded_ecc
;
architecture
rtl
of
secded_ecc
is
function
f_mask_word
(
mask
:
std_logic_vector
(
3
downto
0
);
d1
:
std_logic_vector
(
31
downto
0
);
d2
:
std_logic_vector
(
31
downto
0
))
return
std_logic_vector
is
variable
masked_word
:
std_logic_vector
(
31
downto
0
);
begin
for
i
in
1
to
4
loop
if
mask
(
i
-1
)
=
'0'
then
masked_word
(
i
*
8-1
downto
(
i
-1
)
*
8
)
:
=
d2
(
i
*
8-1
downto
(
i
-1
)
*
8
);
else
masked_word
(
i
*
8-1
downto
(
i
-1
)
*
8
)
:
=
d1
(
i
*
8-1
downto
(
i
-1
)
*
8
);
end
if
;
end
loop
;
return
masked_word
;
end
f_mask_word
;
type
fsm_read_states
is
(
normal_op
,
check_again
,
wait_lock
,
wait_correction
);
type
fsm_write_states
is
(
normal_op
,
check_write
);
type
fsm_rw_states
is
(
idle
,
wait_lock
,
wait_read
,
wait_write
);
signal
fsm_read
:
fsm_read_states
:
=
normal_op
;
signal
fsm_write
:
fsm_write_states
:
=
normal_op
;
signal
fsm_rw
:
fsm_rw_states
:
=
idle
;
signal
ecc_errors
,
ecc_correctable_error
:
std_logic
;
signal
syndrome
:
std_logic_vector
(
6
downto
0
);
signal
re_d
,
re_fsm
,
we_fsm
,
re
,
we
,
valid_ram_d
:
std_logic
;
signal
done_r
,
done_w
,
fsm_done_r_p
,
fsm_done_rw_p
:
std_logic
;
signal
lock_req_r
,
lock_req_rw
:
std_logic
;
signal
req_correction
,
ack_correction
:
std_logic
;
signal
fsm_read_normal
:
std_logic
;
signal
d
,
d_rw
:
std_logic_vector
(
31
downto
0
);
signal
q_ram
:
std_logic_vector
(
38
downto
0
);
attribute
syn_radhardlevel
:
string
;
attribute
syn_radhardlevel
of
rtl
:
architecture
is
"tmr"
;
begin
q_o
<=
d_ram_i
(
31
downto
0
);
re_ram_o
<=
'1'
when
(
fsm_read
/=
normal_op
)
else
re
;
syndrome
<=
f_calc_ecc
(
d_ram_i
(
31
downto
0
))
xor
d_ram_i
(
38
downto
32
);
ecc_errors
<=
f_ecc_errors
(
syndrome
);
ecc_correctable_error
<=
f_ecc_one_error
(
syndrome
);
fsm_read_normal
<=
'1'
when
fsm_read
=
normal_op
else
'0'
;
done_r
<=
(
re_d
and
valid_ram_d
and
fsm_read_normal
and
not
ecc_errors
)
or
fsm_done_r_p
;
done_r_o
<=
done_r
when
(
fsm_rw
=
idle
)
else
'0'
;
done_w_o
<=
'1'
when
(
fsm_done_rw_p
=
'1'
or
(
done_w
=
'1'
and
(
fsm_rw
=
idle
)))
else
'0'
;
process
(
rst_i
,
a_i
,
q_ram
)
begin
-- synthesis translate_off
if
rst_i
=
'1'
then
a_ram_o
<=
(
others
=>
'0'
);
q_ram_o
<=
(
others
=>
'0'
);
else
-- synthesis translate_on
a_ram_o
<=
a_i
;
q_ram_o
<=
q_ram
;
-- synthesis translate_off
end
if
;
-- synthesis translate_on
end
process
;
lock_req_o
<=
lock_req_r
or
lock_req_rw
;
we
<=
we_i
when
(
bwe_i
=
"1111"
)
else
we_fsm
;
re
<=
re_i
or
re_fsm
;
d
<=
d_i
when
(
fsm_rw
=
idle
)
else
d_rw
;
-- this FSM is used for sub-word writing, which require a word read and a word write
-- the read and write is atomic, dual-port thread-safe
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_i
=
'1'
then
fsm_rw
<=
idle
;
lock_req_rw
<=
'0'
;
re_fsm
<=
'0'
;
we_fsm
<=
'0'
;
fsm_done_rw_p
<=
'0'
;
else
case
fsm_rw
is
when
idle
=>
fsm_done_rw_p
<=
'0'
;
if
we_i
=
'1'
and
bwe_i
/=
"1111"
then
lock_req_rw
<=
'1'
;
fsm_rw
<=
wait_lock
;
end
if
;
when
wait_lock
=>
if
lock_grant_i
=
'1'
then
re_fsm
<=
'1'
;
fsm_rw
<=
wait_read
;
end
if
;
when
wait_read
=>
re_fsm
<=
'0'
;
if
done_r
=
'1'
then
d_rw
<=
f_mask_word
(
bwe_i
,
d_i
,
d_ram_i
(
31
downto
0
));
fsm_rw
<=
wait_write
;
we_fsm
<=
'1'
;
end
if
;
when
wait_write
=>
we_fsm
<=
'0'
;
if
done_w
=
'1'
then
fsm_done_rw_p
<=
'1'
;
lock_req_rw
<=
'0'
;
fsm_rw
<=
idle
;
end
if
;
when
others
=>
fsm_rw
<=
idle
;
end
case
;
end
if
;
end
if
;
end
process
;
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_i
=
'1'
then
fsm_read
<=
normal_op
;
re_d
<=
'0'
;
fsm_done_r_p
<=
'0'
;
lock_req_r
<=
'0'
;
req_correction
<=
'0'
;
single_error_p_o
<=
'0'
;
double_error_p_o
<=
'0'
;
else
re_d
<=
re
;
valid_ram_d
<=
valid_ram_i
;
case
fsm_read
is
when
normal_op
=>
fsm_done_r_p
<=
'0'
;
single_error_p_o
<=
'0'
;
double_error_p_o
<=
'0'
;
if
re_d
=
'1'
and
done_r
=
'0'
and
valid_ram_d
=
'1'
and
ecc_errors
=
'1'
then
fsm_read
<=
check_again
;
-- SET?
end
if
;
when
check_again
=>
if
valid_ram_d
=
'1'
and
ecc_errors
=
'1'
then
if
ecc_correctable_error
=
'0'
then
double_error_p_o
<=
'1'
;
fsm_done_r_p
<=
'1'
;
fsm_read
<=
normal_op
;
else
lock_req_r
<=
'1'
;
fsm_read
<=
wait_lock
;
end
if
;
elsif
valid_ram_d
=
'1'
and
ecc_errors
=
'0'
then
fsm_read
<=
normal_op
;
end
if
;
when
wait_lock
=>
if
lock_grant_i
=
'1'
then
req_correction
<=
'1'
;
fsm_read
<=
wait_correction
;
end
if
;
when
wait_correction
=>
--req_correction <= '0';
if
ack_correction
=
'1'
then
req_correction
<=
'0'
;
fsm_read
<=
normal_op
;
fsm_done_r_p
<=
'1'
;
single_error_p_o
<=
'1'
;
lock_req_r
<=
'0'
;
end
if
;
end
case
;
end
if
;
end
if
;
end
process
;
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_i
=
'1'
then
fsm_write
<=
normal_op
;
done_w
<=
'0'
;
we_ram_o
<=
'0'
;
else
ack_correction
<=
'0'
;
done_w
<=
'0'
;
case
fsm_write
is
when
normal_op
=>
ack_correction
<=
'0'
;
done_w
<=
'0'
;
if
req_correction
=
'1'
and
ack_correction
=
'0'
then
q_ram
<=
f_fix_error
(
syndrome
,
d_ram_i
(
38
downto
32
),
d_ram_i
(
31
downto
0
));
we_ram_o
<=
'1'
;
fsm_write
<=
check_write
;
elsif
we
=
'1'
then
q_ram
(
31
downto
0
)
<=
d
;
q_ram
(
38
downto
32
)
<=
f_calc_ecc
(
d
);
we_ram_o
<=
'1'
;
fsm_write
<=
check_write
;
end
if
;
when
check_write
=>
if
valid_ram_i
=
'1'
then
we_ram_o
<=
'0'
;
fsm_write
<=
normal_op
;
if
req_correction
=
'0'
then
done_w
<=
'1'
;
else
ack_correction
<=
'1'
;
end
if
;
end
if
;
end
case
;
end
if
;
end
if
;
end
process
;
end
architecture
;
modules/radtol/voter_status.vhd
0 → 100644
View file @
ba4bbfd2
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: voter_status
--
-- description: 3 input majority voter with error status output
--
--------------------------------------------------------------------------------
-- Copyright CERN 2022
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
entity
voter_status
is
port
(
inp
:
in
std_logic_vector
(
1
to
3
);
res
:
out
std_logic
;
err
:
out
std_logic
);
end
voter_status
;
architecture
behav
of
voter_status
is
begin
res
<=
(
inp
(
1
)
and
inp
(
2
))
or
(
inp
(
1
)
and
inp
(
3
))
or
(
inp
(
2
)
and
inp
(
3
));
err
<=
(
not
(
inp
(
1
)
and
inp
(
2
)
and
inp
(
3
)))
and
(
not
(
not
inp
(
1
)
and
not
inp
(
2
)
and
not
inp
(
3
)));
end
behav
;
\ No newline at end of file
modules/radtol/voter_vec_status.vhd
0 → 100644
View file @
ba4bbfd2
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: voter_vec_status
--
-- description: 3 input majority voter with error status output for a vector
-- NOTE: in case of error, the result may be different from all the inputs
-- (if two errors appear)
--
--------------------------------------------------------------------------------
-- Copyright CERN 2022
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
entity
voter_vec_status
is
generic
(
g_WIDTH
:
natural
);
port
(
a
,
b
,
c
:
in
std_logic_vector
(
g_WIDTH
-
1
downto
0
);
res
:
out
std_logic_vector
(
g_WIDTH
-
1
downto
0
);
err
:
out
std_logic
);
end
voter_vec_status
;
architecture
behav
of
voter_vec_status
is
signal
b_err
:
std_logic_vector
(
g_WIDTH
-
1
downto
0
);
begin
gen_bit
:
for
i
in
res
'range
generate
inst_voter
:
entity
work
.
voter_status
port
map
(
inp
(
1
)
=>
a
(
i
),
inp
(
2
)
=>
b
(
i
),
inp
(
3
)
=>
c
(
i
),
res
=>
res
(
i
),
err
=>
b_err
(
i
)
);
end
generate
;
err
<=
'1'
when
b_err
/=
(
b_err
'range
=>
'0'
)
else
'0'
;
end
behav
;
\ No newline at end of file
modules/wishbone/wb_axi4lite_bridge/xwb_axi4lite_bridge.vhd
View file @
ba4bbfd2
...
...
@@ -109,7 +109,7 @@ begin
if
(
wb_master_i
.
stall
=
'0'
)
then
wb_master_o
.
stb
<=
'0'
;
if
(
wb_master_i
.
ack
=
'1'
)
then
state
<=
IDLE
;
state
<=
RESPONSE_READ
;
axi4_slave_o
.
RRESP
<=
c_AXI4_RESP_OKAY
;
axi4_slave_o
.
RDATA
<=
wb_master_i
.
dat
;
axi4_slave_o
.
RVALID
<=
'1'
;
...
...
modules/wishbone/wb_fine_pulse_gen/Manifest.py
View file @
ba4bbfd2
files
=
[
"fine_pulse_gen_kintex7_shared.vhd"
,
"fine_pulse_gen_kintexultrascale_shared.vhd"
,
"fine_pulse_gen_kintex7.vhd"
,
"fine_pulse_gen_kintexultrascale.vhd"
,
"fine_pulse_gen_wbgen2_pkg.vhd"
,
"fine_pulse_gen_wb.vhd"
,
"xwb_fine_pulse_gen.vhd"
]
import
logging
if
target
==
"xilinx"
:
files
=
[
"fine_pulse_gen_kintex7_shared.vhd"
,
"fine_pulse_gen_kintexultrascale_shared.vhd"
,
"fine_pulse_gen_kintex7.vhd"
,
"fine_pulse_gen_kintexultrascale.vhd"
,
"fine_pulse_gen_wbgen2_pkg.vhd"
,
"fine_pulse_gen_wb.vhd"
,
"xwb_fine_pulse_gen.vhd"
]
else
:
logging
.
info
(
"Library component wb_fine_pulse_gen targets only xilinx devices"
)
modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale_shared.vhd
View file @
ba4bbfd2
...
...
@@ -165,7 +165,7 @@ begin
port
map
(
RDY
=>
odelayctrl_rdy_o
,
REFCLK
=>
clk_odelay
,
RST
=>
odelayctrl_rst_i
RST
=>
rst_synced
);
end
block
;
end
generate
gen_use_odelay
;
...
...
modules/wishbone/wb_register/Manifest.py
View file @
ba4bbfd2
...
...
@@ -2,4 +2,5 @@ files = [
"xwb_register_link.vhd"
,
"wb_skidpad.vhd"
,
"xwb_register.vhd"
,
"wb_skidpad2.vhd"
,
]
modules/wishbone/wb_register/wb_skidpad2.vhd
0 → 100644
View file @
ba4bbfd2
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: xwb_skidpad2
--
-- Add registers in a wishbone flow to help timing closure while maintaining
-- full throughput. WB PIPELINE ONLY.
--
-- Differences with other modules in this directory:
-- * wb_skidpad: wishbone interface, any data width
-- * xwb_register: any data/addr width, full throughput, pipeline only.
-- * xwb_register_link: any data/addr width, pipeline only.
-- Also, note that CYC is not handled (either connect to 1, to stb or to your
-- own logic).
--
--------------------------------------------------------------------------------
-- Copyright CERN 2014-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
ieee
.
numeric_std
.
all
;
entity
wb_skidpad2
is
generic
(
-- Number of bits in adr.
g_adrbits
:
natural
:
=
32
;
-- Number of bits in dat.
g_datbits
:
natural
:
=
32
);
port
(
clk_i
:
std_logic
;
rst_n_i
:
std_logic
;
-- The slave port (note: no dat_o, no ack).
stb_i
:
in
std_logic
;
adr_i
:
in
std_logic_vector
(
g_adrbits
-1
downto
0
);
dat_i
:
in
std_logic_vector
(
g_datbits
-1
downto
0
);
sel_i
:
in
std_logic_vector
((
g_datbits
/
8
)
-1
downto
0
);
we_i
:
in
std_logic
;
stall_o
:
out
std_logic
;
-- The master port (note: no dat_i, no ack).
stb_o
:
out
std_logic
;
adr_o
:
out
std_logic_vector
(
g_adrbits
-1
downto
0
);
dat_o
:
out
std_logic_vector
(
g_datbits
-1
downto
0
);
sel_o
:
out
std_logic_vector
((
g_datbits
/
8
)
-1
downto
0
);
we_o
:
out
std_logic
;
stall_i
:
in
std_logic
);
end
wb_skidpad2
;
architecture
rtl
of
wb_skidpad2
is
signal
r_full0
,
r_full1
:
std_logic
:
=
'0'
;
signal
fill0
,
fill1
:
std_logic
;
signal
stall
:
std_logic
;
signal
r_adr0
,
r_adr1
:
std_logic_vector
(
g_adrbits
-
1
downto
0
);
signal
r_dat0
,
r_dat1
:
std_logic_vector
(
g_datbits
-
1
downto
0
);
signal
r_sel0
,
r_sel1
:
std_logic_vector
((
g_datbits
/
8
)
-
1
downto
0
);
signal
r_we0
,
r_we1
:
std_logic
;
begin
-- A tfr is possible if one of the position is full.
stb_o
<=
r_full1
or
r_full0
;
-- The skidpad is full if both positions are full. Do not check for stall_i as it will create
-- a combinational path.
stall
<=
r_full1
and
r_full0
;
stall_o
<=
stall
;
-- Write into position 0 iff: input valid skidpad not stalling.
fill0
<=
stb_i
and
not
stall
;
-- Move from position 0 to 1 when possible:
-- Position 0 is valid, and position 1 is empty and not read or full and read.
fill1
<=
r_full0
and
(
r_full1
xor
stall_i
);
control
:
process
(
clk_i
,
rst_n_i
)
is
begin
if
rst_n_i
=
'0'
then
r_full0
<=
'0'
;
r_full1
<=
'0'
;
elsif
rising_edge
(
clk_i
)
then
r_full0
<=
fill0
or
(
r_full1
and
stall_i
);
r_full1
<=
fill1
or
(
r_full1
and
stall_i
);
end
if
;
end
process
;
bulk
:
process
(
clk_i
)
is
begin
if
rising_edge
(
clk_i
)
then
if
fill0
=
'1'
then
r_dat0
<=
dat_i
;
r_adr0
<=
adr_i
;
r_sel0
<=
sel_i
;
r_we0
<=
we_i
;
end
if
;
if
fill1
=
'1'
then
r_dat1
<=
r_dat0
;
r_adr1
<=
r_adr0
;
r_sel1
<=
r_sel0
;
r_we1
<=
r_we0
;
end
if
;
end
if
;
end
process
;
adr_o
<=
r_adr1
when
r_full1
=
'1'
else
r_adr0
;
dat_o
<=
r_dat1
when
r_full1
=
'1'
else
r_dat0
;
sel_o
<=
r_sel1
when
r_full1
=
'1'
else
r_sel0
;
we_o
<=
r_we1
when
r_full1
=
'1'
else
r_we0
;
end
rtl
;
modules/wishbone/wb_simple_timer/wb_tics.vhd
View file @
ba4bbfd2
...
...
@@ -79,7 +79,7 @@ architecture behaviour of wb_tics is
signal
cntr_overflow
:
std_logic
;
begin
process
(
clk_sys_i
)
begin
if
rising_edge
(
clk_sys_i
)
then
...
...
@@ -112,7 +112,7 @@ begin
--Wishbone interface
wb_dat_o
<=
std_logic_vector
(
cntr_tics
);
wb_ack_o
<=
'1'
;
wb_ack_o
<=
wb_stb_i
and
wb_cyc_i
;
wb_stall_o
<=
'0'
;
--process(clk_sys_i)
...
...
modules/wishbone/wb_spi/spi_wb.cheby
0 → 100644
View file @
ba4bbfd2
memory-map:
name: spi
description: Wishbone SPI
bus: wb-32-be
x-hdl:
busgroup: True
x-wbgen:
hdl_entity: spi_wishbone_slave
schema-version:
core: 2.0.0
x-conversions: 1.0.0
x-driver-edge: 1.0.0
x-enums: 1.0.0
x-fesa: 2.0.0
x-gena: 2.0.0
x-hdl: 1.0.0
x-map-info: 1.0.0
x-wbgen: 1.0.0
children:
- reg:
name: tx_rx_0
description: TX/RX 0
comment:
width: 32
access: rw
address: 0x0
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_WRITE
field_description: Tx/Rx word 0
load: LOAD_EXT
type: SLV
x-hdl:
write-strobe: True
- reg:
name: tx_rx_1
description: TX/RX 1
comment:
width: 32
access: rw
address: 0x4
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_WRITE
field_description: Tx/Rx word 1
load: LOAD_EXT
type: SLV
x-hdl:
write-strobe: True
- reg:
name: tx_rx_2
description: TX/RX 2
comment:
width: 32
access: rw
address: 0x8
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_WRITE
field_description: Tx/Rx word 2
load: LOAD_EXT
type: SLV
x-hdl:
write-strobe: True
- reg:
name: tx_rx_3
description: TX/RX 3
comment:
width: 32
access: rw
address: 0xc
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_WRITE
field_description: Tx/Rx word 3
load: LOAD_EXT
type: SLV
x-hdl:
write-strobe: True
- reg:
name: ctrl
description: Control register
width: 32
access: rw
address: 0x10
children:
- field:
name: len
description: Length of SPI transfer
range: 6-0
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
type: SLV
- field:
name: go
description: Start SPI transfer
range: 8
x-wbgen:
access_bus: WRITE_ONLY
access_dev: READ_ONLY
size: 1
type: MONOSTABLE
- field:
name: rx_negedge
description: RX negedge
comment: 'write 1: data from Slave received on falling SCLK edge \n write 0: data from Slave received on rising SCLK edge'
range: 9
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
size: 1
type: BIT
- field:
name: tx_negedge
description: TX negedge
comment: 'write 1: data transmitted on falling SCLK edge \n write 0: data transmitted on rising SCLK edge'
range: 10
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
size: 1
type: BIT
- field:
name: lsb
description: LSB first
comment: 'write 1: LSB first on the line \n write 0: MSB first on the line'
range: 11
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
size: 1
type: BIT
- field:
name: irq
description: Interrupt enable
comment: 'write 1: IRQ enabled \n write 0: IRQ disabled'
range: 12
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
size: 1
type: BIT
- field:
name: ass
description: Automatic Slave select
range: 13
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
size: 1
type: BIT
- reg:
name: divider
description: Divider
comment:
width: 32
access: rw
address: 0x14
children:
- field:
name: value
description: Divide factor
range: 15-0
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
field_description: Divide factor
type: SLV
- reg:
name: ss
description: Select SPI slave
comment:
width: 32
access: rw
address: 0x18
x-hdl:
write-strobe: True
children:
- field:
name: value
description: Select slave
range: 0
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_WRITE
field_description: Select slave
load: LOAD_EXT
size: 1
type: SLV
modules/wishbone/wb_xc7_fw_update/Manifest.py
View file @
ba4bbfd2
files
=
[
"wb_xc7_fw_update_regs.vhd"
,
"xwb_xc7_fw_update.vhd"
,
]
import
logging
if
target
==
"xilinx"
:
files
=
[
"wb_xc7_fw_update_regs.vhd"
,
"xwb_xc7_fw_update.vhd"
,
"xwb_xc7_fw_update_v2.vhd"
,
]
else
:
logging
.
info
(
"Library component wb_xc7_fw_update targets only xilinx devices"
)
modules/wishbone/wb_xc7_fw_update/xwb_xc7_fw_update.vhd
View file @
ba4bbfd2
-------------------------------------------------------------------------------
-- Title : XC7 firmware update
-- Project : General Cores
-------------------------------------------------------------------------------
-- Note: The spi clock is directly connected to the STARTUPE2 module, so it
-- doesn't appear as an output.
-------------------------------------------------------------------------------
-- Copyright (c) 2020-2021 CERN
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License") (which enables you, at your option,
-- to treat this file as licensed under the Apache License 2.0); you may not
-- use this file except in compliance with the License. You may obtain a copy
-- of the License at http://solderpad.org/licenses/SHL-0.51.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
-------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
...
...
@@ -21,71 +42,18 @@ entity xwb_xc7_fw_update is
end
xwb_xc7_fw_update
;
architecture
rtl
of
xwb_xc7_fw_update
is
signal
far_data_in
:
std_logic_vector
(
7
downto
0
);
signal
far_data_out
:
std_logic_vector
(
7
downto
0
);
signal
far_xfer_out
:
std_logic
;
signal
far_ready_in
:
std_logic
;
signal
far_cs_out
:
std_logic
;
signal
far_wr_out
:
std_logic
;
signal
flash_spi_cs
:
std_logic
;
signal
flash_spi_start
:
std_logic
;
signal
flash_spi_wdata
:
std_logic_vector
(
7
downto
0
);
signal
flash_sclk
:
std_logic
;
begin
i
nst_regs
:
entity
work
.
wb_xc7_fw_update_regs
i
_inst
:
entity
work
.
xwb_xc7_fw_update_v2
port
map
(
clk_i
=>
clk_i
,
clk_i
=>
clk_i
,
rst_n_i
=>
rst_n_i
,
wb_i
=>
wb_i
,
wb_o
=>
wb_o
,
far_data_i
=>
far_data_in
,
far_data_o
=>
far_data_out
,
far_xfer_i
=>
'0'
,
far_xfer_o
=>
far_xfer_out
,
far_ready_i
=>
far_ready_in
,
far_ready_o
=>
open
,
far_cs_i
=>
'0'
,
far_cs_o
=>
far_cs_out
,
far_wr_o
=>
far_wr_out
);
-- Need to capture cs and data_out, and need to delay start.
p_host_spi_registers
:
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_n_i
=
'0'
then
flash_spi_start
<=
'0'
;
flash_spi_wdata
<=
(
others
=>
'0'
);
flash_spi_cs
<=
'0'
;
elsif
far_wr_out
=
'1'
then
flash_spi_wdata
<=
far_data_out
;
flash_spi_start
<=
far_xfer_out
;
flash_spi_cs
<=
far_cs_out
;
else
-- Pulse for start.
flash_spi_start
<=
'0'
;
end
if
;
end
if
;
end
process
;
U_SPI_Master
:
entity
work
.
gc_simple_spi_master
generic
map
(
g_div_ratio_log2
=>
0
,
g_num_data_bits
=>
8
)
port
map
(
clk_sys_i
=>
clk_i
,
rst_n_i
=>
rst_n_i
,
cs_i
=>
flash_spi_cs
,
start_i
=>
flash_spi_start
,
cpol_i
=>
'0'
,
data_i
=>
flash_spi_wdata
,
ready_o
=>
far_ready_in
,
data_o
=>
far_data_in
,
spi_cs_n_o
=>
flash_cs_n_o
,
spi_sclk_o
=>
flash_sclk
,
spi_mosi_o
=>
flash_mosi_o
,
spi_miso_i
=>
flash_miso_i
);
wb_i
=>
wb_i
,
wb_o
=>
wb_o
,
flash_cs_n_o
=>
flash_cs_n_o
,
flash_mosi_o
=>
flash_mosi_o
,
flash_miso_i
=>
flash_miso_i
,
flash_sck_o
=>
flash_sclk
);
STARTUPE2_inst
:
STARTUPE2
generic
map
(
...
...
modules/wishbone/wb_xc7_fw_update/xwb_xc7_fw_update_v2.vhd
0 → 100644
View file @
ba4bbfd2
-------------------------------------------------------------------------------
-- Title : XC7 firmware update
-- Project : General Cores
-------------------------------------------------------------------------------
-- Note: Contrary to V1, this version doesn't include the STARTUPE2 module
-- so the spi clock port is added.
-------------------------------------------------------------------------------
-- Copyright (c) 2020-2021 CERN
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License") (which enables you, at your option,
-- to treat this file as licensed under the Apache License 2.0); you may not
-- use this file except in compliance with the License. You may obtain a copy
-- of the License at http://solderpad.org/licenses/SHL-0.51.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
-------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
work
.
wishbone_pkg
.
all
;
entity
xwb_xc7_fw_update_v2
is
port
(
clk_i
:
in
std_logic
;
rst_n_i
:
in
std_logic
;
wb_i
:
in
t_wishbone_slave_in
;
wb_o
:
out
t_wishbone_slave_out
;
flash_cs_n_o
:
out
std_logic
;
flash_mosi_o
:
out
std_logic
;
flash_miso_i
:
in
std_logic
;
flash_sck_o
:
out
std_logic
);
end
xwb_xc7_fw_update_v2
;
architecture
rtl
of
xwb_xc7_fw_update_v2
is
signal
far_data_in
:
std_logic_vector
(
7
downto
0
);
signal
far_data_out
:
std_logic_vector
(
7
downto
0
);
signal
far_xfer_out
:
std_logic
;
signal
far_ready_in
:
std_logic
;
signal
far_cs_out
:
std_logic
;
signal
far_wr_out
:
std_logic
;
signal
flash_spi_cs
:
std_logic
;
signal
flash_spi_start
:
std_logic
;
signal
flash_spi_wdata
:
std_logic_vector
(
7
downto
0
);
signal
flash_sclk
:
std_logic
;
begin
inst_regs
:
entity
work
.
wb_xc7_fw_update_regs
port
map
(
clk_i
=>
clk_i
,
rst_n_i
=>
rst_n_i
,
wb_i
=>
wb_i
,
wb_o
=>
wb_o
,
far_data_i
=>
far_data_in
,
far_data_o
=>
far_data_out
,
far_xfer_i
=>
'0'
,
far_xfer_o
=>
far_xfer_out
,
far_ready_i
=>
far_ready_in
,
far_ready_o
=>
open
,
far_cs_i
=>
'0'
,
far_cs_o
=>
far_cs_out
,
far_wr_o
=>
far_wr_out
);
-- Need to capture cs and data_out, and need to delay start.
p_host_spi_registers
:
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_n_i
=
'0'
then
flash_spi_start
<=
'0'
;
flash_spi_wdata
<=
(
others
=>
'0'
);
flash_spi_cs
<=
'0'
;
elsif
far_wr_out
=
'1'
then
flash_spi_wdata
<=
far_data_out
;
flash_spi_start
<=
far_xfer_out
;
flash_spi_cs
<=
far_cs_out
;
else
-- Pulse for start.
flash_spi_start
<=
'0'
;
end
if
;
end
if
;
end
process
;
U_SPI_Master
:
entity
work
.
gc_simple_spi_master
generic
map
(
g_div_ratio_log2
=>
0
,
g_num_data_bits
=>
8
)
port
map
(
clk_sys_i
=>
clk_i
,
rst_n_i
=>
rst_n_i
,
cs_i
=>
flash_spi_cs
,
start_i
=>
flash_spi_start
,
cpol_i
=>
'0'
,
data_i
=>
flash_spi_wdata
,
ready_o
=>
far_ready_in
,
data_o
=>
far_data_in
,
spi_cs_n_o
=>
flash_cs_n_o
,
spi_sclk_o
=>
flash_sclk
,
spi_mosi_o
=>
flash_mosi_o
,
spi_miso_i
=>
flash_miso_i
);
flash_sck_o
<=
flash_sclk
;
end
rtl
;
platform/altera/wb_pcie/pcie_wb.vhd
View file @
ba4bbfd2
...
...
@@ -14,19 +14,19 @@ entity pcie_wb is
port
(
clk125_i
:
in
std_logic
;
-- 125 MHz, free running
cal_clk50_i
:
in
std_logic
;
-- 50 MHz, shared between all PHYs
-- Physical PCIe pins
pcie_refclk_i
:
in
std_logic
;
-- 100 MHz, must not derive clk125_i or cal_clk50_i
pcie_rstn_i
:
in
std_logic
;
-- Asynchronous "clear sticky" PCIe pin
pcie_rx_i
:
in
std_logic_vector
(
3
downto
0
);
pcie_tx_o
:
out
std_logic_vector
(
3
downto
0
);
-- Commands from PC to FPGA
master_clk_i
:
in
std_logic
;
master_rstn_i
:
in
std_logic
;
master_o
:
out
t_wishbone_master_out
;
master_i
:
in
t_wishbone_master_in
;
-- Command to PC from FPGA
slave_clk_i
:
in
std_logic
:
=
'0'
;
slave_rstn_i
:
in
std_logic
:
=
'1'
;
...
...
@@ -35,30 +35,30 @@ entity pcie_wb is
end
pcie_wb
;
architecture
rtl
of
pcie_wb
is
signal
internal_wb_clk
,
internal_wb_rstn
,
stall
:
std_logic
;
signal
internal_wb_clk
,
internal_wb_rstn
,
stall
:
std_logic
;
signal
internal_wb_rstn_sync
:
std_logic_vector
(
3
downto
0
)
:
=
(
others
=>
'0'
);
signal
rx_wb64_stb
,
rx_wb64_stall
:
std_logic
;
signal
rx_wb32_stb
,
rx_wb32_stall
:
std_logic
;
signal
rx_wb64_dat
:
std_logic_vector
(
63
downto
0
);
signal
rx_wb32_dat
:
std_logic_vector
(
31
downto
0
);
signal
rx_bar
:
std_logic_vector
(
2
downto
0
);
signal
tx_rdy
,
tx_eop
:
std_logic
;
signal
tx64_alloc
,
tx_wb64_stb
:
std_logic
;
signal
tx32_alloc
,
tx_wb32_stb
:
std_logic
;
signal
tx_wb64_dat
:
std_logic_vector
(
63
downto
0
);
signal
tx_wb32_dat
:
std_logic_vector
(
31
downto
0
);
signal
tx_alloc_mask
:
std_logic
:
=
'1'
;
-- Only pass every even tx32_alloc to tx64_alloc.
signal
wb_stb
,
wb_ack
,
wb_stall
:
std_logic
;
signal
wb_adr
:
std_logic_vector
(
63
downto
0
);
signal
wb_bar
:
std_logic_vector
(
2
downto
0
);
signal
wb_dat
:
std_logic_vector
(
31
downto
0
);
signal
cfg_busdev
:
std_logic_vector
(
12
downto
0
);
-- Internal WB clock, PC->FPGA
signal
int_slave_i
:
t_wishbone_slave_in
;
signal
int_slave_o
:
t_wishbone_slave_out
;
...
...
@@ -66,25 +66,25 @@ architecture rtl of pcie_wb is
signal
int_master_o
:
t_wishbone_master_out
;
signal
int_master_i
:
t_wishbone_master_in
;
signal
ext_slave_o
:
t_wishbone_slave_out
;
-- control registers
signal
r_cyc
:
std_logic
;
signal
r_int
:
std_logic
:
=
'0'
;
-- interrupt mask, starts=0
signal
r_addr
:
std_logic_vector
(
31
downto
16
);
signal
r_error
:
std_logic_vector
(
63
downto
0
);
-- interrupt signals
signal
fifo_full
,
r_fifo_full
,
app_int_sts
,
app_msi_req
:
std_logic
;
begin
pcie_phy
:
pcie_altera
pcie_phy
:
pcie_altera
generic
map
(
g_family
=>
g_family
)
port
map
(
clk125_i
=>
clk125_i
,
cal_clk50_i
=>
cal_clk50_i
,
async_rstn
=>
master_rstn_i
and
slave_rstn_i
,
pcie_refclk_i
=>
pcie_refclk_i
,
pcie_rstn_i
=>
pcie_rstn_i
,
pcie_rx_i
=>
pcie_rx_i
,
...
...
@@ -96,19 +96,19 @@ begin
wb_clk_o
=>
internal_wb_clk
,
wb_rstn_i
=>
internal_wb_rstn
,
rx_wb_stb_o
=>
rx_wb64_stb
,
rx_wb_dat_o
=>
rx_wb64_dat
,
rx_wb_stall_i
=>
rx_wb64_stall
,
rx_bar_o
=>
rx_bar
,
tx_rdy_o
=>
tx_rdy
,
tx_alloc_i
=>
tx64_alloc
,
tx_wb_stb_i
=>
tx_wb64_stb
,
tx_wb_dat_i
=>
tx_wb64_dat
,
tx_eop_i
=>
tx_eop
);
pcie_rx
:
pcie_64to32
port
map
(
clk_i
=>
internal_wb_clk
,
rstn_i
=>
internal_wb_rstn
,
...
...
@@ -118,7 +118,7 @@ begin
slave32_stb_o
=>
rx_wb32_stb
,
slave32_dat_o
=>
rx_wb32_dat
,
slave32_stall_i
=>
rx_wb32_stall
);
pcie_tx
:
pcie_32to64
port
map
(
clk_i
=>
internal_wb_clk
,
rstn_i
=>
internal_wb_rstn
,
...
...
@@ -128,24 +128,24 @@ begin
slave64_stb_o
=>
tx_wb64_stb
,
slave64_dat_o
=>
tx_wb64_dat
,
slave64_stall_i
=>
'0'
);
pcie_logic
:
pcie_tlp
port
map
(
clk_i
=>
internal_wb_clk
,
rstn_i
=>
internal_wb_rstn
,
rx_wb_stb_i
=>
rx_wb32_stb
,
rx_wb_dat_i
=>
rx_wb32_dat
,
rx_wb_stall_o
=>
rx_wb32_stall
,
rx_bar_i
=>
rx_bar
,
tx_rdy_i
=>
tx_rdy
,
tx_alloc_o
=>
tx32_alloc
,
tx_wb_stb_o
=>
tx_wb32_stb
,
tx_wb_dat_o
=>
tx_wb32_dat
,
tx_eop_o
=>
tx_eop
,
cfg_busdev_i
=>
cfg_busdev
,
wb_stb_o
=>
wb_stb
,
wb_adr_o
=>
wb_adr
,
wb_bar_o
=>
wb_bar
,
...
...
@@ -157,14 +157,14 @@ begin
wb_err_i
=>
int_slave_o
.
err
,
wb_rty_i
=>
int_slave_o
.
rty
,
wb_dat_i
=>
wb_dat
);
internal_wb_rstn
<=
internal_wb_rstn_sync
(
0
);
tx64_alloc
<=
tx32_alloc
and
tx_alloc_mask
;
alloc
:
process
(
internal_wb_clk
)
begin
if
rising_edge
(
internal_wb_clk
)
then
internal_wb_rstn_sync
<=
(
master_rstn_i
and
slave_rstn_i
)
&
internal_wb_rstn_sync
(
internal_wb_rstn_sync
'length
-1
downto
1
);
if
internal_wb_rstn
=
'0'
then
tx_alloc_mask
<=
'1'
;
else
...
...
@@ -172,43 +172,43 @@ begin
end
if
;
end
if
;
end
process
;
PC_to_FPGA_clock_crossing
:
xwb_clock_crossing
PC_to_FPGA_clock_crossing
:
xwb_clock_crossing
generic
map
(
g_size
=>
32
)
port
map
(
slave_clk_i
=>
internal_wb_clk
,
slave_rst_n_i
=>
internal_wb_rstn
,
slave_i
=>
int_slave_i
,
slave_o
=>
int_slave_o
,
master_clk_i
=>
master_clk_i
,
master_clk_i
=>
master_clk_i
,
master_rst_n_i
=>
master_rstn_i
,
master_i
=>
master_i
,
master_o
=>
master_o
);
int_slave_i
.
stb
<=
wb_stb
when
wb_bar
=
"001"
else
'0'
;
wb_stall
<=
int_slave_o
.
stall
when
wb_bar
=
"001"
else
'0'
;
int_slave_i
.
cyc
<=
r_cyc
;
int_slave_i
.
adr
(
r_addr
'range
)
<=
r_addr
;
int_slave_i
.
adr
(
r_addr
'right
-1
downto
0
)
<=
wb_adr
(
r_addr
'right
-1
downto
0
);
FPGA_to_PC_clock_crossing
:
xwb_clock_crossing
generic
map
(
g_size
=>
32
)
port
map
(
slave_clk_i
=>
slave_clk_i
,
slave_rst_n_i
=>
slave_rstn_i
,
slave_i
=>
slave_i
,
slave_o
=>
ext_slave_o
,
master_clk_i
=>
internal_wb_clk
,
master_clk_i
=>
internal_wb_clk
,
master_rst_n_i
=>
internal_wb_rstn
,
master_i
=>
int_master_i
,
master_o
=>
int_master_o
);
-- Do not wait for software acknowledgement
fask_ack
:
if
g_fast_ack
generate
slave_o
.
stall
<=
ext_slave_o
.
stall
;
slave_o
.
rty
<=
'0'
;
slave_o
.
err
<=
'0'
;
slave_o
.
dat
<=
(
others
=>
'0'
);
fast_ack
:
process
(
slave_clk_i
)
begin
if
rising_edge
(
slave_clk_i
)
then
...
...
@@ -216,7 +216,7 @@ begin
end
if
;
end
process
;
end
generate
;
-- Uses ack/err and dat from software
slow_ack
:
if
not
g_fast_ack
generate
slave_o
<=
ext_slave_o
;
...
...
@@ -226,26 +226,26 @@ begin
fifo_full
<=
int_master_o
.
cyc
and
int_master_o
.
stb
;
app_int_sts
<=
fifo_full
and
r_int
;
-- Classic interrupt until FIFO drained
app_msi_req
<=
fifo_full
and
not
r_fifo_full
;
-- Edge-triggered MSI
int_master_i
.
rty
<=
'0'
;
control
:
process
(
internal_wb_clk
)
begin
if
rising_edge
(
internal_wb_clk
)
then
r_fifo_full
<=
fifo_full
;
-- Shift in the error register
if
int_slave_o
.
ack
=
'1'
or
int_slave_o
.
err
=
'1'
or
int_slave_o
.
rty
=
'1'
then
r_error
<=
r_error
(
r_error
'length
-2
downto
0
)
&
(
int_slave_o
.
err
or
int_slave_o
.
rty
);
end
if
;
if
wb_bar
=
"001"
then
wb_ack
<=
int_slave_o
.
ack
;
wb_dat
<=
int_slave_o
.
dat
;
else
-- The control BAR is targetted
-- Feedback acks one cycle after strobe
wb_ack
<=
wb_stb
;
-- Always output read result (even w/o stb or we)
case
wb_adr
(
6
downto
2
)
is
when
"00000"
=>
-- Control register high
...
...
@@ -274,12 +274,12 @@ begin
when
others
=>
wb_dat
<=
(
others
=>
'0'
);
end
case
;
-- Unless requested to by the PC, don't deque the FPGA->PC FIFO
int_master_i
.
stall
<=
'1'
;
int_master_i
.
ack
<=
'0'
;
int_master_i
.
err
<=
'0'
;
-- Is this a write to the register space?
if
wb_stb
=
'1'
and
int_slave_i
.
we
=
'1'
then
case
wb_adr
(
6
downto
2
)
is
...
...
@@ -306,6 +306,7 @@ begin
when
"01"
=>
int_master_i
.
stall
<=
'0'
;
when
"10"
=>
int_master_i
.
ack
<=
'1'
;
when
"11"
=>
int_master_i
.
err
<=
'1'
;
when
others
=>
null
;
end
case
;
end
if
;
when
"10101"
=>
-- Master FIFO data low
...
...
@@ -316,5 +317,5 @@ begin
end
if
;
end
if
;
end
process
;
end
rtl
;
sim/if_wb_master.svh
View file @
ba4bbfd2
...
...
@@ -72,8 +72,8 @@ interface IWishboneMaster
WAIT_ACK
}
xf_state
;
wb_cycle_t
request_queue
[$]
;
wb_cycle_t
result_queue
[$]
;
mailbox
#(
wb_cycle_t
)
request_queue
;
mailbox
#(
wb_cycle_t
)
result_queue
;
struct
{
int
gen_random_throttling
;
...
...
@@ -152,7 +152,7 @@ interface IWishboneMaster
dat_o
<=
gen_data
(
c
.
data
[
i
])
;
@
(
posedge
clk_i
)
;
while
(
ack
!=
1'b1
&&
err
!=
1'b1
&&
rty
==
1'b
1
)
@
(
posedge
clk_i
)
;
while
(
ack
!=
1'b1
&&
err
!=
1'b1
&&
rty
==
1'b
0
)
@
(
posedge
clk_i
)
;
if
(
err
||
rty
)
begin
c
.
result
=
(
err
?
R_ERROR
:
R_RETRY
)
;
...
...
@@ -283,35 +283,29 @@ class CIWBMasterAccessor extends CWishboneAccessor;
endfunction
// poll
task
get
(
ref
wb_cycle_t
xfer
)
;
while
(
!
result_queue
.
size
())
@
(
posedge
clk_i
)
;
xfer
=
result_queue
.
pop_front
()
;
result_queue
.
get
(
xfer
)
;
endtask
// get
task
put
(
ref
wb_cycle_t
xfer
)
;
request_queue
.
pu
sh_back
(
xfer
)
;
request_queue
.
pu
t
(
xfer
)
;
endtask
// put
function
int
idle
()
;
return
(
request_queue
.
size
()
==
0
)
&&
(
xf_state
==
IDLE
)
;
return
(
request_queue
.
num
()
==
0
)
&&
(
xf_state
==
IDLE
)
;
endfunction
// idle
endclass
// CIWBMasterAccessor
CIWBMasterAccessor
theAccessor
;
initial
theAccessor
=
new
;
function
automatic
CIWBMasterAccessor
get_accessor
()
;
return
theAccessor
;
endfunction
// get_accessor
always
@
(
posedge
clk_i
)
if
(
!
rst_n_i
)
begin
request_queue
=
{}
;
result_queue
=
{}
;
request_queue
=
new
()
;
result_queue
=
new
()
;
xf_state
=
IDLE
;
cyc
<=
0
;
dat_o
<=
0
;
...
...
@@ -322,30 +316,38 @@ endclass // CIWBMasterAccessor
end
initial
begin
theAccessor
=
new
;
request_queue
=
new
()
;
result_queue
=
new
()
;
settings
.
gen_random_throttling
=
0
;
settings
.
throttle_prob
=
0.1
;
settings
.
addr_gran
=
WORD
;
end
initial
forever
begin
@
(
posedge
clk_i
)
;
if
(
request_queue
.
size
()
>
0
)
begin
forever
begin
wb_cycle_t
c
;
c
=
request_queue
.
pop_front
(
)
;
@
(
posedge
clk_i
)
;
case
(
c
.
ctype
)
PIPELINED:
pipelined_cycle
(
c
)
;
CLASSIC:
classic_cycle
(
c
)
;
endcase
if
(
request_queue
.
try_get
(
c
))
begin
result_queue
.
push_back
(
c
)
;
end
case
(
c
.
ctype
)
PIPELINED:
pipelined_cycle
(
c
)
;
CLASSIC:
classic_cycle
(
c
)
;
endcase
// Notify any waiting thread that the transfer is complete
->
c
.
done
;
result_queue
.
put
(
c
)
;
end
// if (request_queue.try_get(c))
end
// forever begin
end
end
// initial begin
endinterface
// IWishboneMaster
sim/if_wishbone_accessor.svh
View file @
ba4bbfd2
...
...
@@ -9,16 +9,12 @@ virtual class CWishboneAccessor extends CBusAccessor;
protected
wb_cycle_type_t
m_cycle_type
;
function
new
()
;
$
display
(
"NEW"
)
;
m_cycle_type
=
CLASSIC
;
m_default_xfer_size
=
4
;
endfunction
// new
virtual
task
automatic
set_mode
(
wb_cycle_type_t
mode
)
;
m_cycle_type
=
mode
;
$
display
(
"SET MODE %d"
,
mode
)
;
endtask
// set_mode
...
...
@@ -70,8 +66,11 @@ virtual class CWishboneAccessor extends CBusAccessor;
end
// $display("DS: %d", cycle.data.size());
put
(
cycle
)
;
// wait for the transfer completion notification to avoid getting the result of the wrong transfer
// in case multiple threads are calling readm()/writem() in parallel.
@
cycle
.
done
;
get
(
cycle
)
;
result
=
cycle
.
result
;
...
...
@@ -83,7 +82,6 @@ virtual class CWishboneAccessor extends CBusAccessor;
int
i
;
cycle
.
ctype
=
m_cycle_type
;
$
display
(
"CYCLE CTYPE %d %d"
,
cycle
.
ctype
,
m_cycle_type
)
;
cycle
.
rw
=
1'b0
;
...
...
@@ -96,6 +94,9 @@ virtual class CWishboneAccessor extends CBusAccessor;
end
put
(
cycle
)
;
// wait for the transfer completion notification to avoid getting the result of the wrong transfer
// in case multiple threads are calling readm()/writem() in parallel.
@
cycle
.
done
;
get
(
cycle
)
;
for
(
i
=
0
;
i
<
addr
.
size
()
;
i
++
)
...
...
sim/if_wishbone_types.svh
View file @
ba4bbfd2
...
...
@@ -42,6 +42,7 @@ typedef struct {
wb_cycle_type_t
ctype
;
wb_xfer_t
data
[$]
;
wb_cycle_result_t
result
;
event
done
;
}
wb_cycle_t
;
typedef
enum
...
...
sim/simdrv_wb_spi.svh
0 → 100644
View file @
ba4bbfd2
//------------------------------------------------------------------------------
// CERN BE-CEM-EDL
// General Cores Library
// https://www.ohwr.org/projects/general-cores
//------------------------------------------------------------------------------
//
// unit name: CSimDrv_WB_SPI
//
// author: Grzegorz Daniluk
//
// description: SV wb_spi master driver for testbenches
//
//------------------------------------------------------------------------------
// Copyright CERN 2021
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------
`ifndef
__
SIMDRV_WB_SPI_SVH
`define
__SIMDRV_WB_SPI_SVH 1
`define
SPI_REG_RX0 0
`define
SPI_REG_TX0 0
`define
SPI_REG_RX1 4
`define
SPI_REG_TX1 4
`define
SPI_REG_RX2 8
`define
SPI_REG_TX2 8
`define
SPI_REG_RX3 12
`define
SPI_REG_TX3 12
`define
SPI_REG_CTRL 16
`define
SPI_REG_DIVIDER 20
`define
SPI_REG_SS 24
`define
SPI_CTRL_ASS
(
1
<<
13
)
//
automatic slave select
(
nCS
)
`define
SPI_CTRL_IE
(
1
<<
12
)
//
interrupt enable
`define
SPI_CTRL_LSB
(
1
<<
11
)
//
LSB first on line
`define
SPI_CTRL_TXNEG
(
1
<<
10
)
//
MOSI driven on negative SCLK edge
`define
SPI_CTRL_RXNEG
(
1
<<
9
)
//
MISO sampled on negative SCLK edge
`define
SPI_CTRL_GO_BSY
(
1
<<
8
)
`define
SPI_CTRL_CHAR_LEN
(
x
)
((
x
)
&
'
h7f
)
class
CSimDrv_WB_SPI
;
protected
CBusAccessor
acc
;
protected
uint64_t
base
;
function
new
(
CBusAccessor
busacc
,
uint64_t
adr
)
;
acc
=
busacc
;
base
=
adr
;
endfunction
task
init
()
;
// set divider
acc
.
write
(
base
+
`SPI_REG_DIVIDER
,
10
)
;
endtask
;
task
cs
(
int
state
)
;
acc
.
write
(
base
+
`SPI_REG_SS
,
state
)
;
endtask
task
txrx
(
uint32_t
in
,
int
nbits
,
output
uint32_t
out
)
;
uint64_t
rval
;
// configure transfer
acc
.
write
(
`SPI_REG_CTRL
,
`SPI_CTRL_CHAR_LEN
(
nbits
)
|
`SPI_CTRL_TXNEG
)
;
acc
.
write
(
`SPI_REG_TX0
,
in
)
;
// start transfer
acc
.
write
(
`SPI_REG_CTRL
,
`SPI_CTRL_CHAR_LEN
(
nbits
)
|
`SPI_CTRL_TXNEG
|
`SPI_CTRL_GO_BSY
)
;
do
begin
acc
.
read
(
`SPI_REG_CTRL
,
rval
)
;
end
while
(
rval
&
`SPI_CTRL_GO_BSY
)
;
acc
.
read
(
`SPI_REG_RX0
,
rval
)
;
out
=
rval
;
endtask
endclass
`endif
testbench/radtol/tb_secded_32b_pkg.vhd
0 → 100644
View file @
ba4bbfd2
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
work
.
secded_32b_pkg
.
all
;
entity
tb_secded_32b_pkg
is
end
tb_secded_32b_pkg
;
architecture
behav
of
tb_secded_32b_pkg
is
function
image
(
v
:
std_logic_vector
)
return
string
is
alias
va
:
std_logic_vector
(
1
to
v
'length
)
is
v
;
variable
res
:
string
(
va
'range
);
begin
for
i
in
va
'range
loop
if
va
(
i
)
=
'1'
then
res
(
i
)
:
=
'1'
;
else
res
(
i
)
:
=
'0'
;
end
if
;
end
loop
;
return
res
;
end
image
;
signal
orig_data
,
data
:
std_logic_vector
(
31
downto
0
);
signal
orig_ecc
,
ecc
,
comp_ecc
,
syndrome
:
std_logic_vector
(
6
downto
0
);
signal
err
,
cor
:
std_logic_vector
(
38
downto
0
);
type
vectors_type
is
array
(
natural
range
<>
)
of
std_logic_vector
(
31
downto
0
);
constant
vectors
:
vectors_type
:
=
(
x"00001197"
,
x"22c18193"
,
x"00040117"
,
x"ffffffff"
);
begin
process
variable
ecc2
:
std_logic_vector
(
6
downto
0
);
begin
for
i
in
vectors
'range
loop
ecc2
:
=
f_calc_ecc
(
vectors
(
i
));
report
"data: "
&
to_hstring
(
vectors
(
i
))
&
", ecc: "
&
to_hstring
(
ecc2
);
end
loop
;
orig_data
<=
x"789a_d3f5"
;
syndrome
<=
"0000000"
;
wait
for
1
ns
;
assert
f_ecc_errors
(
syndrome
)
=
'0'
severity
failure
;
assert
f_ecc_one_error
(
syndrome
)
=
'0'
severity
failure
;
orig_ecc
<=
f_calc_ecc
(
orig_data
);
-- Single error (detection and correction)
for
i
in
0
to
38
loop
err
<=
(
others
=>
'0'
);
err
(
i
)
<=
'1'
;
wait
for
1
ns
;
if
i
<
32
then
-- Bit flip in data
data
<=
orig_data
xor
err
(
31
downto
0
);
ecc
<=
orig_ecc
;
else
-- Bit flip in ecc
ecc
<=
orig_ecc
xor
err
(
38
downto
32
);
data
<=
orig_data
;
end
if
;
wait
for
1
ns
;
comp_ecc
<=
f_calc_ecc
(
data
);
wait
for
1
ns
;
syndrome
<=
comp_ecc
xor
ecc
;
wait
for
1
ns
;
assert
f_ecc_errors
(
syndrome
)
=
'1'
severity
failure
;
assert
f_ecc_one_error
(
syndrome
)
=
'1'
severity
failure
;
cor
<=
f_fix_error
(
syndrome
,
ecc
,
data
);
wait
for
1
ns
;
report
"data: "
&
image
(
data
)
&
", ecc: "
&
image
(
ecc
)
&
", err: "
&
image
(
err
)
&
", ecc/err: "
&
image
(
comp_ecc
);
report
"cdata: "
&
image
(
cor
(
31
downto
0
))
&
", cecc: "
&
image
(
cor
(
38
downto
32
))
&
" syndrome: "
&
image
(
syndrome
);
assert
cor
(
31
downto
0
)
=
orig_data
severity
failure
;
assert
cor
(
38
downto
32
)
=
orig_ecc
severity
failure
;
end
loop
;
report
"end of test"
;
wait
;
end
process
;
end
behav
;
testbench/radtol/tb_secded_ecc.vhd
0 → 100644
View file @
ba4bbfd2
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
ieee
.
numeric_std
.
all
;
entity
tb_secded_ecc
is
end
tb_secded_ecc
;
architecture
arch
of
tb_secded_ecc
is
constant
addr_width
:
natural
:
=
8
;
subtype
ram_word_t
is
std_logic_vector
(
38
downto
0
);
signal
clk
:
std_logic
;
signal
rst
:
std_logic
;
-- to the processor/bus
signal
addr
:
std_logic_vector
(
addr_width
-1
downto
0
);
signal
din
:
std_logic_vector
(
31
downto
0
);
signal
we
:
std_logic
;
signal
bwe
:
std_logic_vector
(
3
downto
0
);
signal
re
:
std_logic
;
signal
dout
:
std_logic_vector
(
31
downto
0
);
signal
done_r
:
std_logic
;
signal
done_w
:
std_logic
;
--to the BRAM
signal
a_ram
:
std_logic_vector
(
addr_width
-1
downto
0
);
signal
d_ram
:
ram_word_t
;
signal
q_ram
:
ram_word_t
;
signal
we_ram
:
std_logic
;
signal
re_ram
:
std_logic
;
signal
valid_ram
:
std_logic
;
signal
lock_req
:
std_logic
;
signal
lock_grant
:
std_logic
;
signal
force_err
:
ram_word_t
:
=
(
others
=>
'0'
);
signal
single_error_p
:
std_logic
;
signal
double_error_p
:
std_logic
;
signal
end_of_test
:
boolean
:
=
false
;
begin
process
begin
clk
<=
'0'
;
wait
for
5
ns
;
clk
<=
'1'
;
wait
for
5
ns
;
if
end_of_test
then
wait
;
end
if
;
end
process
;
rst
<=
'1'
,
'0'
after
20
ns
;
process
(
clk
)
type
mem_t
is
array
(
2
**
addr_width
-
1
downto
0
)
of
ram_word_t
;
variable
mem
:
mem_t
;
begin
if
rising_edge
(
clk
)
then
valid_ram
<=
'0'
;
if
we_ram
=
'1'
then
mem
(
to_integer
(
unsigned
(
a_ram
)))
:
=
q_ram
xor
force_err
;
valid_ram
<=
'1'
;
end
if
;
if
re_ram
=
'1'
then
d_ram
<=
mem
(
to_integer
(
unsigned
(
a_ram
)));
valid_ram
<=
'1'
;
end
if
;
end
if
;
end
process
;
inst_secded
:
entity
work
.
secded_ecc
generic
map
(
g_addr_width
=>
addr_width
)
port
map
(
clk_i
=>
clk
,
rst_i
=>
rst
,
a_i
=>
addr
,
d_i
=>
din
,
we_i
=>
we
,
bwe_i
=>
bwe
,
re_i
=>
re
,
q_o
=>
dout
,
done_r_o
=>
done_r
,
done_w_o
=>
done_w
,
a_ram_o
=>
a_ram
,
d_ram_i
=>
d_ram
,
q_ram_o
=>
q_ram
,
we_ram_o
=>
we_ram
,
re_ram_o
=>
re_ram
,
valid_ram_i
=>
valid_ram
,
lock_req_o
=>
lock_req
,
lock_grant_i
=>
lock_grant
,
single_error_p_o
=>
single_error_p
,
double_error_p_o
=>
double_error_p
);
lock_grant
<=
lock_req
;
proc_tb
:
process
constant
pattern
:
std_logic_vector
(
31
downto
0
)
:
=
x"0123_4567"
;
variable
xaddr
:
std_logic_vector
(
addr_width
-
1
downto
0
);
begin
wait
until
rst
=
'0'
;
wait
until
rising_edge
(
clk
);
-- Write words.
for
i
in
0
to
80
loop
xaddr
:
=
std_logic_vector
(
to_unsigned
(
i
,
addr_width
));
addr
<=
xaddr
;
din
<=
pattern
;
din
(
addr_width
-
1
downto
0
)
<=
xaddr
;
we
<=
'1'
;
bwe
<=
"1111"
;
force_err
<=
(
others
=>
'0'
);
if
i
>=
32
and
i
<
32
+
39
then
force_err
(
i
-
32
)
<=
'1'
;
elsif
i
=
71
then
force_err
(
31
)
<=
'1'
;
force_err
(
21
)
<=
'1'
;
end
if
;
re
<=
'0'
;
wait
until
rising_edge
(
clk
);
we
<=
'0'
;
wait
until
rising_edge
(
clk
)
and
done_w
=
'1'
;
end
loop
;
-- Check words
for
i
in
0
to
71
loop
xaddr
:
=
std_logic_vector
(
to_unsigned
(
i
,
addr_width
));
addr
<=
xaddr
;
re
<=
'1'
;
wait
until
rising_edge
(
clk
)
and
done_r
=
'1'
;
re
<=
'0'
;
case
i
is
when
0
to
31
=>
assert
dout
=
pattern
(
31
downto
addr_width
)
&
xaddr
severity
failure
;
assert
single_error_p
=
'0'
severity
failure
;
assert
double_error_p
=
'0'
severity
failure
;
when
32
to
70
=>
assert
dout
=
pattern
(
31
downto
addr_width
)
&
xaddr
severity
failure
;
assert
single_error_p
=
'1'
severity
failure
;
assert
double_error_p
=
'0'
severity
failure
;
when
71
=>
assert
single_error_p
=
'0'
severity
failure
;
assert
double_error_p
=
'1'
severity
failure
;
when
others
=>
assert
false
;
end
case
;
wait
until
rising_edge
(
clk
)
and
done_r
=
'0'
;
end
loop
;
report
"end of test"
;
end_of_test
<=
true
;
wait
;
end
process
;
end
;
\ No newline at end of file
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