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",
];
-------------------------------------------------------------------------------
-- Title : AXI4Full64 to AXI4Lite32 bridge
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : axi4lite32_axi4full64_bridge.vhd
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Copyright (c) 2019 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 ieee.numeric_std.all;
entity axi4lite32_axi4full64_bridge is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- AXI4-Full slave
s_awaddr : in STD_LOGIC_VECTOR (31 downto 0);
s_awlen : in STD_LOGIC_VECTOR (7 downto 0);
s_awsize : in STD_LOGIC_VECTOR (2 downto 0);
s_awburst : in STD_LOGIC_VECTOR (1 downto 0);
s_awvalid : in STD_LOGIC;
s_awready : out STD_LOGIC;
s_wdata : in STD_LOGIC_VECTOR (63 downto 0);
s_wstrb : in STD_LOGIC_VECTOR (7 downto 0);
s_wlast : in STD_LOGIC;
s_wvalid : in STD_LOGIC;
s_wready : out STD_LOGIC;
s_bresp : out STD_LOGIC_VECTOR (1 downto 0);
s_bvalid : out STD_LOGIC;
s_bready : in STD_LOGIC;
s_araddr : in STD_LOGIC_VECTOR (31 downto 0);
s_arlen : in STD_LOGIC_VECTOR (7 downto 0);
s_arsize : in STD_LOGIC_VECTOR (2 downto 0);
s_arburst : in STD_LOGIC_VECTOR (1 downto 0);
s_arvalid : in STD_LOGIC;
s_arready : out STD_LOGIC;
s_rdata : out STD_LOGIC_VECTOR (63 downto 0);
s_rresp : out STD_LOGIC_VECTOR (1 downto 0);
s_rlast : out STD_LOGIC;
s_rvalid : out STD_LOGIC;
s_rready : in STD_LOGIC;
-- AXI4-Lite master
m_awaddr : out STD_LOGIC_VECTOR (31 downto 0);
m_awvalid : out STD_LOGIC;
m_awready : in STD_LOGIC;
m_wdata : out STD_LOGIC_VECTOR (31 downto 0);
m_wstrb : out STD_LOGIC_VECTOR (3 downto 0);
m_wvalid : out STD_LOGIC;
m_wready : in STD_LOGIC;
m_bresp : in STD_LOGIC_VECTOR (1 downto 0);
m_bvalid : in STD_LOGIC;
m_bready : out STD_LOGIC;
m_araddr : out STD_LOGIC_VECTOR (31 downto 0);
m_arvalid : out STD_LOGIC;
m_arready : in STD_LOGIC;
m_rdata : in STD_LOGIC_VECTOR (31 downto 0);
m_rresp : in STD_LOGIC_VECTOR (1 downto 0);
m_rvalid : in STD_LOGIC;
m_rready : out STD_LOGIC
);
end axi4lite32_axi4full64_bridge;
architecture behav of axi4lite32_axi4full64_bridge is
constant RSP_OKAY : std_logic_vector(1 downto 0) := b"00";
constant RSP_EXOKAY : std_logic_vector(1 downto 0) := b"01";
constant RSP_SLVERR : std_logic_vector(1 downto 0) := b"10";
constant RSP_DECERR : std_logic_vector(1 downto 0) := b"11";
type t_wr_state is (WR_IDLE,
WR_MASTER, WR_SLAVE, WR_SLAVE2, WR_WAIT, WR_DONE);
type t_rd_state is (RD_IDLE, RD_READ, RD_SLAVE);
signal wstate : t_wr_state;
signal rstate : t_rd_state;
signal waddr : std_logic_vector(31 downto 0);
signal wlen : std_logic_vector(7 downto 0);
signal wsize : std_logic_vector(2 downto 0);
signal wdata : std_logic_vector(63 downto 0);
signal wstrb : std_logic_vector(7 downto 0);
signal raddr : std_logic_vector(31 downto 0);
signal rlen : std_logic_vector(7 downto 0);
signal rsize : std_logic_vector(2 downto 0);
signal rdata : std_logic_vector(63 downto 0);
begin
-- Write part.
m_awaddr <= waddr;
process (clk_i)
begin
if rising_edge (clk_i) then
if rst_n_i = '0' then
wstate <= WR_IDLE;
s_awready <= '1';
s_wready <= '0';
s_bvalid <= '0';
m_awvalid <= '0';
m_wvalid <= '0';
m_bready <= '0';
else
case wstate is
when WR_IDLE =>
-- Wait until awvalid is ready.
if s_awvalid = '1' then
-- Save transaction parameters
waddr <= s_awaddr;
wlen <= s_awlen;
wsize <= s_awsize;
-- Not anymore ready for addresses.
s_awready <= '0';
-- But ready for data.
s_wready <= '1';
wstate <= WR_MASTER;
end if;
when WR_MASTER =>
-- Clear wvalid when coming from WR_SLAVE.
m_wvalid <= '0';
if s_wvalid = '1' then
-- Got data from master.
wdata <= s_wdata;
wstrb <= s_wstrb;
s_wready <= '0';
-- Address cycle.
m_awvalid <= '1';
wstate <= WR_SLAVE;
end if;
when WR_SLAVE =>
if m_awready = '1' then
m_awvalid <= '0';
end if;
-- Prepare data write cycle.
if waddr (2) = '1' then
m_wdata <= wdata(63 downto 32);
m_wstrb <= wstrb(7 downto 4);
else
m_wdata <= wdata(31 downto 0);
m_wstrb <= wstrb(3 downto 0);
end if;
m_wvalid <= '1';
wstate <= WR_SLAVE2;
when WR_SLAVE2 =>
if m_awready = '1' then
m_awvalid <= '0';
end if;
if m_wready = '1' then
m_wvalid <= '0';
m_bready <= '1';
wstate <= WR_WAIT;
end if;
when WR_WAIT =>
-- End of transfer ?
if m_bvalid = '1' then
m_bready <= '0';
if waddr (2) = '1'
or (wsize (1 downto 0) = "10" and waddr (1) /= '1') -- 4 bytes
or (wsize (1 downto 0) = "01" and waddr (1 downto 0) /= "11")
or wsize (1 downto 0) = "00" -- 1 byte
then
if wlen = x"00" then
-- End of the burst.
s_bresp <= RSP_OKAY;
s_bvalid <= '1';
wstate <= WR_DONE;
else
wlen <= std_logic_vector(unsigned(wlen) - 1);
-- TODO: adjust address.
s_wready <= '1';
wstate <= WR_MASTER;
end if;
else
-- Next part of the data.
waddr (2) <= '1';
m_awvalid <= '1';
wstate <= WR_SLAVE;
end if;
end if;
when WR_DONE =>
if s_bready = '1' then
s_bvalid <= '0';
s_awready <= '1';
wstate <= WR_IDLE;
end if;
end case;
end if;
end if;
end process;
-- Read part.
m_araddr <= raddr;
s_rdata <= rdata;
process (clk_i)
begin
if rising_edge (clk_i) then
if rst_n_i = '0' then
rstate <= RD_IDLE;
s_arready <= '1';
s_rvalid <= '0';
s_rlast <= '0';
m_arvalid <= '0';
m_rready <= '0';
raddr <= (others => 'X');
rdata <= (others => '0');
else
case rstate is
when RD_IDLE =>
-- Wait until awvalid is ready.
if s_arvalid = '1' then
-- Save transaction parameters
raddr <= s_araddr;
rlen <= s_arlen;
rsize <= s_arsize;
-- Provide a clean result.
rdata <= (others => '0');
-- Not anymore ready for addresses.
s_arready <= '0';
-- Start transfer on the slave part.
m_arvalid <= '1';
m_rready <= '1';
rstate <= RD_READ;
end if;
when RD_READ =>
if m_arready = '1' then
m_arvalid <= '0';
end if;
if m_rvalid = '1' then
-- Read data. Address must have been acked.
-- According to A3.4.3 of AXI4 spec, the AXI4 bus is little
-- endian.
if raddr (2) = '1' then
rdata (63 downto 32) <= m_rdata;
else
rdata (31 downto 0) <= m_rdata;
end if;
-- End of transfer on the master ?
if raddr (2) = '1'
or (rsize (1 downto 0) = "10" and raddr (1) /= '1') -- 4 bytes
or (rsize (1 downto 0) = "01" and raddr (1 downto 0) /= "11")
or rsize (1 downto 0) = "00" -- 1 byte
then
-- To master.
rstate <= RD_SLAVE;
s_rresp <= RSP_OKAY;
if rlen = x"00" then
s_rlast <= '1';
else
s_rlast <= '0';
end if;
s_rvalid <= '1';
else
-- Next transfer.
raddr (2) <= '1';
m_arvalid <= '1';
m_rready <= '1';
end if;
end if;
when RD_SLAVE =>
if s_rready = '1' then
s_rvalid <= '0';
if rlen = x"00" then
-- End of the burst.
s_arready <= '1';
rstate <= RD_IDLE;
else
rlen <= std_logic_vector(unsigned(rlen) - 1);
-- TODO: adjust address.
-- New beat.
m_arvalid <= '1';
m_rready <= '1';
rstate <= RD_READ;
end if;
end if;
end case;
end if;
end if;
end process;
end behav;
......@@ -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",
......
--------------------------------------------------------------------------------
-- GSI
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: enc_8b10b
--
-- author(s): Mathias Kreider, Vladimir Cherkashyn
--
-- description: 8b/10b Encoder
-- This module provides 8bit-to-10bit encoding. It accepts 8-bit parallel
-- data input and generates 10-bit encoded data output in accordance with
-- the 8b/10b standard. IO latency is one clock cycle.
--
-- This approach uses a mix of LUTs and stacked ifs, unlike the suggested
-- approach that only used gates. This uses more logic cells, but also runs
-- about twice as fast. The reverse vector function is used because all code
-- tables are provided in literature as LSB first. This way, the sourcecode
-- is easier to compare.
--
--------------------------------------------------------------------------------
-- Copyright GSI 2009-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;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
entity gc_enc_8b10b is
generic
(
g_USE_INTERNAL_RUNNING_DISPARITY : boolean := TRUE);
port
(
clk_i : in std_logic; -- byte clock, trigger on rising edge
rst_n_i : in std_logic; -- reset, assert HI
ctrl_i : in std_logic; -- control char, assert HI
in_8b_i : in std_logic_vector(7 downto 0); -- 8bit input
err_o : out std_logic; -- HI if ctrl_i is HI and input is not a valid control byte
dispar_i : in std_logic := '0';
dispar_o : out std_logic; -- running disparity: HI = +1, LO = 0
out_10b_o : out std_logic_vector(9 downto 0) -- 10bit codeword output
);
end gc_enc_8b10b;
architecture rtl of gc_enc_8b10b is
--=============================================================================
-- LOOKUP TABLES
--=============================================================================
constant c_RD_MINUS : std_logic := '0';
constant c_RD_PLUS : std_logic := '1';
-- type for 5b/6b Code Table
type t_enc_5b_6b is array(integer range <>) of std_logic_vector(5 downto 0);
-- type for 5b/6b Code Table
type t_enc_3b_4b is array(integer range <>) of std_logic_vector(3 downto 0);
-- 5b/6b Code Table
constant c_ENC_5B_6B_TABLE : t_enc_5b_6b (0 to 31) :=
("100111", -- D00
"011101", -- D01
"101101", -- D02
"110001", -- D03
"110101", -- D04
"101001", -- D05
"011001", -- D06
"111000", -- D07
"111001", -- D08
"100101", -- D09
"010101", -- D10
"110100", -- D11
"001101", -- D12
"101100", -- D13
"011100", -- D14
"010111", -- D15
"011011", -- D16
"100011", -- D17
"010011", -- D18
"110010", -- D19
"001011", -- D20
"101010", -- D21
"011010", -- D22
"111010", -- D23
"110011", -- D24
"100110", -- D25
"010110", -- D26
"110110", -- D27
"001110", -- D28
"101110", -- D29
"011110", -- D30
"101011"); -- D31
-- 5b/6b Disparity Table
constant c_DISPAR_6B : std_logic_vector(0 to 31) :=
(
"11101000100000011000000110010111");
-- 3b/4b Code Table
constant c_ENC_3B_4B_TABLE : t_enc_3b_4b (0 to 7) :=
("1011", -- Dx0
"1001", -- Dx1
"0101", -- Dx2
"1100", -- Dx3
"1101", -- Dx4
"1010", -- Dx5
"0110", -- Dx6
"1110"); -- DxP7
-- 3b/4b Disparity Table
constant c_DISPAR_4B : std_logic_vector(0 to 7) :=
(
"10001001");
--=============================================================================
-- INTERNAL SIGNALS
--=============================================================================
signal s_ind5b : integer := 0; -- LUT 5b index
signal s_ind3b : integer := 0; -- LUT 3b index
signal s_val6bit : std_logic_vector(5 downto 0); -- 6bit code
signal s_val6bit_n : std_logic_vector(5 downto 0); -- 6bit code inverted
signal s_val4bit : std_logic_vector(3 downto 0); -- 4bit code
signal s_val4bit_n : std_logic_vector(3 downto 0); -- 4bit code inverted
-- code disparity 6b code: HI = uneven number of bits, LO = even, neutral disp
signal s_dP6bit : std_logic := '0';
-- code disparity 4b code: HI = uneven number of bits, LO = even, neutral disp
signal s_dP4bit : std_logic := '0';
-- output 10b signal buffer
signal s_out_10b, s_out_10b_reg : std_logic_vector(9 downto 0) := (others => '0');
signal s_in_8b_reg : std_logic_vector(7 downto 0); -- input 8b signal buffer
signal s_err, s_err_reg : std_logic; -- output err signal buffer
signal s_ctrl_reg : std_logic; -- output dispar, ctrl signal buffers
signal s_dpTrack : std_logic := c_RD_MINUS; -- current disparity: Hi = +1, LO = 0
signal s_RunDisp : std_logic; -- running disparity register
signal s_RunDisp_reg : std_logic; -- running disparity register
signal s_RunDisp_comb : std_logic; -- running disparity register
begin
s_RunDisp <= s_RunDisp_reg when g_USE_INTERNAL_RUNNING_DISPARITY else dispar_i;
dispar_o <= s_RunDisp_comb;
--=============================================================================
-- CONCURRENT COMMANDS
--=============================================================================
-- use 3bit at 7-5 as index for 4bit code and disparity table \n
s_ind3b <= to_integer(unsigned(s_in_8b_reg(7 downto 5)));
s_val4bit <= c_ENC_3B_4B_TABLE(s_ind3b);
s_dP4bit <= c_DISPAR_4B(s_ind3b);
s_val4bit_n <= not (s_val4bit);
-- use 5bit at 4-0 as index for 6bit code and disparity table
s_ind5b <= to_integer(unsigned(s_in_8b_reg(4 downto 0)));
s_val6bit <= c_ENC_5B_6B_TABLE(s_ind5b);
s_dP6bit <= c_DISPAR_6B(s_ind5b);
s_val6bit_n <= not (s_val6bit);
-- output wires
err_o <= s_err_reg;
out_10b_o <= s_out_10b_reg;
--=============================================================================
-- ENCODING
--=============================================================================
-- Process encodes 8bit value to 10bit codeword depending on current disparity
p_encoding : process (s_RunDisp, s_ctrl_reg, s_dP4bit, s_dP6bit, s_in_8b_reg,
s_val4bit, s_val4bit_n, s_val6bit, s_val6bit_n)
-- buffers ctrl code during selection
variable v_ctrl_code : std_logic_vector(9 downto 0) := (others => '0');
begin
v_ctrl_code := (others => '0');
s_err <= '0';
--========================================================================
-- TRANSMISSION CONTROL CODES
--========================================================================
if s_ctrl_reg = '1' then -- Control Char selected
-- control byte directly selects control code
case s_in_8b_reg is
when "00011100" => v_ctrl_code := f_reverse_vector("0011110100");
when "00111100" => v_ctrl_code := f_reverse_vector("0011111001");
when "01011100" => v_ctrl_code := f_reverse_vector("0011110101");
when "01111100" => v_ctrl_code := f_reverse_vector("0011110011");
when "10011100" => v_ctrl_code := f_reverse_vector("0011110010");
when "10111100" => v_ctrl_code := f_reverse_vector("0011111010");
when "11011100" => v_ctrl_code := f_reverse_vector("0011110110");
when "11111100" => v_ctrl_code := f_reverse_vector("0011111000");
when "11110111" => v_ctrl_code := f_reverse_vector("1110101000");
when "11111011" => v_ctrl_code := f_reverse_vector("1101101000");
when "11111101" => v_ctrl_code := f_reverse_vector("1011101000");
when "11111110" => v_ctrl_code := f_reverse_vector("0111101000");
when others => s_err <= '1';
end case;
-- select the right disparity and assign to output
if (s_RunDisp = c_RD_MINUS) then
s_out_10b <= v_ctrl_code;
else
s_out_10b <= not(v_ctrl_code);
end if;
else
--====================================================================
-- DATA CODES
--====================================================================
s_out_10b <= f_reverse_vector(s_val6bit & s_val4bit);
if s_RunDisp = c_RD_MINUS then
if s_dP4bit = s_dP6bit then
if s_dP6bit = '1' then
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
else
if s_dP4bit = '1' then
if ((s_val6bit(2 downto 0) = "011") and
(s_val4bit(3 downto 1) = "111")) then
s_out_10b(9 downto 6) <= "1110";
end if;
else
if (s_val4bit = "1100") then
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
end if;
end if;
else
if s_dP6bit = '1' then
s_out_10b(5 downto 0) <= f_reverse_vector(s_val6bit_n);
else
if (s_val6bit = "111000") then
s_out_10b(5 downto 0) <= f_reverse_vector(s_val6bit_n);
end if;
if s_dP4bit = '1' then
if ((s_val6bit(2 downto 0) = "100") and
(s_val4bit(3 downto 1) = "111")) then
s_out_10b(9 downto 6) <= "0001";
else
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
else
if (s_val4bit = "1100") then
s_out_10b(9 downto 6) <= f_reverse_vector(s_val4bit_n);
end if;
end if;
end if;
end if;
end if;
end process p_encoding;
p_disp_fsm_next : process(s_RunDisp, s_ctrl_reg, s_dP4bit, s_dP6bit,
s_in_8b_reg)
begin
s_RunDisp_comb <= s_RunDisp;
if s_RunDisp = c_RD_MINUS then
if (s_ctrl_reg xor s_dP6bit xor s_dP4bit) /= '0' then
s_RunDisp_comb <= c_RD_PLUS;
end if;
else -- RD_PLUS
if (s_ctrl_reg xor s_dP6bit xor s_dP4bit) /= '0' then
s_RunDisp_comb <= c_RD_MINUS;
end if;
end if;
if (s_in_8b_reg(1 downto 0) /= "00" and s_ctrl_reg = '1') then
s_RunDisp_comb <= s_RunDisp;
end if;
end process p_disp_fsm_next;
p_disp_fsm_seq : process(clk_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
s_RunDisp_reg <= c_RD_MINUS;
else
s_RunDisp_reg <= s_RunDisp_comb;
end if;
end if;
end process p_disp_fsm_seq;
s_ctrl_reg <= ctrl_i;
s_in_8b_reg <= in_8b_i;
p_inout_buffers : process(clk_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
s_err_reg <= '0';
s_out_10b_reg <= B"0000_000000";
else
s_err_reg <= s_err;
s_out_10b_reg <= s_out_10b;
end if;
end if;
end process p_inout_buffers;
end architecture rtl;
......@@ -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;
......
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// General Cores Library
// https://www.ohwr.org/projects/general-cores
//------------------------------------------------------------------------------
//
// Title : Software Wishbone master unit for testbenches
// unit name: IWishboneMaster
//
// File : if_wishbone.sv
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : SystemVerilog
// description: Software Wishbone master unit for testbenches.
//
/* Todo:
pipelined reads
settings wrapped in the accessor object
*/
//------------------------------------------------------------------------------
// Copyright CERN 2010-2019
//------------------------------------------------------------------------------
// 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.
//------------------------------------------------------------------------------
`include "simdrv_defs.svh"
`include "if_wishbone_types.svh"
......@@ -23,35 +32,24 @@ interface IWishboneMaster
input rst_n_i
);
parameter g_addr_width = 32;
parameter g_data_width = 32;
logic [g_addr_width - 1 : 0] adr;
logic [g_data_width - 1 : 0] dat_o;
logic [(g_data_width/8)-1 : 0] sel;
wire [g_data_width - 1 : 0] dat_i;
wire ack;
wire stall;
wire err;
wire rty;
logic cyc;
logic stb;
logic we;
wire clk;
wire rst_n;
time last_access_t = 0;
parameter g_addr_width = 32;
parameter g_data_width = 32;
struct {
int gen_random_throttling;
real throttle_prob;
int little_endian;
int cyc_on_stall;
wb_address_granularity_t addr_gran;
} settings;
logic [g_addr_width - 1 : 0] adr;
logic [g_data_width - 1 : 0] dat_o;
logic [(g_data_width/8)-1 : 0] sel;
wire [g_data_width - 1 : 0] dat_i;
wire ack;
wire stall;
wire err;
wire rty;
logic cyc;
logic stb;
logic we;
modport master
wire stall_valid = stall & cyc;
modport master
(
output adr,
output dat_o,
......@@ -59,316 +57,246 @@ interface IWishboneMaster
output cyc,
output stb,
output we,
input ack,
input dat_i,
input stall,
input err,
input rty
input ack,
input dat_i,
input stall,
input err,
input rty
);
function automatic logic[g_addr_width-1:0] gen_addr(uint64_t addr, int xfer_size);
if(settings.addr_gran == WORD)
case(g_data_width)
8: return addr;
16: return addr >> 1;
32: return addr >> 2;
64: return addr >> 3;
default: $error("IWishbone: invalid WB data bus width [%d bits\n]", g_data_width);
endcase // case (xfer_size)
else
return addr;
endfunction
time last_access_t = 0;
enum {
IDLE,
BUSY,
WAIT_ACK
} xf_state;
wb_cycle_t request_queue[$];
wb_cycle_t result_queue[$];
struct {
int gen_random_throttling;
real throttle_prob;
int little_endian; // not supported
int cyc_on_stall; // not used, kept for compatibility
wb_address_granularity_t addr_gran;
} settings;
function automatic logic[63:0] rev_bits(logic [63:0] x, int nbits);
logic[63:0] tmp;
int i;
for (i=0;i<nbits;i++)
tmp[nbits-1-i] = x[i];
for (i = 0; i < nbits; i++)
tmp[nbits-1-i] = x[i];
return tmp;
endfunction // rev_bits
function automatic logic[g_addr_width-1:0] gen_addr(wb_xfer_t xfer);
if (settings.addr_gran == WORD)
case (g_data_width)
8: return xfer.a;
16: return xfer.a >> 1;
32: return xfer.a >> 2;
64: return xfer.a >> 3;
default: $error("IWishbone: invalid WB data bus width [%d bits\n]", g_data_width);
endcase
else
return xfer.a;
endfunction // gen_addr
//FIXME: little endian
function automatic logic[(g_data_width/8)-1:0] gen_sel(uint64_t addr, int xfer_size, int little_endian);
function automatic logic[(g_data_width/8)-1:0] gen_sel(wb_xfer_t xfer);
logic [(g_data_width/8)-1:0] sel;
const int dbytes = (g_data_width/8-1);
sel = ((1<<xfer_size) - 1);
return rev_bits(sel << (addr % xfer_size), g_data_width/8);
endfunction
sel = ((1 << xfer.size) - 1);
return rev_bits(sel << (xfer.a % xfer.size), g_data_width/8);
endfunction // gen_sel
function automatic logic[g_data_width-1:0] gen_data(uint64_t addr, uint64_t data, int xfer_size, int little_endian);
//FIXME: little endian
function automatic logic[g_data_width-1:0] gen_data(wb_xfer_t xfer);
const int dbytes = (g_data_width/8-1);
logic[g_data_width-1:0] tmp;
tmp = data << (8 * (dbytes - (xfer_size - 1 - (addr % xfer_size))));
// $display("GenData: xs %d dbytes %d %x", tmp, xfer_size, dbytes);
return tmp;
return xfer.d << (8 * (dbytes - (xfer.size - 1 - (xfer.a % xfer.size))));
endfunction // gen_data
function automatic uint64_t decode_data(uint64_t addr, logic[g_data_width-1:0] data, int xfer_size);
function automatic uint64_t decode_data(wb_xfer_t xfer, logic[g_data_width-1:0] data);
int rem;
// $display("decode: a %x d %x xs %x", addr, data ,xfer_size);
rem = xfer.a % xfer.size;
rem = addr % xfer_size;
return (data >> (8*rem)) & ((1<<(xfer_size*8)) - 1);
return (data >> (8 * rem)) & ((1 << (xfer.size * 8)) - 1);
endfunction // decode_data
task automatic classic_cycle
(
inout wb_xfer_t xfer[],
input bit rw,
input int n_xfers,
output wb_cycle_result_t result
);
int i;
if($time != last_access_t)
@(posedge clk_i); /* resynchronize, just in case */
for(i=0;i<n_xfers;i++)
begin
stb <= 1'b1;
cyc <= 1'b1;
adr <= gen_addr(xfer[i].a, xfer[i].size);
we <= rw;
sel <= gen_sel(xfer[i].a, xfer[i].size, settings.little_endian);
//gen_sel(xfer[i].a, xfer[i].size);
dat_o <= gen_data(xfer[i].a, xfer[i].d, xfer[i].size, settings.little_endian);
@(posedge clk_i);
if(ack == 0) begin
while(ack == 0) begin @(posedge clk_i); end
end else if(err == 1'b1 || rty == 1'b1)
begin
cyc <= 0;
we <= 0;
stb <= 0;
result = (err ==1'b1 ? R_ERROR: R_RETRY);
break;
end
xfer[i].d = decode_data(xfer[i].a, dat_i, xfer[i].size);
cyc <= 0;
we <= 0;
stb <= 0;
end // if (ack == 0)
@(posedge clk_i);
result = R_OK;
last_access_t = $time;
endtask // automatic
task automatic classic_cycle(ref wb_cycle_t c);
reg xf_idle = 1;
int i;
int ack_cnt_int;
int failure = 0;
/* resynchronize, just in case */
if ($time != last_access_t) @(posedge clk_i);
xf_state = BUSY;
for (i = 0; i < c.data.size(); i++) begin
stb <= 1'b1;
cyc <= 1'b1;
adr <= gen_addr(c.data[i]);
we <= (c.rw != 0);
sel <= gen_sel(c.data[i]);
dat_o <= gen_data(c.data[i]);
@(posedge clk_i);
while (ack != 1'b1 && err != 1'b1 && rty == 1'b1) @(posedge clk_i);
if (err || rty) begin
c.result = (err ? R_ERROR: R_RETRY);
failure = 1;
break;
end
c.data[i].d = decode_data(c.data[i], dat_i);
cyc <= 0;
we <= 0;
stb <= 0;
@(posedge clk_i);
end
if (!failure)
c.result = R_OK;
xf_state = IDLE;
last_access_t = $time;
endtask // classic_cycle
task automatic pipelined_cycle(ref wb_cycle_t c);
int stb_count = 0;
int ack_count = 0;
int failure = 0;
int cur_rdbk = 0;
/* resynchronize, just in case */
if ($time != last_access_t) @(posedge clk_i);
xf_state = BUSY;
cyc <= 1'b1;
stb <= 1'b1;
adr <= gen_addr(c.data[stb_count]);
if (c.rw == 1) begin
we <= 1'b1;
sel <= gen_sel(c.data[stb_count]);
dat_o <= gen_data(c.data[stb_count]);
end
else begin
we <= 1'b0;
sel <= 'hffffffff;
end
while (stall_valid || ((stb_count < c.data.size()) && !failure)) begin
if (ack) begin
ack_count++;
if (c.rw == 0) begin
c.data[cur_rdbk].d = dat_i;
cur_rdbk++;
end
end
else if (err || rty) begin
c.result = (err ? R_ERROR: R_RETRY);
failure = 1;
break;
end
if (settings.gen_random_throttling &&
probability_hit(settings.throttle_prob)) begin
stb <= 1'b0;
we <= 1'b0;
end
else if (stall_valid == 1'b0) begin
stb <= 1'b1;
adr <= gen_addr(c.data[stb_count]);
if (c.rw == 1) begin
we <= 1'b1;
sel <= gen_sel(c.data[stb_count]);
dat_o <= gen_data(c.data[stb_count]);
end
else begin
we <= 1'b0;
sel <= 'hffffffff;
end
stb_count++;
end
@(posedge clk_i);
end
stb <= 1'b0;
we <= 1'b0;
xf_state = WAIT_ACK;
while ((ack_count < c.data.size()) && !failure) begin
if (ack) begin
ack_count++;
if (c.rw == 0) begin
c.data[cur_rdbk].d = dat_i;
cur_rdbk++;
end
end
else if (err || rty) begin
c.result = (err ? R_ERROR: R_RETRY);
failure = 1;
xf_state = IDLE;
break;
end
if (ack_count == c.data.size()) begin
cyc <= 1'b0;
we <= 1'b0;
xf_state = IDLE;
end
@(posedge clk_i);
end
always@(posedge clk_i)
begin
if(!cyc)
ack_cnt_int <= 0;
else if(stb && !stall && !ack)
ack_cnt_int++;
else if((!stb || stall) && ack)
ack_cnt_int--;
end
task automatic count_ack(ref int ack_cnt);
// if(stb && !stall && !ack)
// ack_cnt++;
if (ack)
ack_cnt--;
endtask
task automatic handle_readback(ref wb_xfer_t xf [$], input int read, ref int cur_rdbk);
if(ack && read)
begin
xf[cur_rdbk].d = dat_i;
cur_rdbk++;
end
endtask // handle_readback
task automatic pipelined_cycle
(
ref wb_xfer_t xfer[$],
input int write,
input int n_xfers,
output wb_cycle_result_t result
);
int i;
int ack_count ;
int failure ;
int cur_rdbk;
ack_count = 0;
failure = 0;
xf_idle = 0;
cur_rdbk = 0;
if($time != last_access_t)
@(posedge clk_i); /* resynchronize, just in case */
while(stall && !settings.cyc_on_stall)
@(posedge clk_i);
cyc <= 1'b1;
i =0;
ack_count = n_xfers;
while(i<n_xfers)
begin
count_ack(ack_count);
handle_readback(xfer, !write, cur_rdbk);
if(err) begin
result = R_ERROR;
failure = 1;
break;
end
if(rty) begin
result = R_RETRY;
failure = 1;
break;
end
if (!stall && settings.gen_random_throttling && probability_hit(settings.throttle_prob)) begin
stb <= 1'b0;
we <= 1'b0;
@(posedge clk_i);
end else begin
adr <= gen_addr(xfer[i].a, xfer[i].size);
stb <= 1'b1;
if(write)
begin
we <= 1'b1;
sel <= gen_sel(xfer[i].a, xfer[i].size, settings.little_endian);
dat_o <= gen_data(xfer[i].a, xfer[i].d, xfer[i].size, settings.little_endian);
end else begin
we<=1'b0;
sel <= 'hffffffff;
end
@(posedge clk_i);
stb <= 1'b0;
we <= 1'b0;
if(stall)
begin
stb <= 1'b1;
if(write)
we <= 1'b1;
while(stall)
begin
count_ack(ack_count);
@(posedge clk_i);
end
stb <= 1'b0;
we <= 1'b0;
end
i++;
end
end // for (i =0;i<n_xfers;i++)
while((ack_count > 0) && !failure)
begin
// $display("AckCount %d", ack_count);
if(err) begin
result = R_ERROR;
failure = 1;
break;
end
if(rty) begin
result = R_RETRY;
failure = 1;
break;
end
count_ack(ack_count);
handle_readback(xfer, !write, cur_rdbk);
if(stb && !ack)
ack_count++;
else if(!stb && ack)
ack_count--;
@(posedge clk_i);
end
cyc <= 1'b0;
@(posedge clk_i);
if(!failure)
result = R_OK;
xf_idle = 1;
last_access_t = $time;
endtask // automatic
we <= 1'b0;
wb_cycle_t request_queue[$];
wb_cycle_t result_queue[$];
if (!failure)
c.result = R_OK;
last_access_t = $time;
endtask // pipelined_cycle
class CIWBMasterAccessor extends CWishboneAccessor;
function automatic int poll();
return 0;
endfunction
endfunction // poll
task get(ref wb_cycle_t xfer);
while(!result_queue.size())
@(posedge clk_i);
xfer = result_queue.pop_front();
endtask
task clear();
endtask // clear
@(posedge clk_i);
xfer = result_queue.pop_front();
endtask // get
task put(ref wb_cycle_t xfer);
request_queue.push_back(xfer);
endtask // put
function int idle();
return (request_queue.size() == 0) && xf_idle;
return (request_queue.size() == 0) && (xf_state == IDLE);
endfunction // idle
endclass // CIWBMasterAccessor
endclass // CIWBMasterAccessor
function automatic CIWBMasterAccessor get_accessor();
automatic CIWBMasterAccessor tmp;
......@@ -376,63 +304,44 @@ endclass // CIWBMasterAccessor
return tmp;
endfunction // get_accessor
always@(posedge clk_i)
if(!rst_n_i)
begin
request_queue = {};
result_queue = {};
xf_idle = 1;
cyc <= 0;
dat_o <= 0;
stb <= 0;
sel <= 0;
adr <= 0;
we <= 0;
end
if (!rst_n_i) begin
request_queue = {};
result_queue = {};
xf_state = IDLE;
cyc <= 0;
dat_o <= 0;
stb <= 0;
sel <= 0;
adr <= 0;
we <= 0;
end
initial begin
settings.gen_random_throttling = 0;
settings.throttle_prob = 0.1;
settings.cyc_on_stall = 0;
settings.addr_gran = WORD;
settings.throttle_prob = 0.1;
settings.addr_gran = WORD;
end
initial forever begin
@(posedge clk_i);
if (request_queue.size() > 0) begin
wb_cycle_t c;
c = request_queue.pop_front();
case(c.ctype)
PIPELINED:
pipelined_cycle(c);
CLASSIC:
classic_cycle(c);
endcase
result_queue.push_back(c);
end
end
initial forever
begin
@(posedge clk_i);
if(request_queue.size() > 0)
begin
wb_cycle_t c;
wb_cycle_result_t res;
c = request_queue.pop_front();
case(c.ctype)
PIPELINED:
begin
pipelined_cycle(c.data, c.rw, c.data.size(), res);
c.result =res;
end
CLASSIC:
begin
// $display("WBMaster: got classic cycle [%d, rw %d]", c.data.size(), c.rw);
classic_cycle(c.data, c.rw, c.data.size, res);
c.result =res;
end
endcase // case (c.ctype)
result_queue.push_back(c);
end
end
endinterface // IWishbone
endinterface // IWishboneMaster
......@@ -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