Commit 63f36713 authored by Dimitris Lampridis's avatar Dimitris Lampridis

Merge branch 'release/1.0.4'

parents 9e46223f 42b207a0
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-License-Identifier: CC0-1.0
SPDX-FileCopyrightText: 2019 CERN
SPDX-FileCopyrightText: 2019-2020 CERN
==========
Change Log
==========
Format: `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_
Versioning: `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_
- Format inspired by: `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_
- Versioning scheme follows: `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_
1.0.4 - 2020-03-26
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.4
Added
-----
- [hdl] VHDL functions to convert characters and strings to upper/lower case.
- [sw][i2c] Support for kernel greater than 4.7.
- [hdl] Separate synchroniser and edge detection modules.
- [hdl] 8b10b encoder.
Changed
-------
- [hdl] Rewritten the WB master interface used in simulations.
- [hdl] Reimplement gc_sync_ffs using new synchroniser and edge detectors.
Fixed
-----
- [sw][spi] Align polarity and phase for Rx and Tx.
- [hdl][i2c] Fix reset lock for I2C master.
- [hdl] Avoid cyclic dependencies for log2 ceiling functions.
1.0.3 - 2020-01-15
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.3
[1.0.3] - 2020-01-15
====================
Changed
-----
- [sw] add more file to .gitignore
[1.0.2] - 2019-10-24
====================
1.0.2 - 2019-10-24
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.2
Fixed
-----
- [ci] forgot rule to publish RPMs
[1.0.1] - 2019-10-24
====================
1.0.1 - 2019-10-24
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.1
Added
-----
- [ci] building and publish RPMs automatically on new releases
Changed
-------
- [sw] Makefiles have been changed to better support RPM generation
[1.0.0] - 2019-10-21
====================
1.0.0 - 2019-10-21
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.0
Added
-----
- First release of general-cores.
......@@ -13,13 +13,22 @@ In [modules/common](modules/common) there are general purpose cores:
* The package [matrix_pkg](modules/common/matrix_pkg.vhd) declares a 2d
array of std_logic, and some subprograms to handle it.
* Edge detectors are provided by [gc_posedge](modules/common/gc_posedge.vhd)
and [gc_negedge](modules/common/gc_negedge.vhd).
* For clock-domain crossing or asynchronous signal register, use
[gc_sync_ffs](modules/common/gc_sync_ffs.vhd). It also has an edge
detector.
[gc_sync](modules/common/gc_sync.vhd). This is the basic synchronizer.
If you also need an edge detector, use
[gc_sync_ffs](modules/common/gc_sync_ffs.vhd).
The other synchronizer [gc_sync_register](modules/common/gc_sync_register.vhd)
is deprecated. It can synchronize multiple signals at the same time but
doesn't ensure coherency between these signals.
The module [gc_sync_edge](modules/common/gc_sync_edge.vhd) provides a
synchronizer with an (positive or negative) edge detector. The signal
edge is always detected on the rising edge of the clock. This module is
simpler than the gc_sync_ffs module.
To pass words from one clock domain to another, you can use the module
[gc_sync_word_wr](modules/common/gc_sync_word_wr.vhd) for writing data,
and [gc_sync_word_rd](modules/common/gc_sync_word_rd.vhd) for reading
......@@ -197,6 +206,15 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
AT91SAM9x CPU external bus interface.
- [wb_axi4lite_bridge](modules/wishbone/wb_axi4lite_bridge) is an axi4lite
to wishbone bridge
- [wb16_to_wb32](modules/wishbone/wb16_to_wb32) is an adapter from a
16 data bit wishbone master to a 32 data bit wishbone slave. It uses
an intermediate register. Refer to the module for how to use it.
* There are modules for axi4 bus
- [axi4lite32_axi4full64_bridge](modules/axi/axi4lite32_axi4full64_bridge) is
a bridge from axi4full64 to axi4lite32. It was defined to interface with
the Vivado PCI-e bridge and doesn't support all the axi4full features
(in particular the burst accesses).
* There a modules to build a bus hierarchy:
- [wb_bus_fanout](modules/wishbone/wb_bus_fanout) is a simple master to
......
modules = { "local" : [
"z7_axi_gpio_expander",
"axi4lite_wb_bridge",
"axi4lite32_axi4full64_bridge",
]}
files = [
......
files = [
"axi4lite32_axi4full64_bridge.vhd",
];
......@@ -11,6 +11,11 @@ files = [
"gc_serial_dac.vhd",
"gc_sync_ffs.vhd",
"gc_arbitrated_mux.vhd",
"gc_sync_register.vhd",
"gc_sync.vhd",
"gc_posedge.vhd",
"gc_negedge.vhd",
"gc_sync_edge.vhd",
"gc_pulse_synchronizer.vhd",
"gc_pulse_synchronizer2.vhd",
"gc_frequency_meter.vhd",
......@@ -25,10 +30,10 @@ files = [
"gc_big_adder.vhd",
"gc_fsm_watchdog.vhd",
"gc_bicolor_led_ctrl.vhd",
"gc_sync_register.vhd",
"gc_single_reset_gen.vhd",
"gc_async_signals_input_stage.vhd",
"gc_dec_8b10b.vhd",
"gc_enc_8b10b.vhd",
"gc_dyn_extend_pulse.vhd",
"gc_ds182x_interface.vhd",
"gc_ds182x_readout/gc_ds182x_readout.vhd",
......
This diff is collapsed.
......@@ -22,6 +22,21 @@
-- and limitations under the License.
--------------------------------------------------------------------------------
-- Principle of operation:
--
-- This block counts the number of pulses on CLK_IN_I during a period.
-- At the end of the period, the value is saved and the counter reset.
-- The saved value is available on FREQ_O, which is synchronized with
-- CLK_SYS_I if G_SYNC_OUT is True.
-- The width of the counter is defined by G_COUNTER_BITS.
--
-- - If g_WITH_INTERNAL_TIMEBASE is True:
-- The period is defined by an internal counter that generates a pulse
-- every G_CLK_SYS_FREQ CLK_SYS_I ticks.
--
-- - If g_WITH_INTERNAL_TIMEBASE is False:
-- The period is defined by PPS_P1_I
library ieee;
use ieee.std_logic_1164.all;
......
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_negedge
--
-- description: Simple falling edge detector. Combinatorial.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020
--------------------------------------------------------------------------------
-- 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 gc_negedge is
port(
clk_i : in std_logic; -- clock
rst_n_i : in std_logic; -- reset
data_i : in std_logic; -- input
pulse_o : out std_logic); -- falling edge detect output
end entity gc_negedge;
architecture arch of gc_negedge is
signal dff : std_logic;
begin
pulse_o <= not data_i and dff;
process (clk_i)
begin
if rising_edge (clk_i) then
if rst_n_i = '0' then
dff <= '0';
else
dff <= data_i;
end if;
end if;
end process;
end arch;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_posedge
--
-- description: Simple rising edge detector. Combinatorial.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020
--------------------------------------------------------------------------------
-- 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 gc_posedge is
port(
clk_i : in std_logic; -- clock
rst_n_i : in std_logic; -- reset
data_i : in std_logic; -- input
pulse_o : out std_logic); -- positive edge detect output
end entity gc_posedge;
architecture arch of gc_posedge is
signal dff : std_logic;
begin
pulse_o <= data_i and not dff;
process (clk_i)
begin
if rising_edge (clk_i) then
if rst_n_i = '0' then
dff <= '0';
else
dff <= data_i;
end if;
end if;
end process;
end arch;
......@@ -89,12 +89,18 @@ begin -- rtl
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;
......
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_sync
--
-- description: Elementary synchronizer chain using two flip-flops.
--
--------------------------------------------------------------------------------
-- 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;
entity gc_sync is
generic(
g_sync_edge : string := "positive");
port (
clk_i : in std_logic;
rst_n_a_i : in std_logic;
d_i : in std_logic;
q_o : out std_logic);
end gc_sync;
-- make Altera Quartus quiet regarding unknown attributes:
-- altera message_off 10335
architecture arch of gc_sync is
-- Use an intermediate signal with a particular name and a keep attribute
-- so that it can be referenced in the constraints in order to ignore
-- timing (TIG) on that signal.
signal gc_sync_ffs_in : std_logic;
signal sync0, sync1 : std_logic;
attribute rloc : string;
attribute rloc of sync0 : signal is "X0Y0";
attribute rloc of sync1 : signal is "X0Y0";
attribute shreg_extract : string;
attribute shreg_extract of sync0 : signal is "no";
attribute shreg_extract of sync1 : signal is "no";
attribute keep : string;
attribute keep of gc_sync_ffs_in : signal is "true";
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
attribute keep_hierarchy : string;
attribute keep_hierarchy of arch : architecture is "true";
attribute async_reg : string;
attribute async_reg of sync0 : signal is "true";
attribute async_reg of sync1 : signal is "true";
begin
assert g_sync_edge = "positive" or g_sync_edge = "negative" severity failure;
gc_sync_ffs_in <= d_i;
sync_posedge : if (g_sync_edge = "positive") generate
process(clk_i, rst_n_a_i)
begin
if rst_n_a_i = '0' then
sync1 <= '0';
sync0 <= '0';
elsif rising_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
end if;
end process;
end generate sync_posedge;
sync_negedge : if(g_sync_edge = "negative") generate
process(clk_i, rst_n_a_i)
begin
if rst_n_a_i = '0' then
sync1 <= '0';
sync0 <= '0';
elsif falling_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
end if;
end process;
end generate sync_negedge;
q_o <= sync1;
end arch;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_sync_edge
--
-- description: Synchronizer chain and edge detector.
-- All the registers in the chain are cleared at reset.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2010-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;
entity gc_sync_edge is
generic(
g_edge : string := "positive");
port(
clk_i : in std_logic; -- clock from the destination clock domain
rst_n_a_i : in std_logic; -- async reset
data_i : in std_logic; -- async input
synced_o : out std_logic; -- synchronized output
pulse_o : out std_logic); -- edge detect output
end entity gc_sync_edge;
architecture arch of gc_sync_edge is
signal sync : std_logic;
begin
inst_sync : entity work.gc_sync
port map (
clk_i => clk_i,
rst_n_a_i => rst_n_a_i,
d_i => data_i,
q_o => sync);
assert g_edge = "positive" or g_edge = "negative" severity FAILURE;
sync_posedge : if g_edge = "positive" generate
inst_pedge : entity work.gc_posedge
port map (
clk_i => clk_i,
rst_n_i => rst_n_a_i,
data_i => sync,
pulse_o => pulse_o);
end generate;
sync_negedge : if g_edge = "negative" generate
inst_pedge : entity work.gc_negedge
port map (
clk_i => clk_i,
rst_n_i => rst_n_a_i,
data_i => sync,
pulse_o => pulse_o);
end generate;
end architecture arch;
......@@ -31,66 +31,53 @@ entity gc_sync_ffs is
g_sync_edge : string := "positive");
port(
clk_i : in std_logic; -- clock from the destination clock domain
rst_n_i : in std_logic; -- reset
rst_n_i : in std_logic; -- async reset
data_i : in std_logic; -- async input
synced_o : out std_logic; -- synchronized output
npulse_o : out std_logic; -- negative edge detect output
ppulse_o : out std_logic); -- positive edge detect output
end entity gc_sync_ffs;
-- make Altera Quartus quiet regarding unknown attributes:
-- altera message_off 10335
architecture arch of gc_sync_ffs is
signal sync0, sync1, sync2 : std_logic;
signal gc_sync_ffs_in : std_logic;
attribute shreg_extract : string;
attribute shreg_extract of sync0 : signal is "no";
attribute shreg_extract of sync1 : signal is "no";
attribute shreg_extract of sync2 : signal is "no";
attribute keep : string;
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
attribute rloc : string;
attribute rloc of sync0 : signal is "X0Y0";
attribute rloc of sync1 : signal is "X0Y0";
attribute keep of gc_sync_ffs_in : signal is "true";
-- synchronizer attribute for Vivado
attribute ASYNC_REG : string;
attribute ASYNC_REG of sync0 : signal is "true";
attribute ASYNC_REG of sync1 : signal is "true";
attribute ASYNC_REG of sync2 : signal is "true";
signal sync, npulse, ppulse : std_logic;
begin
-- rename data_i to something we can use as wildcard
-- in timing constraints
gc_sync_ffs_in <= data_i;
cmp_gc_sync : entity work.gc_sync
generic map (
g_sync_edge => g_sync_edge)
port map (
clk_i => clk_i,
rst_n_a_i => rst_n_i,
d_i => data_i,
q_o => sync);
cmp_gc_posedge : entity work.gc_posedge
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => sync,
pulse_o => ppulse);
cmp_gc_negedge : entity work.gc_negedge
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => sync,
pulse_o => npulse);
sync_posedge : if (g_sync_edge = "positive") generate
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
sync0 <= '0';
sync1 <= '0';
sync2 <= '0';
synced_o <= '0';
npulse_o <= '0';
ppulse_o <= '0';
elsif rising_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
sync2 <= sync1;
synced_o <= sync1;
npulse_o <= sync2 and not sync1;
ppulse_o <= not sync2 and sync1;
synced_o <= sync;
npulse_o <= npulse;
ppulse_o <= ppulse;
end if;
end process;
end generate sync_posedge;
......@@ -99,19 +86,13 @@ begin
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
sync0 <= '0';
sync1 <= '0';
sync2 <= '0';
synced_o <= '0';
npulse_o <= '0';
ppulse_o <= '0';
elsif falling_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
sync2 <= sync1;
synced_o <= sync1;
npulse_o <= sync2 and not sync1;
ppulse_o <= not sync2 and sync1;
synced_o <= sync;
npulse_o <= npulse;
ppulse_o <= ppulse;
end if;
end process;
end generate sync_negedge;
......
......@@ -53,7 +53,10 @@ architecture rtl of gc_sync_register is
attribute keep of gc_sync_register_in : signal is "true";
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
attribute keep_hierarchy : string;
attribute keep_hierarchy of rtl : architecture is "true";
attribute async_reg : string;
attribute async_reg of gc_sync_register_in : signal is "true";
attribute async_reg of sync0 : signal is "true";
......
......@@ -27,10 +27,60 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
package gencores_pkg is
--============================================================================
-- Procedures and functions
--============================================================================
procedure f_rr_arbitrate (
signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector;
signal grant : out std_logic_vector);
function f_onehot_decode(x : std_logic_vector; size : integer) return std_logic_vector;
function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector;
function f_gray_encode(x : std_logic_vector) return std_logic_vector;
function f_gray_decode(x : std_logic_vector; step : natural) return std_logic_vector;
function f_log2_ceil(N : natural) return positive;
-- kept for backwards compatibility, same as f_log2_ceil()
function log2_ceil(N : natural) return positive;
function f_bool2int (b : boolean) return natural;
function f_int2bool (n : natural) return boolean;
-- Convert a boolean to std_logic ('1' for True, '0' for False).
function f_to_std_logic(b : boolean) return std_logic;
-- Reduce-OR an std_logic_vector to std_logic
function f_reduce_or (x : std_logic_vector) return std_logic;
-- Character/String to std_logic_vector
function f_to_std_logic_vector (c : character) return std_logic_vector;
function f_to_std_logic_vector (s : string) return std_logic_vector;
-- Functions for short-hand if assignments
function f_pick (cond : boolean; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : boolean; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
function f_pick (cond : std_logic; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : std_logic; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
-- Functions to convert characters and strings to upper/lower case
function to_upper(c : character) return character;
function to_lower(c : character) return character;
function to_upper(s : string) return string;
function to_lower(s : string) return string;
-- Bit reversal function
function f_reverse_vector (a : in std_logic_vector) return std_logic_vector;
--============================================================================
-- Component instantiations
--============================================================================
......@@ -198,6 +248,46 @@ package gencores_pkg is
ppulse_o : out std_logic);
end component;
component gc_sync is
generic (
g_sync_edge : string := "positive");
port (
clk_i : in std_logic;
rst_n_a_i : in std_logic;
d_i : in std_logic;
q_o : out std_logic);
end component gc_sync;
component gc_sync_edge is
generic (
g_edge : string := "positive");
port (
clk_i : in std_logic;
rst_n_a_i : in std_logic;
data_i : in std_logic;
synced_o : out std_logic;
pulse_o : out std_logic);
end component gc_sync_edge;
------------------------------------------------------------------------------
-- Edge detectors
------------------------------------------------------------------------------
component gc_negedge is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
data_i : in std_logic;
pulse_o : out std_logic);
end component gc_negedge;
component gc_posedge is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
data_i : in std_logic;
pulse_o : out std_logic);
end component gc_posedge;
------------------------------------------------------------------------------
-- Pulse synchroniser
------------------------------------------------------------------------------
......@@ -295,7 +385,7 @@ package gencores_pkg is
d_req_o : out std_logic_vector(g_num_inputs-1 downto 0);
q_o : out std_logic_vector(g_width-1 downto 0);
q_valid_o : out std_logic;
q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0));
q_input_id_o : out std_logic_vector(f_log2_ceil(g_num_inputs)-1 downto 0));
end component;
------------------------------------------------------------------------------
......@@ -690,42 +780,6 @@ package gencores_pkg is
counter_o : out std_logic_vector(g_bits downto 0));
end component gc_async_counter_diff;
--============================================================================
-- Procedures and functions
--============================================================================
procedure f_rr_arbitrate (
signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector;
signal grant : out std_logic_vector);
function f_onehot_decode(x : std_logic_vector; size : integer) return std_logic_vector;
function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector;
function f_gray_encode(x : std_logic_vector) return std_logic_vector;
function f_gray_decode(x : std_logic_vector; step : natural) return std_logic_vector;
function log2_ceil(N : natural) return positive;
function f_bool2int (b : boolean) return natural;
function f_int2bool (n : natural) return boolean;
-- Convert a boolean to std_logic ('1' for True, '0' for False).
function f_to_std_logic(b : boolean) return std_logic;
-- Reduce-OR an std_logic_vector to std_logic
function f_reduce_or (x : std_logic_vector) return std_logic;
-- Character/String to std_logic_vector
function f_to_std_logic_vector (c : character) return std_logic_vector;
function f_to_std_logic_vector (s : string) return std_logic_vector;
-- Functions for short-hand if assignments
function f_pick (cond : boolean; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : boolean; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
function f_pick (cond : std_logic; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : std_logic; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
end package;
package body gencores_pkg is
......@@ -827,17 +881,22 @@ package body gencores_pkg is
------------------------------------------------------------------------------
-- Returns log of 2 of a natural number
------------------------------------------------------------------------------
function log2_ceil(N : natural) return positive is
function f_log2_ceil(N : natural) return positive is
begin
if N <= 2 then
return 1;
elsif N mod 2 = 0 then
return 1 + log2_ceil(N/2);
return 1 + f_log2_ceil(N/2);
else
return 1 + log2_ceil((N+1)/2);
return 1 + f_log2_ceil((N+1)/2);
end if;
end;
-- kept for backwards compatibility
function log2_ceil(N : natural) return positive is
begin
return f_log2_ceil(N);
end;
------------------------------------------------------------------------------
-- Converts a boolean to natural integer (false -> 0, true -> 1)
......@@ -954,4 +1013,59 @@ package body gencores_pkg is
return f_pick (f_to_std_logic(cond), if_1, if_0);
end function f_pick;
------------------------------------------------------------------------------
-- Functions to convert characters and strings to upper/lower case
------------------------------------------------------------------------------
function to_upper(c : character) return character is
variable i : integer;
begin
i := character'pos(c);
if (i > 96 and i < 123) then
i := i - 32;
end if;
return character'val(i);
end function to_upper;
function to_lower(c : character) return character is
variable i : integer;
begin
i := character'pos(c);
if (i > 64 and i < 91) then
i := i + 32;
end if;
return character'val(i);
end function to_lower;
function to_upper(s : string) return string is
variable uppercase : string (s'range);
begin
for i in s'range loop
uppercase(i) := to_upper(s(i));
end loop;
return uppercase;
end to_upper;
function to_lower(s : string) return string is
variable lowercase : string (s'range);
begin
for i in s'range loop
lowercase(i) := to_lower(s(i));
end loop;
return lowercase;
end to_lower;
------------------------------------------------------------------------------
-- Vector bit reversal
------------------------------------------------------------------------------
function f_reverse_vector (a : in std_logic_vector) return std_logic_vector is
variable v_result : std_logic_vector(a'reverse_range);
begin
for i in a'range loop
v_result(i) := a(i);
end loop;
return v_result;
end function f_reverse_vector;
end gencores_pkg;
......@@ -83,6 +83,10 @@ entity inferred_async_fifo is
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
attribute keep_hierarchy : string;
attribute keep_hierarchy of
inferred_async_fifo : entity is "true";
end inferred_async_fifo;
......
......@@ -74,6 +74,10 @@ entity inferred_async_fifo_dual_rst is
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
attribute keep_hierarchy : string;
attribute keep_hierarchy of
inferred_async_fifo_dual_rst : entity is "true";
end inferred_async_fifo_dual_rst;
......
......@@ -72,13 +72,13 @@ end inferred_sync_fifo;
architecture syn of inferred_sync_fifo is
constant c_pointer_width : integer := f_log2_size(g_size);
signal rd_ptr, wr_ptr, wr_ptr_d0, rd_ptr_muxed : unsigned(c_pointer_width-1 downto 0);
signal usedw : unsigned(c_pointer_width downto 0);
signal full, empty : std_logic;
signal q_int : std_logic_vector(g_data_width-1 downto 0);
signal we_int, rd_int : std_logic;
signal guard_bit : std_logic;
constant c_pointer_width : integer := f_log2_size(g_size);
signal rd_ptr, wr_ptr, rd_ptr_muxed : unsigned(c_pointer_width-1 downto 0);
signal usedw : unsigned(c_pointer_width downto 0);
signal full, empty : std_logic;
signal we_int, rd_int : std_logic;
signal guard_bit : std_logic;
signal q_comb : std_logic_vector(g_data_width-1 downto 0);
......
......@@ -26,6 +26,9 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
package genram_pkg is
function f_log2_size (A : natural) return natural;
......@@ -248,14 +251,10 @@ end genram_pkg;
package body genram_pkg is
-- kept for backwards compatibility
function f_log2_size (A : natural) return natural is
begin
for I in 1 to 64 loop -- Works for up to 64 bits
if (2**I >= A) then
return(I);
end if;
end loop;
return(63);
return f_log2_ceil(A);
end function f_log2_size;
function f_gen_dummy_vec (val : std_logic; size : natural) return std_logic_vector is
......
......@@ -118,17 +118,12 @@ architecture syn of generic_dpram_dualclock is
return false;
-- synthesis translate_on
return true;
end f_is_synthesis;
end f_is_synthesis;
shared variable ram : t_ram_type := f_file_to_ramtype;
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0);
signal clka_int : std_logic;
signal clkb_int : std_logic;
signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0);
......@@ -177,7 +172,7 @@ begin
end loop;
end if;
end process;
......@@ -266,6 +261,6 @@ begin
end if;
end process;
end generate gen_without_byte_enable_nochange;
end syn;
......@@ -123,9 +123,7 @@ architecture syn of generic_dpram_sameclock is
shared variable ram : t_ram_type := f_file_to_ramtype;
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0);
signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0);
......
......@@ -26,6 +26,7 @@ modules = { "local" : [
"wb_ds182x_readout",
"wb_metadata",
"wb_split",
"wb16_to_wb32",
"wbgen2",
"wbgenplus",
]}
......
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- WR2RF_VME core
-- https://ohwr.org/project/vme-rf-wr-bobr
--------------------------------------------------------------------------------
--
-- unit name: wb16_to_wb32
--
-- description: Bridge wishbone data width by using a register for the upper 16
-- bits.
-- In order to atomically read a 32 bit word at address ADDR:
-- * read the 16 LSB word at address ADDR
-- * read the 16 MSB word at address ADDR+2
-- In order to atomically write a 32 bit word at address ADDR:
-- * write the 16 MSB word at address ADDR+2
-- * write the 16 LSB word at address ADDR
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN (home.cern)
--------------------------------------------------------------------------------
-- 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.wishbone_pkg.all;
entity wb16_to_wb32 is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
wb16_i : in t_wishbone_slave_in;
wb16_o : out t_wishbone_slave_out;
wb32_i : in t_wishbone_master_in;
wb32_o : out t_wishbone_master_out
);
end;
architecture arch of wb16_to_wb32 is
signal datah : std_logic_vector(15 downto 0);
signal stall : std_logic;
signal we : std_logic;
signal ack : std_logic;
begin
wb16_o.stall <= stall or ack;
wb32_o.dat (31 downto 16) <= datah;
wb16_o.rty <= '0';
wb16_o.err <= '0';
wb16_o.ack <= ack;
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
datah <= (others => '0');
stall <= '0';
ack <= '0';
wb32_o.cyc <= '0';
wb32_o.stb <= '0';
else
if stall = '0' then
-- Ready.
ack <= '0';
if wb16_i.stb = '1' and wb16_i.cyc = '1' and ack = '0' then
if wb16_i.adr(1) = '1' then
-- Access to DATAH.
if wb16_i.we = '1' then
-- Write.
if wb16_i.sel(0) = '1' then
datah (7 downto 0) <= wb16_i.dat(7 downto 0);
end if;
if wb16_i.sel(1) = '1' then
datah (15 downto 8) <= wb16_i.dat(15 downto 8);
end if;
else
-- Read
wb16_o.dat(15 downto 0) <= datah;
end if;
ack <= '1';
else
-- Access to the device.
stall <= '1';
we <= wb16_i.we;
wb32_o.cyc <= '1';
wb32_o.stb <= '1';
wb32_o.adr <= wb16_i.adr(31 downto 2) & "00";
wb32_o.dat (15 downto 0) <= wb16_i.dat(15 downto 0);
wb32_o.we <= wb16_i.we;
wb32_o.sel <= "11" & wb16_i.sel (1 downto 0); -- Humm...
end if;
end if;
else
-- Stall = 1, waiting for the answer.
if wb32_i.ack = '1' then
wb16_o.dat (15 downto 0) <= wb32_i.dat (15 downto 0);
if we = '0' then
datah <= wb32_i.dat (31 downto 16);
end if;
wb32_o.cyc <= '0';
wb32_o.stb <= '0';
ack <= '1';
stall <= '0';
end if;
end if;
end if;
end if;
end process;
end arch;
......@@ -157,7 +157,7 @@ architecture structural of i2c_master_top is
signal sr : std_logic_vector(7 downto 0); -- status register
-- internal reset signal
signal rst_i : std_logic;
signal arst_n : std_logic;
-- wishbone write access
signal wb_wacc : std_logic;
......@@ -190,7 +190,7 @@ architecture structural of i2c_master_top is
begin
-- generate internal reset signal
rst_i <= not wb_rst_i; --arst_i xor ARST_LVL;
arst_n <= arst_i xor ARST_LVL;
-- generate acknowledge output signal
gen_ack_o : process(wb_clk_i)
......@@ -228,9 +228,9 @@ begin
-- generate registers (CR, SR see below)
gen_regs: process(rst_i, wb_clk_i)
gen_regs: process(arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
prer <= (others => '1');
ctr <= (others => '0');
txr <= (others => '0');
......@@ -268,9 +268,9 @@ begin
-- generate command register
gen_cr: process(rst_i, wb_clk_i)
gen_cr: process(arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
cr <= (others => '0');
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
......@@ -309,7 +309,7 @@ begin
port map (
clk => wb_clk_i,
rst => wb_rst_i,
nReset => rst_i,
nReset => arst_n,
ena => core_en,
clk_cnt => prer,
start => sta,
......@@ -346,9 +346,9 @@ begin
st_irq_block : block
begin
-- generate status register bits
gen_sr_bits: process (wb_clk_i, rst_i)
gen_sr_bits: process (arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
al <= '0';
rxack <= '0';
tip <= '0';
......@@ -371,9 +371,9 @@ begin
end process gen_sr_bits;
-- generate interrupt request signals
gen_irq: process (wb_clk_i, rst_i)
gen_irq: process (arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
inta_o <= '0';
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
......
......@@ -28,9 +28,6 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.genram_pkg.all;
package wishbone_pkg is
constant c_wishbone_address_width : integer := 32;
......
This diff is collapsed.
......@@ -28,6 +28,91 @@
#include <linux/spinlock.h>
#include <linux/jiffies.h>
struct ocores_i2c;
static int ohwr_i2c_mux_select(struct ocores_i2c *i2c, u32 num);
static int ohwr_i2c_mux_deselect(struct ocores_i2c *i2c, u32 num);
#if KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE
struct i2c_mux_core {
struct i2c_adapter *parent;
struct device *dev;
void *priv;
unsigned int max_adapters;
struct i2c_adapter *adapter[0];
};
/**
* It selects the I2C bus to use and lock it
*/
static int ocores_i2c_mux_select_old_api(struct i2c_adapter *adap,
void *priv, u32 num)
{
struct ocores_i2c *i2c = priv;
return ohwr_i2c_mux_select(i2c, num);
}
/**
* It unlocks the bus so that it can be changed.
*/
static int ocores_i2c_mux_deselect_old_api(struct i2c_adapter *adap,
void *priv, u32 num)
{
struct ocores_i2c *i2c = priv;
return ohwr_i2c_mux_deselect(i2c, num);
}
struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
struct device *dev, int max_adapters,
int sizeof_priv, u32 flags,
int (*select)(struct i2c_mux_core *, u32),
int (*deselect)(struct i2c_mux_core *, u32))
{
struct i2c_mux_core *muxc;
muxc = devm_kzalloc(dev, sizeof(*muxc) +
sizeof(*muxc->adapter) * max_adapters +
sizeof_priv, GFP_KERNEL);
if (!muxc)
return NULL;
if (sizeof_priv)
muxc->priv = &muxc->adapter[max_adapters];
muxc->parent = parent;
muxc->dev = dev;
muxc->max_adapters = max_adapters;
return muxc;
}
int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
u32 force_nr, u32 chan_id,
unsigned int class)
{
muxc->adapter[chan_id] = i2c_add_mux_adapter(muxc->parent,
muxc->dev,
muxc->priv,
force_nr,
chan_id,
#if KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE
class, /* class */
#endif
ocores_i2c_mux_select_old_api,
ocores_i2c_mux_deselect_old_api);
return muxc->adapter[chan_id] ? 0 : -EINVAL;
}
void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
{
int i;
for (i = 0; i < muxc->max_adapters; ++i)
i2c_del_mux_adapter(muxc->adapter[i]);
}
#endif
#define OCORES_FLAG_POLL BIT(0)
/**
......@@ -41,8 +126,7 @@ struct ocores_i2c {
unsigned long flags;
wait_queue_head_t wait;
struct i2c_adapter adap;
struct i2c_adapter **adap_mux;
unsigned int n_adap_mux;
struct i2c_mux_core *adap_mux;
struct i2c_msg *msg;
int pos;
int nmsgs;
......@@ -578,14 +662,8 @@ static const struct platform_device_id ocores_id_table[] = {
};
MODULE_DEVICE_TABLE(id_table, ocores_id_table);
/**
* It selects the I2C bus to use and lock it
*/
static int ocores_i2c_mux_select(struct i2c_adapter *adap,
void *priv, u32 num)
static int ohwr_i2c_mux_select(struct ocores_i2c *i2c, u32 num)
{
struct ocores_i2c *i2c = priv;
u8 mux;
mux = oc_getreg(i2c, OCI2C_OHWR_MUX);
......@@ -601,57 +679,69 @@ static int ocores_i2c_mux_select(struct i2c_adapter *adap,
return 0;
}
/**
* It unlocks the bus so that it can be changed.
*/
static int ocores_i2c_mux_deselect(struct i2c_adapter *adap,
void *priv, u32 num)
static int ohwr_i2c_mux_deselect(struct ocores_i2c *i2c, u32 num)
{
struct ocores_i2c *i2c = priv;
u8 mux;
/* Unlock bus selection */
mux = oc_getreg(i2c, OCI2C_OHWR_MUX);
if (unlikely(!(mux & OCI2C_OHWR_MUX_BUSY)))
dev_err(&adap->dev, "deselect a bus that was not selected\n");
dev_err(i2c->adap_mux->dev,
"deselect a bus that was not selected\n");
mux &= ~OCI2C_OHWR_MUX_BUSY;
oc_setreg(i2c, OCI2C_OHWR_MUX, mux);
return 0;
}
/**
* It selects the I2C bus to use and lock it
*/
static int ocores_i2c_mux_select(struct i2c_mux_core *muxc, u32 num)
{
struct ocores_i2c *i2c = muxc->priv;
return ohwr_i2c_mux_select(i2c, num);
}
/**
* It unlocks the bus so that it can be changed.
*/
static int ocores_i2c_mux_deselect(struct i2c_mux_core *muxc, u32 num)
{
struct ocores_i2c *i2c = muxc->priv;
return ohwr_i2c_mux_deselect(i2c, num);
}
/**
* Add OHWR multiplexer
*/
static int ocores_i2c_probe_ohwr(struct ocores_i2c *i2c)
{
int err, i;
i2c->n_adap_mux = 2;
i2c->adap_mux = devm_kzalloc(&i2c->adap.dev,
sizeof(void *) * i2c->n_adap_mux,
GFP_KERNEL);
for (i = 0; i < i2c->n_adap_mux; ++i) {
i2c->adap_mux[i] = i2c_add_mux_adapter(&i2c->adap,
i2c->adap.dev.parent,
i2c,
0, i,
#if KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE
0, /* class */
#endif
ocores_i2c_mux_select,
ocores_i2c_mux_deselect);
if (!i2c->adap_mux[i])
int i, err = 0;
i2c->adap_mux = i2c_mux_alloc(&i2c->adap, i2c->adap.dev.parent,
2, sizeof(i2c), 0,
ocores_i2c_mux_select,
ocores_i2c_mux_deselect);
if (!i2c->adap_mux) {
err = -ENOMEM;
goto err_exit;
}
i2c->adap_mux->priv = i2c;
for (i = 0; i < i2c->adap_mux->max_adapters; ++i) {
err = i2c_mux_add_adapter(i2c->adap_mux,
0, i, 0);
if (err)
goto err_add;
}
return 0;
err_add:
while (--i >= 0)
i2c_del_mux_adapter(i2c->adap_mux[i]);
i2c_mux_del_adapters(i2c->adap_mux);
err_exit:
return err;
}
......@@ -660,10 +750,7 @@ err_add:
*/
static void ocores_i2c_remove_ohwr(struct ocores_i2c *i2c)
{
int i;
for (i = 0; i < i2c->n_adap_mux; ++i)
i2c_del_mux_adapter(i2c->adap_mux[i]);
i2c_mux_del_adapters(i2c->adap_mux);
}
#ifdef CONFIG_OF
......
[*]
[*] GTKWave Analyzer v3.3.98 (w)1999-2018 BSI
[*] Tue Mar 3 12:42:41 2020
[*]
[dumpfile] "/home/tgingold/Repositories/ohwr/general-cores/modules/wishbone/wb16_to_wb32/tb/tb.ghw"
[dumpfile_mtime] "Tue Mar 3 12:40:34 2020"
[dumpfile_size] 2363
[savefile] "/home/tgingold/Repositories/ohwr/general-cores/modules/wishbone/wb16_to_wb32/tb/tb.gtkw"
[timestart] 0
[size] 1620 1056
[pos] -1 -1
*-23.629396 61240000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top.
[treeopen] top.tb_wb16_to_wb32.
[sst_width] 283
[signals_width] 102
[sst_expanded] 1
[sst_vpaned_height] 315
@28
top.tb_wb16_to_wb32.rst_n
top.tb_wb16_to_wb32.clk
@200
-wb32
@28
top.tb_wb16_to_wb32.wb32_in.cyc
top.tb_wb16_to_wb32.wb32_in.stb
top.tb_wb16_to_wb32.wb32_in.we
top.tb_wb16_to_wb32.wb32_out.ack
@22
#{top.tb_wb16_to_wb32.wb32_out.dat[31:0]} top.tb_wb16_to_wb32.wb32_out.dat[31] top.tb_wb16_to_wb32.wb32_out.dat[30] top.tb_wb16_to_wb32.wb32_out.dat[29] top.tb_wb16_to_wb32.wb32_out.dat[28] top.tb_wb16_to_wb32.wb32_out.dat[27] top.tb_wb16_to_wb32.wb32_out.dat[26] top.tb_wb16_to_wb32.wb32_out.dat[25] top.tb_wb16_to_wb32.wb32_out.dat[24] top.tb_wb16_to_wb32.wb32_out.dat[23] top.tb_wb16_to_wb32.wb32_out.dat[22] top.tb_wb16_to_wb32.wb32_out.dat[21] top.tb_wb16_to_wb32.wb32_out.dat[20] top.tb_wb16_to_wb32.wb32_out.dat[19] top.tb_wb16_to_wb32.wb32_out.dat[18] top.tb_wb16_to_wb32.wb32_out.dat[17] top.tb_wb16_to_wb32.wb32_out.dat[16] top.tb_wb16_to_wb32.wb32_out.dat[15] top.tb_wb16_to_wb32.wb32_out.dat[14] top.tb_wb16_to_wb32.wb32_out.dat[13] top.tb_wb16_to_wb32.wb32_out.dat[12] top.tb_wb16_to_wb32.wb32_out.dat[11] top.tb_wb16_to_wb32.wb32_out.dat[10] top.tb_wb16_to_wb32.wb32_out.dat[9] top.tb_wb16_to_wb32.wb32_out.dat[8] top.tb_wb16_to_wb32.wb32_out.dat[7] top.tb_wb16_to_wb32.wb32_out.dat[6] top.tb_wb16_to_wb32.wb32_out.dat[5] top.tb_wb16_to_wb32.wb32_out.dat[4] top.tb_wb16_to_wb32.wb32_out.dat[3] top.tb_wb16_to_wb32.wb32_out.dat[2] top.tb_wb16_to_wb32.wb32_out.dat[1] top.tb_wb16_to_wb32.wb32_out.dat[0]
#{top.tb_wb16_to_wb32.wb32_in.adr[31:0]} top.tb_wb16_to_wb32.wb32_in.adr[31] top.tb_wb16_to_wb32.wb32_in.adr[30] top.tb_wb16_to_wb32.wb32_in.adr[29] top.tb_wb16_to_wb32.wb32_in.adr[28] top.tb_wb16_to_wb32.wb32_in.adr[27] top.tb_wb16_to_wb32.wb32_in.adr[26] top.tb_wb16_to_wb32.wb32_in.adr[25] top.tb_wb16_to_wb32.wb32_in.adr[24] top.tb_wb16_to_wb32.wb32_in.adr[23] top.tb_wb16_to_wb32.wb32_in.adr[22] top.tb_wb16_to_wb32.wb32_in.adr[21] top.tb_wb16_to_wb32.wb32_in.adr[20] top.tb_wb16_to_wb32.wb32_in.adr[19] top.tb_wb16_to_wb32.wb32_in.adr[18] top.tb_wb16_to_wb32.wb32_in.adr[17] top.tb_wb16_to_wb32.wb32_in.adr[16] top.tb_wb16_to_wb32.wb32_in.adr[15] top.tb_wb16_to_wb32.wb32_in.adr[14] top.tb_wb16_to_wb32.wb32_in.adr[13] top.tb_wb16_to_wb32.wb32_in.adr[12] top.tb_wb16_to_wb32.wb32_in.adr[11] top.tb_wb16_to_wb32.wb32_in.adr[10] top.tb_wb16_to_wb32.wb32_in.adr[9] top.tb_wb16_to_wb32.wb32_in.adr[8] top.tb_wb16_to_wb32.wb32_in.adr[7] top.tb_wb16_to_wb32.wb32_in.adr[6] top.tb_wb16_to_wb32.wb32_in.adr[5] top.tb_wb16_to_wb32.wb32_in.adr[4] top.tb_wb16_to_wb32.wb32_in.adr[3] top.tb_wb16_to_wb32.wb32_in.adr[2] top.tb_wb16_to_wb32.wb32_in.adr[1] top.tb_wb16_to_wb32.wb32_in.adr[0]
#{top.tb_wb16_to_wb32.wb32_in.dat[31:0]} top.tb_wb16_to_wb32.wb32_in.dat[31] top.tb_wb16_to_wb32.wb32_in.dat[30] top.tb_wb16_to_wb32.wb32_in.dat[29] top.tb_wb16_to_wb32.wb32_in.dat[28] top.tb_wb16_to_wb32.wb32_in.dat[27] top.tb_wb16_to_wb32.wb32_in.dat[26] top.tb_wb16_to_wb32.wb32_in.dat[25] top.tb_wb16_to_wb32.wb32_in.dat[24] top.tb_wb16_to_wb32.wb32_in.dat[23] top.tb_wb16_to_wb32.wb32_in.dat[22] top.tb_wb16_to_wb32.wb32_in.dat[21] top.tb_wb16_to_wb32.wb32_in.dat[20] top.tb_wb16_to_wb32.wb32_in.dat[19] top.tb_wb16_to_wb32.wb32_in.dat[18] top.tb_wb16_to_wb32.wb32_in.dat[17] top.tb_wb16_to_wb32.wb32_in.dat[16] top.tb_wb16_to_wb32.wb32_in.dat[15] top.tb_wb16_to_wb32.wb32_in.dat[14] top.tb_wb16_to_wb32.wb32_in.dat[13] top.tb_wb16_to_wb32.wb32_in.dat[12] top.tb_wb16_to_wb32.wb32_in.dat[11] top.tb_wb16_to_wb32.wb32_in.dat[10] top.tb_wb16_to_wb32.wb32_in.dat[9] top.tb_wb16_to_wb32.wb32_in.dat[8] top.tb_wb16_to_wb32.wb32_in.dat[7] top.tb_wb16_to_wb32.wb32_in.dat[6] top.tb_wb16_to_wb32.wb32_in.dat[5] top.tb_wb16_to_wb32.wb32_in.dat[4] top.tb_wb16_to_wb32.wb32_in.dat[3] top.tb_wb16_to_wb32.wb32_in.dat[2] top.tb_wb16_to_wb32.wb32_in.dat[1] top.tb_wb16_to_wb32.wb32_in.dat[0]
#{top.tb_wb16_to_wb32.wb32_in.sel[3:0]} top.tb_wb16_to_wb32.wb32_in.sel[3] top.tb_wb16_to_wb32.wb32_in.sel[2] top.tb_wb16_to_wb32.wb32_in.sel[1] top.tb_wb16_to_wb32.wb32_in.sel[0]
@200
-wb16
@28
top.tb_wb16_to_wb32.wb16_out.cyc
top.tb_wb16_to_wb32.wb16_out.stb
top.tb_wb16_to_wb32.wb16_out.we
@29
top.tb_wb16_to_wb32.wb16_in.stall
@22
#{top.tb_wb16_to_wb32.wb16_out.adr[31:0]} top.tb_wb16_to_wb32.wb16_out.adr[31] top.tb_wb16_to_wb32.wb16_out.adr[30] top.tb_wb16_to_wb32.wb16_out.adr[29] top.tb_wb16_to_wb32.wb16_out.adr[28] top.tb_wb16_to_wb32.wb16_out.adr[27] top.tb_wb16_to_wb32.wb16_out.adr[26] top.tb_wb16_to_wb32.wb16_out.adr[25] top.tb_wb16_to_wb32.wb16_out.adr[24] top.tb_wb16_to_wb32.wb16_out.adr[23] top.tb_wb16_to_wb32.wb16_out.adr[22] top.tb_wb16_to_wb32.wb16_out.adr[21] top.tb_wb16_to_wb32.wb16_out.adr[20] top.tb_wb16_to_wb32.wb16_out.adr[19] top.tb_wb16_to_wb32.wb16_out.adr[18] top.tb_wb16_to_wb32.wb16_out.adr[17] top.tb_wb16_to_wb32.wb16_out.adr[16] top.tb_wb16_to_wb32.wb16_out.adr[15] top.tb_wb16_to_wb32.wb16_out.adr[14] top.tb_wb16_to_wb32.wb16_out.adr[13] top.tb_wb16_to_wb32.wb16_out.adr[12] top.tb_wb16_to_wb32.wb16_out.adr[11] top.tb_wb16_to_wb32.wb16_out.adr[10] top.tb_wb16_to_wb32.wb16_out.adr[9] top.tb_wb16_to_wb32.wb16_out.adr[8] top.tb_wb16_to_wb32.wb16_out.adr[7] top.tb_wb16_to_wb32.wb16_out.adr[6] top.tb_wb16_to_wb32.wb16_out.adr[5] top.tb_wb16_to_wb32.wb16_out.adr[4] top.tb_wb16_to_wb32.wb16_out.adr[3] top.tb_wb16_to_wb32.wb16_out.adr[2] top.tb_wb16_to_wb32.wb16_out.adr[1] top.tb_wb16_to_wb32.wb16_out.adr[0]
#{top.tb_wb16_to_wb32.wb16_out.dat[31:0]} top.tb_wb16_to_wb32.wb16_out.dat[31] top.tb_wb16_to_wb32.wb16_out.dat[30] top.tb_wb16_to_wb32.wb16_out.dat[29] top.tb_wb16_to_wb32.wb16_out.dat[28] top.tb_wb16_to_wb32.wb16_out.dat[27] top.tb_wb16_to_wb32.wb16_out.dat[26] top.tb_wb16_to_wb32.wb16_out.dat[25] top.tb_wb16_to_wb32.wb16_out.dat[24] top.tb_wb16_to_wb32.wb16_out.dat[23] top.tb_wb16_to_wb32.wb16_out.dat[22] top.tb_wb16_to_wb32.wb16_out.dat[21] top.tb_wb16_to_wb32.wb16_out.dat[20] top.tb_wb16_to_wb32.wb16_out.dat[19] top.tb_wb16_to_wb32.wb16_out.dat[18] top.tb_wb16_to_wb32.wb16_out.dat[17] top.tb_wb16_to_wb32.wb16_out.dat[16] top.tb_wb16_to_wb32.wb16_out.dat[15] top.tb_wb16_to_wb32.wb16_out.dat[14] top.tb_wb16_to_wb32.wb16_out.dat[13] top.tb_wb16_to_wb32.wb16_out.dat[12] top.tb_wb16_to_wb32.wb16_out.dat[11] top.tb_wb16_to_wb32.wb16_out.dat[10] top.tb_wb16_to_wb32.wb16_out.dat[9] top.tb_wb16_to_wb32.wb16_out.dat[8] top.tb_wb16_to_wb32.wb16_out.dat[7] top.tb_wb16_to_wb32.wb16_out.dat[6] top.tb_wb16_to_wb32.wb16_out.dat[5] top.tb_wb16_to_wb32.wb16_out.dat[4] top.tb_wb16_to_wb32.wb16_out.dat[3] top.tb_wb16_to_wb32.wb16_out.dat[2] top.tb_wb16_to_wb32.wb16_out.dat[1] top.tb_wb16_to_wb32.wb16_out.dat[0]
#{top.tb_wb16_to_wb32.wb16_out.sel[3:0]} top.tb_wb16_to_wb32.wb16_out.sel[3] top.tb_wb16_to_wb32.wb16_out.sel[2] top.tb_wb16_to_wb32.wb16_out.sel[1] top.tb_wb16_to_wb32.wb16_out.sel[0]
@28
top.tb_wb16_to_wb32.wb16_in.ack
@22
#{top.tb_wb16_to_wb32.wb16_in.dat[31:0]} top.tb_wb16_to_wb32.wb16_in.dat[31] top.tb_wb16_to_wb32.wb16_in.dat[30] top.tb_wb16_to_wb32.wb16_in.dat[29] top.tb_wb16_to_wb32.wb16_in.dat[28] top.tb_wb16_to_wb32.wb16_in.dat[27] top.tb_wb16_to_wb32.wb16_in.dat[26] top.tb_wb16_to_wb32.wb16_in.dat[25] top.tb_wb16_to_wb32.wb16_in.dat[24] top.tb_wb16_to_wb32.wb16_in.dat[23] top.tb_wb16_to_wb32.wb16_in.dat[22] top.tb_wb16_to_wb32.wb16_in.dat[21] top.tb_wb16_to_wb32.wb16_in.dat[20] top.tb_wb16_to_wb32.wb16_in.dat[19] top.tb_wb16_to_wb32.wb16_in.dat[18] top.tb_wb16_to_wb32.wb16_in.dat[17] top.tb_wb16_to_wb32.wb16_in.dat[16] top.tb_wb16_to_wb32.wb16_in.dat[15] top.tb_wb16_to_wb32.wb16_in.dat[14] top.tb_wb16_to_wb32.wb16_in.dat[13] top.tb_wb16_to_wb32.wb16_in.dat[12] top.tb_wb16_to_wb32.wb16_in.dat[11] top.tb_wb16_to_wb32.wb16_in.dat[10] top.tb_wb16_to_wb32.wb16_in.dat[9] top.tb_wb16_to_wb32.wb16_in.dat[8] top.tb_wb16_to_wb32.wb16_in.dat[7] top.tb_wb16_to_wb32.wb16_in.dat[6] top.tb_wb16_to_wb32.wb16_in.dat[5] top.tb_wb16_to_wb32.wb16_in.dat[4] top.tb_wb16_to_wb32.wb16_in.dat[3] top.tb_wb16_to_wb32.wb16_in.dat[2] top.tb_wb16_to_wb32.wb16_in.dat[1] top.tb_wb16_to_wb32.wb16_in.dat[0]
[pattern_trace] 1
[pattern_trace] 0
library ieee;
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
entity tb_wb16_to_wb32 is
end;
architecture behav of tb_wb16_to_wb32 is
signal clk : std_logic;
signal rst_n : std_logic;
signal wb16_in : t_wishbone_master_in;
signal wb16_out : t_wishbone_master_out;
signal wb32_in : t_wishbone_slave_in;
signal wb32_out : t_wishbone_slave_out;
signal reg1 : std_logic_vector(31 downto 0);
signal reg0 : std_logic_vector(31 downto 0);
signal done : boolean := false;
begin
dut: entity work.wb16_to_wb32
port map (
clk_i => clk,
rst_n_i => rst_n,
wb16_i => wb16_out,
wb16_o => wb16_in,
wb32_i => wb32_out,
wb32_o => wb32_in
);
process
begin
clk <= '0';
wait for 5 ns;
clk <= '1';
wait for 5 ns;
if done then
wait;
end if;
end process;
-- Simple slave with 2 registers.
process (clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
reg1 <= x"4400_3300";
reg0 <= x"2200_1100";
wb32_out.ack <= '0';
else
if wb32_in.cyc = '1' and wb32_in.stb = '1' then
if wb32_in.we = '1' then
if wb32_in.adr (2) = '1' then
reg1 <= wb32_in.dat;
else
reg0 <= wb32_in.dat;
end if;
else
if wb32_in.adr (2) = '1' then
wb32_out.dat <= reg1;
else
wb32_out.dat <= reg0;
end if;
end if;
wb32_out.ack <= '1';
else
wb32_out.ack <= '0';
end if;
end if;
end if;
end process;
process
procedure wait_ack is
begin
loop
wait until rising_edge (clk);
exit when wb16_in.ack = '1';
end loop;
end wait_ack;
procedure read16 (addr : std_logic_vector (31 downto 0)) is
begin
wb16_out.adr <= addr;
wb16_out.we <= '0';
wb16_out.cyc <= '1';
wb16_out.stb <= '1';
wait_ack;
end read16;
procedure write16 (addr : std_logic_vector (31 downto 0); dat : std_logic_vector(15 downto 0)) is
begin
wb16_out.adr <= addr;
wb16_out.dat (15 downto 0) <= dat;
wb16_out.we <= '1';
wb16_out.sel <= "0011";
wb16_out.cyc <= '1';
wb16_out.stb <= '1';
wait_ack;
end write16;
begin
rst_n <= '0';
wait until rising_edge (clk);
wait until rising_edge (clk);
rst_n <= '1';
read16 (x"0000_0000");
assert wb16_in.dat (15 downto 0) = x"1100" severity failure;
read16 (x"0000_0002");
assert wb16_in.dat (15 downto 0) = x"2200" severity failure;
read16 (x"0000_0004");
assert wb16_in.dat (15 downto 0) = x"3300" severity failure;
read16 (x"0000_0006");
assert wb16_in.dat (15 downto 0) = x"4400" severity failure;
write16(x"0000_0002", x"0220");
write16(x"0000_0000", x"0110");
read16 (x"0000_0000");
assert wb16_in.dat (15 downto 0) = x"0110" severity failure;
read16 (x"0000_0002");
assert wb16_in.dat (15 downto 0) = x"0220" severity failure;
done <= true;
report "done";
wait;
end process;
end behav;
\ No newline at end of file
......@@ -3,10 +3,16 @@
with open("buildinfo_pkg.vhd", "w") as f:
import subprocess
import time
commitid = subprocess.check_output(
try:
commitid = subprocess.check_output(
["git", "log", "-1", "--format=%H"]).decode().strip()
userid = subprocess.check_output(
except:
commitid = "unknown"
try:
userid = subprocess.check_output(
["git", "config", "--get", "user.name"]).decode().strip()
except:
userid = "unknown"
if action == "simulation":
top = sim_top
tool = sim_tool
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment