Commit 258eb8e0 authored by Dimitris Lampridis's avatar Dimitris Lampridis

Merge branch 'release/1.1.0'

parents 63f36713 3a61c9d7
......@@ -9,6 +9,30 @@ Change Log
- 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.1.0 - 2020-07-24
==================
https://www.ohwr.org/project/general-cores/tags/v1.1.0
Added
-----
- hdl: New indirect wishbone master (driven by an address and data register).
- hdl: New memory wrapper for Cheby.
- hdl: Provide a simple vhdl package to generate WB transactions.
- hdl: New wb_xc7_fw_update module.
- bld: Introduce gen_sourceid.py script to generate a package with the source id.
Changed
-------
- bld: gen_buildinfo.py now adds tag and dirty flag.
Fixed
-----
- hdl: regression to gc_sync_ffs introduced by v1.0.4.
- hdl: add dummy generic to generic_dpram in altera.
- hdl: add missing generics to generic_sync_fifo in genram_pkg.
- hdl: avoid f_log2() circular dependencies in gc_extend_pulse.
1.0.4 - 2020-03-26
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.4
......
......@@ -13,8 +13,9 @@ 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).
* Edge detectors are provided by [gc_posedge](modules/common/gc_posedge.vhd),
[gc_negedge](modules/common/gc_negedge.vhd), and
[gc_edge_detect](modules/common/gc_edge_detect.vhd).
* For clock-domain crossing or asynchronous signal register, use
[gc_sync](modules/common/gc_sync.vhd). This is the basic synchronizer.
......@@ -195,6 +196,8 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
- [wb_vic](modules/wishbone/wb_vic) is the vectored interrupt controller.
- [wb_ds182x_readout](modules/wishbone/wb_ds182x_readout) is a direct
interface to the digital thermometer.
- [wb_xc7_fw_update](modules/wishbone/wb_xc7_fw_update) is an SPI interface
to drive the xc7 bitstream spi flash (using the ht-flash tool).
* There are utilities to handle a wishbone bus:
- [wb_clock_crossing](modules/wishbone/wb_clock_crossing) handle clock domain
......@@ -228,3 +231,5 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
superseeded by the crossbar.
- [wb_metadata](modules/wishbone/wb_metadata) is a little helper to
create metadata for the convention.
- [wb_indirect](modules/wishbone/wb_indirect) provides a wishbone
master driven by an address and a data registers.
......@@ -15,7 +15,7 @@ files = [
"gc_sync.vhd",
"gc_posedge.vhd",
"gc_negedge.vhd",
"gc_sync_edge.vhd",
"gc_edge_detect.vhd",
"gc_pulse_synchronizer.vhd",
"gc_pulse_synchronizer2.vhd",
"gc_frequency_meter.vhd",
......@@ -24,6 +24,7 @@ files = [
"gc_prio_encoder.vhd",
"gc_word_packer.vhd",
"gc_i2c_slave.vhd",
"gc_simple_spi_master.vhd",
"gc_glitch_filt.vhd",
"gc_dyn_glitch_filt.vhd",
"gc_comparator.vhd",
......
......@@ -4,13 +4,12 @@
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_sync_edge
-- unit name: gc_edge_detect
--
-- description: Synchronizer chain and edge detector.
-- All the registers in the chain are cleared at reset.
-- description: Simple edge detector. Combinatorial.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2010-2018
-- 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
......@@ -26,45 +25,93 @@
library ieee;
use ieee.std_logic_1164.all;
entity gc_sync_edge is
entity gc_edge_detect is
generic(
g_edge : string := "positive");
g_ASYNC_RST : boolean := FALSE;
-- Positive/negative edge detection for pulse_o output.
-- Valid values are "positive" and "negative".
g_PULSE_EDGE : string := "positive";
-- Clock edge sensitivity of edge detection flip-flop.
-- Valid values are "positive" and "negative".
g_CLOCK_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;
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_edge_detect;
architecture arch of gc_edge_detect is
signal dff : 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;
assert g_PULSE_EDGE = "positive" or g_PULSE_EDGE = "negative" severity FAILURE;
assert g_CLOCK_EDGE = "positive" or g_CLOCK_EDGE = "negative" severity FAILURE;
gen_pos_pulse : if g_PULSE_EDGE = "positive" generate
pulse_o <= data_i and not dff;
end generate gen_pos_pulse;
gen_neg_pulse : if g_PULSE_EDGE = "negative" generate
pulse_o <= not data_i and dff;
end generate gen_neg_pulse;
gen_async_rst : if g_ASYNC_RST = TRUE generate
sync_posedge : if g_CLOCK_EDGE = "positive" generate
process (clk_i, rst_n_i)
begin
if rst_n_i = '0' then
dff <= '0';
elsif rising_edge (clk_i) then
dff <= data_i;
end if;
end process;
end generate sync_posedge;
sync_negedge : if g_CLOCK_EDGE = "negative" generate
process (clk_i, rst_n_i)
begin
if rst_n_i = '0' then
dff <= '0';
elsif falling_edge (clk_i) then
dff <= data_i;
end if;
end process;
end generate sync_negedge;
end generate gen_async_rst;
gen_sync_rst : if g_ASYNC_RST = FALSE generate
sync_posedge : if g_CLOCK_EDGE = "positive" generate
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 generate sync_posedge;
sync_negedge : if g_CLOCK_EDGE = "negative" generate
process (clk_i)
begin
if falling_edge (clk_i) then
if rst_n_i = '0' then
dff <= '0';
else
dff <= data_i;
end if;
end if;
end process;
end generate sync_negedge;
end generate gen_sync_rst;
end architecture arch;
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2009-09-01
-- Last update: 2012-06-19
-- Last update: 2020-03-30
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
......@@ -41,7 +41,6 @@ use ieee.NUMERIC_STD.all;
library work;
use work.gencores_pkg.all;
use work.genram_pkg.all;
entity gc_extend_pulse is
......@@ -60,7 +59,7 @@ end gc_extend_pulse;
architecture rtl of gc_extend_pulse is
signal cntr : unsigned(f_log2_size(g_width)-1 downto 0);
signal cntr : unsigned(f_log2_ceil(g_width)-1 downto 0);
signal extended_int : std_logic;
begin -- rtl
......
......@@ -26,6 +26,11 @@ library ieee;
use ieee.std_logic_1164.all;
entity gc_negedge is
generic(
g_ASYNC_RST : boolean := FALSE;
-- Clock edge sensitivity of edge detection flip-flop.
-- Valid values are "positive" and "negative".
g_CLOCK_EDGE : string := "positive");
port(
clk_i : in std_logic; -- clock
rst_n_i : in std_logic; -- reset
......@@ -34,18 +39,18 @@ entity gc_negedge is
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;
inst_gc_edge_detect : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => g_ASYNC_RST,
g_PULSE_EDGE => "negative",
g_CLOCK_EDGE => g_CLOCK_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => data_i,
pulse_o => pulse_o);
end architecture arch;
......@@ -26,6 +26,11 @@ library ieee;
use ieee.std_logic_1164.all;
entity gc_posedge is
generic(
g_ASYNC_RST : boolean := FALSE;
-- Clock edge sensitivity of edge detection flip-flop.
-- Valid values are "positive" and "negative".
g_CLOCK_EDGE : string := "positive");
port(
clk_i : in std_logic; -- clock
rst_n_i : in std_logic; -- reset
......@@ -34,18 +39,18 @@ entity gc_posedge is
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;
inst_gc_edge_detect : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => g_ASYNC_RST,
g_PULSE_EDGE => "positive",
g_CLOCK_EDGE => g_CLOCK_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => data_i,
pulse_o => pulse_o);
end architecture arch;
......@@ -40,9 +40,10 @@ entity gc_pulse_synchronizer2 is
-- pulse input ready (clk_in_i domain). When HI, a pulse
-- coming to d_p_i will be correctly transferred to q_p_o.
d_ready_o : out std_logic;
-- last pulse input acknowledged. This is an alternative
-- status flag to d_ready_o for applications that work better
-- with a pulsed ACK instead of a "ready" flag.
-- last pulse input acknowledged (clk_in_i domain).
-- This is an alternative status flag to d_ready_o for
-- applications that work better with a pulsed ACK
-- instead of a "ready" flag.
d_ack_p_o : out std_logic;
-- pulse input (clk_in_i domain)
d_p_i : in std_logic;
......@@ -63,23 +64,27 @@ architecture rtl of gc_pulse_synchronizer2 is
begin -- rtl
cmp_in2out_sync : gc_sync_ffs
cmp_in2out_sync : gc_sync
port map (
clk_i => clk_out_i,
rst_n_i => rst_out_n_i,
data_i => in_ext,
synced_o => out_ext,
npulse_o => open,
ppulse_o => q_p_o);
cmp_out2in_sync : gc_sync_ffs
clk_i => clk_out_i,
rst_n_a_i => rst_out_n_i,
d_i => in_ext,
q_o => out_ext);
cmp_pulse_out : gc_edge_detect
port map (
clk_i => clk_out_i,
rst_n_i => rst_out_n_i,
data_i => out_ext,
pulse_o => q_p_o);
cmp_out2in_sync : gc_sync
port map (
clk_i => clk_in_i,
rst_n_i => rst_in_n_i,
data_i => out_ext,
synced_o => out_feedback,
npulse_o => open,
ppulse_o => open);
clk_i => clk_in_i,
rst_n_a_i => rst_in_n_i,
d_i => out_ext,
q_o => out_feedback);
p_input_ack : process(clk_in_i)
begin
......
-----------------------------------------------------------------------------
-- Title : SPI Bus Master
-- Project : Simple VME64x FMC Carrier (SVEC)
-------------------------------------------------------------------------------
-- File : gc_simple_spi_master.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2013-01-25
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Just a simple SPI master (bus-less).
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011-2013 CERN / BE-CO-HT
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gc_simple_spi_master is
generic(
-- clock division ratio (SCLK = clk_sys_i / (2 ** g_div_ratio_log2).
g_div_ratio_log2 : integer := 2;
-- number of data bits per transfer
g_num_data_bits : integer := 2);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- state of the Chip select line (1 = CS active). External control
-- allows for multi-transfer commands (SPI master itself does not
-- control the state of spi_cs_n_o)
cs_i : in std_logic;
-- 1: start next transfer (using CPOL, DATA and SEL from the inputs below)
start_i : in std_logic;
-- Clock polarity: 1: slave clocks in the data on rising SCLK edge, 0: ...
-- on falling SCLK edge
cpol_i : in std_logic;
-- TX Data input
data_i : in std_logic_vector(g_num_data_bits - 1 downto 0);
-- 1: data_o contains the result of last read operation. Core is ready to initiate
-- another transfer.
ready_o : out std_logic;
-- data read from selected slave, valid when ready_o == 1.
data_o : out std_logic_vector(g_num_data_bits - 1 downto 0);
-- these are obvious
spi_cs_n_o : out std_logic;
spi_sclk_o : out std_logic;
spi_mosi_o : out std_logic;
spi_miso_i : in std_logic
);
end gc_simple_spi_master;
architecture behavioral of gc_simple_spi_master is
signal divider : unsigned(11 downto 0);
signal tick : std_logic;
signal sreg : std_logic_vector(g_num_data_bits-1 downto 0);
signal rx_sreg : std_logic_vector(g_num_data_bits-1 downto 0);
type t_state is (IDLE, TX_CS, TX_DAT1, TX_DAT2, TX_SCK1, TX_SCK2, TX_CS2, TX_GAP);
signal state : t_state;
signal sclk : std_logic;
signal counter : unsigned(4 downto 0);
begin -- rtl
-- Simple clock divder. Produces a 'tick' signal which defines the timing for
-- the main state machine transitions.
p_divide_spi_clock: process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
divider <= (others => '0');
else
if(start_i = '1' or tick = '1') then
divider <= (others => '0');
else
divider <= divider + 1;
end if;
end if;
end if;
end process;
tick <= divider(g_div_ratio_log2);
-- Main state machine. Executes SPI transfers
p_main_fsm: process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
state <= IDLE;
sclk <= '0';
sreg <= (others => '0');
rx_sreg <= (others => '0');
spi_mosi_o <= '0';
counter <= (others => '0');
else
case state is
-- Waits for start of transfer command
when IDLE =>
sclk <= '0';
counter <= (others => '0');
if(start_i = '1') then
sreg <= data_i;
state <= TX_CS;
spi_mosi_o <= data_i(sreg'high);
end if;
-- Generates a gap between the externally asserted Chip Select and
-- the beginning of data transfer
when TX_CS =>
if tick = '1' then
state <= TX_DAT1;
end if;
-- Outputs subsequent bits to MOSI line.
when TX_DAT1 =>
if(tick = '1') then
spi_mosi_o <= sreg(sreg'high);
sreg <= sreg(sreg'high-1 downto 0) & '0';
state <= TX_SCK1;
end if;
-- Flips the SCLK (active edge)
when TX_SCK1 =>
if(tick = '1') then
sclk <= not sclk;
counter <= counter + 1;
state <= TX_DAT2;
end if;
-- Shifts in bits read from the slave
when TX_DAT2 =>
if(tick = '1') then
rx_sreg <= rx_sreg(rx_sreg'high-1 downto 0) & spi_miso_i;
state <= TX_SCK2;
end if;
-- Flips the SCLK (inactive edge). Checks if all bits have been
-- transferred.
when TX_SCK2 =>
if(tick = '1') then
sclk <= not sclk;
if(counter = g_num_data_bits) then
state <= TX_CS2;
else
state <= TX_DAT1;
end if;
end if;
-- Generates a gap for de-assertoin of CS line
when TX_CS2 =>
if(tick = '1') then
state <= TX_GAP;
data_o <= rx_sreg;
end if;
when TX_GAP =>
if (tick = '1') then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
ready_o <= '1' when (state = IDLE and start_i = '0') else '0';
-- SCLK polarity control
spi_sclk_o <= sclk xor cpol_i;
spi_cs_n_o <= not cs_i;
end behavioral;
......@@ -9,7 +9,7 @@
-- description: Elementary synchronizer chain using two flip-flops.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2014-2018
-- Copyright CERN 2014-2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
......@@ -27,7 +27,8 @@ use ieee.std_logic_1164.all;
entity gc_sync is
generic(
g_sync_edge : string := "positive");
-- valid values are "positive" and "negative"
g_SYNC_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_a_i : in std_logic;
......@@ -69,11 +70,11 @@ architecture arch of gc_sync is
begin
assert g_sync_edge = "positive" or g_sync_edge = "negative" severity failure;
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
sync_posedge : if (g_SYNC_EDGE = "positive") generate
process(clk_i, rst_n_a_i)
begin
if rst_n_a_i = '0' then
......@@ -86,7 +87,7 @@ begin
end process;
end generate sync_posedge;
sync_negedge : if(g_sync_edge = "negative") generate
sync_negedge : if(g_SYNC_EDGE = "negative") generate
process(clk_i, rst_n_a_i)
begin
if rst_n_a_i = '0' then
......
......@@ -10,7 +10,7 @@
-- All the registers in the chain are cleared at reset.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2010-2018
-- Copyright CERN 2010-2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
......@@ -28,7 +28,8 @@ use ieee.std_logic_1164.all;
entity gc_sync_ffs is
generic(
g_sync_edge : string := "positive");
-- valid values are "positive" and "negative"
g_SYNC_EDGE : string := "positive");
port(
clk_i : in std_logic; -- clock from the destination clock domain
rst_n_i : in std_logic; -- async reset
......@@ -46,28 +47,36 @@ begin
cmp_gc_sync : entity work.gc_sync
generic map (
g_sync_edge => g_sync_edge)
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
cmp_gc_posedge : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => TRUE,
g_PULSE_EDGE => "positive",
g_CLOCK_EDGE => g_SYNC_EDGE)
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
cmp_gc_negedge : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => TRUE,
g_PULSE_EDGE => "negative",
g_CLOCK_EDGE => g_SYNC_EDGE)
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
sync_posedge : if (g_SYNC_EDGE = "positive") generate
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
......@@ -82,7 +91,7 @@ begin
end process;
end generate sync_posedge;
sync_negedge : if(g_sync_edge = "negative") generate
sync_negedge : if(g_SYNC_EDGE = "negative") generate
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
......
......@@ -37,7 +37,7 @@ use work.gencores_pkg.all;
entity gc_sync_word_wr is
generic (
-- automatically write next word when not busy
-- Automatically write next word when not busy.
g_AUTO_WR : boolean := FALSE;
g_WIDTH : positive := 8);
port (
......@@ -47,16 +47,18 @@ entity gc_sync_word_wr is
-- Output clock and reset
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
-- Input data
-- Input data (from clk_in_i domain)
data_i : in std_logic_vector (g_WIDTH - 1 downto 0);
-- Input control and status
-- Input control (from clk_in_i domain)
-- wr_i is ignored if g_AUTO_WR is set
wr_i : in std_logic := '0';
-- Transfer in progress (clk_in_i domain).
busy_o : out std_logic;
-- Input wr_i has been used (clk_in_i domain).
ack_o : out std_logic;
-- Output data
data_o : out std_logic_vector (g_WIDTH - 1 downto 0);
-- Output status
-- Output status. Pulse set when the data has been transfered (clk_out_i domain).
wr_o : out std_logic);
end entity;
......
......@@ -238,7 +238,7 @@ package gencores_pkg is
------------------------------------------------------------------------------
component gc_sync_ffs
generic (
g_sync_edge : string := "positive");
g_SYNC_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
......@@ -246,33 +246,37 @@ package gencores_pkg is
synced_o : out std_logic;
npulse_o : out std_logic;
ppulse_o : out std_logic);
end component;
end component gc_sync_ffs;
component gc_sync is
generic (
g_sync_edge : string := "positive");
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);
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_edge_detect is
generic (
g_ASYNC_RST : boolean := FALSE;
g_PULSE_EDGE : string := "positive";
g_CLOCK_EDGE : string := "positive");
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_edge_detect;
component gc_negedge is
generic (
g_ASYNC_RST : boolean := FALSE;
g_CLOCK_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
......@@ -281,6 +285,9 @@ package gencores_pkg is
end component gc_negedge;
component gc_posedge is
generic (
g_ASYNC_RST : boolean := FALSE;
g_CLOCK_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
......
files = [
"genram_pkg.vhd",
"memory_loader_pkg.vhd"];
# Be sure 'target' is defined.
try:
target
except NameError:
target = ""
if (target == "altera"):
modules = {"local" : ["altera", "generic", "common"]}
elif (target == "xilinx" and syn_device[0:4].upper()=="XC6V"):
modules = {"local" : ["xilinx", "xilinx/virtex6", "common"]}
elif (target == "xilinx"):
modules = {"local" : ["xilinx", "generic", "common"]}
# Target specific modules.
if target == "altera":
modules = {"local": ["altera", "generic"]}
elif target == "xilinx":
if syn_device[0:4].upper()=="XC6V":
modules = {"local": ["xilinx", "xilinx/virtex6"]}
else:
modules = {"local": ["xilinx", "generic"]}
else:
modules = {"local" : ["generic", "common"]}
modules = {"local" : ["generic"]}
modules["local"].extend(["common", "cheby"])
......@@ -43,6 +43,7 @@ entity generic_dpram is
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_fail_if_file_not_found : boolean := true; -- dummy (exists in Xilinx/generic)
g_dual_clock : boolean := true);
port(
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
......
files = [
"cheby_pkg.vhd",
"cheby_dpssram.vhd"
]
-------------------------------------------------------------------------------
-- Title : Cheby components
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : cheby_dpssram.vhd
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Copyright (c) 2020 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;
-- This entity is instantiated by cheby when a dual-port RAM is used.
-- This is just a wrapper that could be changed by users.
-- The generics only use integers/logic to be compatible with verilog.
entity cheby_dpssram is
generic (
g_data_width : natural := 32;
g_size : natural := 1024;
g_addr_width : natural := 10;
g_dual_clock : std_logic := '1';
g_use_bwsel : std_logic := '1');
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic
);
end cheby_dpssram;
architecture syn of cheby_dpssram is
begin
wrapped_dpram: entity work.generic_dpram
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_with_byte_enable => g_use_bwsel = '1',
g_dual_clock => g_dual_clock = '1')
port map (
rst_n_i => '1',
clka_i => clk_a_i,
bwea_i => bwsel_a_i,
wea_i => wr_a_i,
aa_i => addr_a_i,
da_i => data_a_i,
qa_o => data_a_o,
clkb_i => clk_b_i,
bweb_i => bwsel_b_i,
web_i => wr_b_i,
ab_i => addr_b_i,
db_i => data_b_i,
qb_o => data_b_o);
end syn;
-------------------------------------------------------------------------------
-- Title : Cheby components
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : cheby_pkg.vhd
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Copyright (c) 2020 CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package cheby_pkg is
component cheby_dpssram
generic (
g_data_width : natural;
g_size : natural;
g_addr_width : natural;
g_dual_clock : std_logic;
g_use_bwsel : std_logic);
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic);
end component;
end cheby_pkg;
......@@ -12,7 +12,7 @@
-- - configurable full/empty/almost full/almost empty/word count signals
--
--------------------------------------------------------------------------------
-- Copyright CERN 2011-2018
-- Copyright CERN 2011-2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
......@@ -38,6 +38,12 @@ entity inferred_sync_fifo is
g_size : natural;
g_show_ahead : boolean := false;
-- Previously, the full flag was asserted at g_size-1 when using g_show_ahead.
-- The new implementation solves this. However, for backward compatibility,
-- the default is to still use the previous behaviour. Set this to false to
-- switch to the new one.
g_show_ahead_legacy_mode : boolean := true;
-- Read-side flag selection
g_with_empty : boolean := true; -- with empty flag
g_with_full : boolean := true; -- with full flag
......@@ -84,6 +90,12 @@ architecture syn of inferred_sync_fifo is
begin -- syn
legacy_mode_check: assert g_show_ahead = false or g_show_ahead_legacy_mode = false
report legacy_mode_check'instance_name & ": show-ahead enabled for sync FIFO in " &
"legacy mode. In this mode, the full flag is asserted at g_SIZE-1. if you want the " &
"full flag to be asserted at g_SIZE, then disable g_SHOW_AHEAD_LEGACY_MODE."
severity NOTE;
we_int <= we_i and not full;
rd_int <= rd_i and not empty;
......@@ -135,7 +147,8 @@ begin -- syn
end if;
end process;
gen_comb_flags_showahead : if(g_show_ahead = true) generate
gen_comb_flags_showahead_legacy : if g_show_ahead = true and
g_show_ahead_legacy_mode = true generate
process(clk_i)
begin
......@@ -149,6 +162,34 @@ begin -- syn
end process;
full <= '1' when (wr_ptr + 1 = rd_ptr) else '0';
end generate gen_comb_flags_showahead_legacy;
gen_comb_flags_showahead : if g_show_ahead = true and
g_show_ahead_legacy_mode = false generate
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
guard_bit <= '0';
empty <= '1';
else
if wr_ptr = rd_ptr_muxed and guard_bit = '0' then
empty <= '1';
else
empty <= '0';
end if;
if(wr_ptr + 1 = rd_ptr and we_int = '1') then
guard_bit <= '1';
elsif(rd_i = '1') then
guard_bit <= '0';
end if;
end if;
end if;
end process;
full <= '1' when (wr_ptr = rd_ptr and guard_bit = '1') else '0';
end generate gen_comb_flags_showahead;
gen_comb_flags : if(g_register_flag_outputs = false and g_show_ahead = false) generate
......
......@@ -12,7 +12,7 @@
-- - configurable full/empty/almost full/almost empty/word count signals
--
--------------------------------------------------------------------------------
-- Copyright CERN 2011-2018
-- Copyright CERN 2011-2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
......@@ -38,15 +38,21 @@ entity generic_sync_fifo is
g_size : natural;
g_show_ahead : boolean := false;
-- Read-side flag selection
-- Previously, the full flag was asserted at g_size-1 when using g_show_ahead.
-- The new implementation solves this. However, for backward compatibility,
-- the default is to still use the previous behaviour. Set this to false to
-- switch to the new one.
g_show_ahead_legacy_mode : boolean := true;
-- Read-side flag selection
g_with_empty : boolean := true; -- with empty flag
g_with_full : boolean := true; -- with full flag
g_with_almost_empty : boolean := false;
g_with_almost_full : boolean := false;
g_with_count : boolean := false; -- with words counter
g_almost_empty_threshold : integer; -- threshold for almost empty flag
g_almost_full_threshold : integer; -- threshold for almost full flag
g_almost_empty_threshold : integer := 0; -- threshold for almost empty flag
g_almost_full_threshold : integer := 0; -- threshold for almost full flag
g_register_flag_outputs : boolean := true
);
......@@ -76,6 +82,7 @@ architecture syn of generic_sync_fifo is
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean;
g_show_ahead_legacy_mode : boolean;
g_with_empty : boolean;
g_with_full : boolean;
g_with_almost_empty : boolean;
......@@ -105,6 +112,7 @@ begin -- syn
g_data_width => g_data_width,
g_size => g_size,
g_show_ahead => g_show_ahead,
g_show_ahead_legacy_mode => g_show_ahead_legacy_mode,
g_with_empty => g_with_empty,
g_with_full => g_with_full,
g_with_almost_empty => g_with_almost_empty,
......
......@@ -209,13 +209,15 @@ package genram_pkg is
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean := false;
g_show_ahead_legacy_mode : boolean := true;
g_with_empty : boolean := true;
g_with_full : boolean := true;
g_with_almost_empty : boolean := false;
g_with_almost_full : boolean := false;
g_with_count : boolean := false;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
g_almost_full_threshold : integer := 0;
g_register_flag_outputs : boolean := true);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......
modules = { "local" : [
"wb_async_bridge",
"wb_axi4lite_bridge",
......@@ -27,8 +26,10 @@ modules = { "local" : [
"wb_metadata",
"wb_split",
"wb16_to_wb32",
"wb_indirect",
"wbgen2",
"wbgenplus",
"wb_xc7_fw_update",
]}
files = [
......
files = ["xwb_indirect.vhd", "wb_indirect_regs.vhd"]
memory-map:
bus: wb-32-be
name: wb_indirect_regs
description: Indirect access to a wishbone bus
x-hdl:
busgroup: True
children:
- reg:
name: addr
description: address to use on the wishbone bus
width: 32
access: rw
x-hdl:
write-strobe: True
type: wire
- reg:
name: data
description: data word to be read or written
width: 32
access: rw
x-hdl:
write-strobe: True
read-strobe: True
write-ack: True
read-ack: True
type: wire
-- Do not edit. Generated on Mon Apr 20 10:08:30 2020 by gingold
-- With Cheby 1.4.dev0 and these options:
-- -i wb_indirect_regs.cheby --gen-hdl=wb_indirect_regs.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wb_indirect_regs is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- address to use on the wishbone bus
addr_i : in std_logic_vector(31 downto 0);
addr_o : out std_logic_vector(31 downto 0);
addr_wr_o : out std_logic;
-- data word to be read or written
data_i : in std_logic_vector(31 downto 0);
data_o : out std_logic_vector(31 downto 0);
data_wr_o : out std_logic;
data_rd_o : out std_logic;
data_wack_i : in std_logic;
data_rack_i : in std_logic
);
end wb_indirect_regs;
architecture syn of wb_indirect_regs is
signal adr_int : std_logic_vector(2 downto 2);
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal addr_wreq : std_logic;
signal data_wreq : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_adr_d0 : std_logic_vector(2 downto 2);
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
adr_int <= wb_i.adr(2 downto 2);
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_adr_d0 <= adr_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Register addr
addr_o <= wr_dat_d0;
addr_wr_o <= addr_wreq;
-- Register data
data_o <= wr_dat_d0;
data_wr_o <= data_wreq;
-- Process for write requests.
process (wr_adr_d0, wr_req_d0, data_wack_i) begin
addr_wreq <= '0';
data_wreq <= '0';
case wr_adr_d0(2 downto 2) is
when "0" =>
-- Reg addr
addr_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0;
when "1" =>
-- Reg data
data_wreq <= wr_req_d0;
wr_ack_int <= data_wack_i;
when others =>
wr_ack_int <= wr_req_d0;
end case;
end process;
-- Process for read requests.
process (adr_int, rd_req_int, addr_i, data_rack_i, data_i) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
data_rd_o <= '0';
case adr_int(2 downto 2) is
when "0" =>
-- Reg addr
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= addr_i;
when "1" =>
-- Reg data
data_rd_o <= rd_req_int;
rd_ack_d0 <= data_rack_i;
rd_dat_d0 <= data_i;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
end process;
end syn;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General cores: Indirect Wishbone Slave
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: xwb_indirect
--
-- description: This design is a wishbone slave that drivers a wishbone master.
-- As a slave, it has 2 registers: address and data. An access to the data
-- register starts a transaction on the WB master side using the address of
-- the address register. At the end of the transaction, the address
-- register is incremented by 4.
--
--------------------------------------------------------------------------------
-- 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;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity xwb_indirect is
generic (
mode : t_wishbone_interface_mode := PIPELINED
);
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
master_wb_i : in t_wishbone_master_in;
master_wb_o : out t_wishbone_master_out
);
end xwb_indirect;
architecture arch of xwb_indirect is
-- Address register. Use a specific register to auto-increment it.
signal addr : std_logic_vector(31 downto 0);
signal addr_out : std_logic_vector(31 downto 0);
signal addr_wr_out : std_logic;
signal data : std_logic_vector(31 downto 0);
signal data_out : std_logic_vector(31 downto 0);
signal data_wr_out : std_logic;
signal data_rd_out : std_logic;
signal data_wack_in : std_logic;
signal data_rack_in : std_logic;
type t_state is (IDLE, READ, WRITE);
signal state : t_state;
signal stb : std_logic;
signal we : std_logic;
begin
process (clk_i)
begin
if rising_edge (clk_i) then
if rst_n_i = '0' then
state <= IDLE;
data_wack_in <= '0';
data_rack_in <= '0';
data <= (others => '0');
addr <= (others => '0');
stb <= '0';
we <= '0';
else
data_wack_in <= '0';
data_rack_in <= '0';
-- Write to the address register.
if addr_wr_out = '1' then
addr <= addr_out;
end if;
case state is
when IDLE =>
if data_wr_out = '1' then
we <= '1';
stb <= '1';
-- Capture the data.
data <= data_out;
state <= WRITE;
elsif data_rd_out = '1' then
we <= '1';
stb <= '1';
state <= READ;
end if;
when WRITE
| READ =>
if mode = PIPELINED then
-- STB is asserted for one cycle in piplined mode.
stb <= '0';
end if;
if master_wb_i.ack = '1'
or master_wb_i.err = '1'
or master_wb_i.rty = '1'
then
-- End of transaction (for classic mode).
stb <= '0';
-- Ack the master.
if state = WRITE then
data_wack_in <= '1';
else
-- Capture the data.
data <= master_wb_i.dat;
data_rack_in <= '1';
end if;
addr <= std_logic_vector(unsigned(addr) + 4);
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
master_wb_o <= (cyc => stb,
stb => stb,
adr => addr,
sel => "1111",
we => we,
dat => data);
inst_regs: entity work.wb_indirect_regs
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
wb_i => wb_i,
wb_o => wb_o,
addr_i => addr,
addr_o => addr_out,
addr_wr_o => addr_wr_out,
data_i => data,
data_o => data_out,
data_wr_o => data_wr_out,
data_rd_o => data_rd_out,
data_wack_i => data_wack_in,
data_rack_i => data_rack_in);
end arch;
files = ["wb_xc7_fw_update_regs.vhd",
"xwb_xc7_fw_update.vhd",
]
memory-map:
bus: wb-32-be
name: wb_xc7_fw_update_regs
description: System Control Registers
x-hdl:
busgroup: True
children:
- reg:
name: far
width: 32
access: rw
comment: Flash Access Register
description: Provides direct access to the SPI flash memory containing the bitstream.
x-hdl:
type: wire
write-strobe: true
children:
- field:
name: data
range: 7-0
comment: SPI Data
description: Data to be written / read to/from the flash SPI controller.
- field:
name: xfer
range: 8
comment: SPI Start Transfer
description: "write 1: initiate an SPI transfer with an 8-bit data word taken from the DATA field. write 0: no effect"
- field:
name: ready
range: 9
comment: SPI Ready
description: "read 1: Core is ready to initiate another transfer. DATA field contains the data read during previous transaction. read 0: core is busy"
- field:
name: cs
range: 10
comment: SPI Chip Select
description: "write 1: Enable target SPI controller. write 0: Disable target SPI controller"
-- Do not edit. Generated on Tue May 19 11:16:59 2020 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- -i wb_xc7_fw_update_regs.cheby --gen-hdl wb_xc7_fw_update_regs.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wb_xc7_fw_update_regs is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- Flash Access Register
-- SPI Data
far_data_i : in std_logic_vector(7 downto 0);
far_data_o : out std_logic_vector(7 downto 0);
-- SPI Start Transfer
far_xfer_i : in std_logic;
far_xfer_o : out std_logic;
-- SPI Ready
far_ready_i : in std_logic;
far_ready_o : out std_logic;
-- SPI Chip Select
far_cs_i : in std_logic;
far_cs_o : out std_logic;
far_wr_o : out std_logic
);
end wb_xc7_fw_update_regs;
architecture syn of wb_xc7_fw_update_regs is
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal far_wreq : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Register far
far_data_o <= wr_dat_d0(7 downto 0);
far_xfer_o <= wr_dat_d0(8);
far_ready_o <= wr_dat_d0(9);
far_cs_o <= wr_dat_d0(10);
far_wr_o <= far_wreq;
-- Process for write requests.
process (wr_req_d0) begin
far_wreq <= '0';
-- Reg far
far_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0;
end process;
-- Process for read requests.
process (rd_req_int, far_data_i, far_xfer_i, far_ready_i, far_cs_i) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
-- Reg far
rd_ack_d0 <= rd_req_int;
rd_dat_d0(7 downto 0) <= far_data_i;
rd_dat_d0(8) <= far_xfer_i;
rd_dat_d0(9) <= far_ready_i;
rd_dat_d0(10) <= far_cs_i;
rd_dat_d0(31 downto 11) <= (others => '0');
end process;
end syn;
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;
use work.wishbone_pkg.all;
entity xwb_xc7_fw_update is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
flash_cs_n_o : out std_logic;
flash_mosi_o : out std_logic;
flash_miso_i : in std_logic
);
end xwb_xc7_fw_update;
architecture rtl of xwb_xc7_fw_update is
signal far_data_in : std_logic_vector(7 downto 0);
signal far_data_out : std_logic_vector(7 downto 0);
signal far_xfer_out : std_logic;
signal far_ready_in : std_logic;
signal far_cs_out : std_logic;
signal far_wr_out : std_logic;
signal flash_spi_cs : std_logic;
signal flash_spi_start : std_logic;
signal flash_spi_wdata : std_logic_vector(7 downto 0);
signal flash_sclk : std_logic;
begin
inst_regs: entity work.wb_xc7_fw_update_regs
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
wb_i => wb_i,
wb_o => wb_o,
far_data_i => far_data_in,
far_data_o => far_data_out,
far_xfer_i => '0',
far_xfer_o => far_xfer_out,
far_ready_i => far_ready_in,
far_ready_o => open,
far_cs_i => '0',
far_cs_o => far_cs_out,
far_wr_o => far_wr_out
);
-- Need to capture cs and data_out, and need to delay start.
p_host_spi_registers : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
flash_spi_start <= '0';
flash_spi_wdata <= (others => '0');
flash_spi_cs <= '0';
elsif far_wr_out = '1' then
flash_spi_wdata <= far_data_out;
flash_spi_start <= far_xfer_out;
flash_spi_cs <= far_cs_out;
else
-- Pulse for start.
flash_spi_start <= '0';
end if;
end if;
end process;
U_SPI_Master : entity work.gc_simple_spi_master
generic map (
g_div_ratio_log2 => 0,
g_num_data_bits => 8)
port map (
clk_sys_i => clk_i,
rst_n_i => rst_n_i,
cs_i => flash_spi_cs,
start_i => flash_spi_start,
cpol_i => '0',
data_i => flash_spi_wdata,
ready_o => far_ready_in,
data_o => far_data_in,
spi_cs_n_o => flash_cs_n_o,
spi_sclk_o => flash_sclk,
spi_mosi_o => flash_mosi_o,
spi_miso_i => flash_miso_i);
STARTUPE2_inst : STARTUPE2
generic map (
PROG_USR => "FALSE", -- Activate program event security feature. Requires encrypted bitstreams.
SIM_CCLK_FREQ => 0.0 -- Set the Configuration Clock Frequency(ns) for simulation.
)
port map (
CFGCLK => open, -- 1-bit output: Configuration main clock output
CFGMCLK => open, -- 1-bit output: Configuration internal oscillator clock output
EOS => open, -- 1-bit output: Active high output signal indicating the End Of Startup.
PREQ => open, -- 1-bit output: PROGRAM request to fabric output
CLK => '0', -- 1-bit input: User start-up clock input
GSR => '0', -- 1-bit input: Global Set/Reset input (GSR cannot be used for the port name)
GTS => '0', -- 1-bit input: Global 3-state input (GTS cannot be used for the port name)
KEYCLEARB => '0', -- 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
PACK => '0', -- 1-bit input: PROGRAM acknowledge input
USRCCLKO => flash_sclk, -- 1-bit input: User CCLK input
USRCCLKTS => '0', -- 1-bit input: User CCLK 3-state enable input
USRDONEO => '0', -- 1-bit input: User DONE pin output control
USRDONETS => '1' -- 1-bit input: User DONE 3-state enable output
);
end rtl;
......@@ -298,10 +298,14 @@ class CIWBMasterAccessor extends CWishboneAccessor;
endclass // CIWBMasterAccessor
CIWBMasterAccessor theAccessor;
initial
theAccessor = new;
function automatic CIWBMasterAccessor get_accessor();
automatic CIWBMasterAccessor tmp;
tmp = new;
return tmp;
return theAccessor;
endfunction // get_accessor
always@(posedge clk_i)
......
......@@ -9,12 +9,16 @@ virtual class CWishboneAccessor extends CBusAccessor;
protected wb_cycle_type_t m_cycle_type;
function new();
$display("NEW");
m_cycle_type = CLASSIC;
m_default_xfer_size = 4;
endfunction // new
virtual task set_mode(wb_cycle_type_t mode);
virtual task automatic set_mode(wb_cycle_type_t mode);
m_cycle_type = mode;
$display("SET MODE %d", mode );
endtask // set_mode
......@@ -29,18 +33,18 @@ virtual class CWishboneAccessor extends CBusAccessor;
// RANDOM - event occurs randomly with probability (prob)
// These two can be combined (random events occuring after a certain initial delay)
// DELAYED events can be repeated (rep_rate parameter)
virtual task add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
virtual task automatic add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
endtask // add_event
// [slave only] gets a cycle from the queue
virtual task get(ref wb_cycle_t xfer);
virtual task automatic get(ref wb_cycle_t xfer);
endtask // get
// [master only] executes a cycle and returns its result
virtual task put(ref wb_cycle_t xfer);
virtual task automatic put(ref wb_cycle_t xfer);
endtask // put
......@@ -49,7 +53,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
endfunction // idle
// [master only] generic write(s), blocking
virtual task writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
virtual task automatic writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
......@@ -74,11 +78,13 @@ virtual class CWishboneAccessor extends CBusAccessor;
endtask // write
// [master only] generic read(s), blocking
virtual task readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
virtual task automatic readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
cycle.ctype = m_cycle_type;
$display("CYCLE CTYPE %d %d", cycle.ctype, m_cycle_type );
cycle.rw = 1'b0;
for(i=0;i < addr.size(); i++)
......@@ -99,7 +105,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
endtask // readm
virtual task read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
virtual task automatic read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
......@@ -108,7 +114,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
data = da[0];
endtask
virtual task write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
virtual task automatic write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
......
......@@ -24,10 +24,10 @@ virtual class CBusAccessor;
pure virtual task writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
pure virtual task automatic writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task automatic readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
virtual task read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
virtual task automatic read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
int res;
uint64_t aa[1], da[];
......@@ -39,7 +39,7 @@ virtual class CBusAccessor;
endtask
virtual task write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
virtual task automatic write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
uint64_t aa[1], da[1];
aa[0] = addr;
da[0] = data;
......
files = [ 'sim_wishbone.vhd', 'sim_wishbone16.vhd']
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
package sim_wishbone is
-- PL: pipelined versions.
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : std_logic_vector (31 downto 0));
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : out std_logic_vector (31 downto 0));
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (31 downto 0));
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (31 downto 0));
end sim_wishbone;
package body sim_wishbone is
-- Generate a strobe pulse.
procedure start_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in) is
begin
wb_o.stb <= '1';
loop
wait until rising_edge(clk);
exit when wb_i.stall = '0';
end loop;
wb_o.stb <= '0';
end start_pl;
procedure wait_ack (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in) is
begin
loop
exit when wb_i.ack = '1';
wait until rising_edge(clk);
end loop;
wb_o.cyc <= '0';
wb_o.adr <= (others => 'X');
wb_o.dat <= (others => 'X');
end wait_ack;
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : std_logic_vector (31 downto 0)) is
begin
wb_o.adr <= addr;
wb_o.dat <= data;
wb_o.sel <= "1111";
wb_o.we <= '1';
wb_o.cyc <= '1';
start_pl (clk, wb_o, wb_i);
wait_ack (clk, wb_o, wb_i);
end write32_pl;
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : out std_logic_vector (31 downto 0)) is
begin
wb_o.adr <= addr;
wb_o.we <= '0';
wb_o.cyc <= '1';
start_pl (clk, wb_o, wb_i);
wait_ack (clk, wb_o, wb_i);
data := wb_i.dat;
end read32_pl;
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (31 downto 0)) is
begin
write32_pl (clk, wb_o, wb_i, std_logic_vector (to_unsigned(addr, 32)), data);
end write32_pl;
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (31 downto 0)) is
begin
read32_pl (clk, wb_o, wb_i, std_logic_vector (to_unsigned(addr, 32)), data);
end read32_pl;
end sim_wishbone;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
package sim_wishbone16 is
-- PL: pipelined versions.
procedure write16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (15 downto 0));
procedure read16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (15 downto 0));
procedure write64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (63 downto 0));
procedure read64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (63 downto 0));
end sim_wishbone16;
use work.sim_wishbone.all;
package body sim_wishbone16 is
procedure write16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (15 downto 0)) is
begin
write32_pl(clk, wb_o, wb_i, addr, x"0000" & data);
end write16_pl;
procedure read16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (15 downto 0))
is
variable t : std_logic_vector(31 downto 0);
begin
read32_pl(clk, wb_o, wb_i, addr, t);
data := t(15 downto 0);
end read16_pl;
procedure write64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (63 downto 0)) is
begin
write32_pl(clk, wb_o, wb_i, addr + 0, x"0000" & data (63 downto 48));
write32_pl(clk, wb_o, wb_i, addr + 2, x"0000" & data (47 downto 32));
write32_pl(clk, wb_o, wb_i, addr + 4, x"0000" & data (31 downto 16));
write32_pl(clk, wb_o, wb_i, addr + 6, x"0000" & data (15 downto 00));
end write64be_pl;
procedure read64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (63 downto 0))
is
variable t : std_logic_vector(31 downto 0);
begin
read32_pl(clk, wb_o, wb_i, addr + 0, t);
data (63 downto 48) := t(15 downto 0);
read32_pl(clk, wb_o, wb_i, addr + 2, t);
data (47 downto 32) := t(15 downto 0);
read32_pl(clk, wb_o, wb_i, addr + 4, t);
data (31 downto 16) := t(15 downto 0);
read32_pl(clk, wb_o, wb_i, addr + 6, t);
data (15 downto 00) := t(15 downto 0);
end read64be_pl;
end sim_wishbone16;
action = "simulation"
target = "generic"
sim_top = "tb_wb_indirect"
sim_tool = ""
modules = { "local" : ["../../../", "../../../sim/vhdl"] };
files = ["tb_wb_indirect.vhd"]
[*]
[*] GTKWave Analyzer v3.3.100 (w)1999-2019 BSI
[*] Mon Apr 20 13:42:47 2020
[*]
[dumpfile] "/Users/gingold/work/general-cores/testbench/wishbone/wb_indirect/tb.ghw"
[dumpfile_mtime] "Mon Apr 20 13:26:13 2020"
[dumpfile_size] 6946
[savefile] "/Users/gingold/work/general-cores/testbench/wishbone/wb_indirect/tb_indirect.gtkw"
[timestart] 0
[size] 1603 918
[pos] -1 -1
*-25.749573 20000000 -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_wb_indirect.
[treeopen] top.tb_wb_indirect.inst_xwb_indirect.
[treeopen] top.tb_wb_indirect.inst_xwb_indirect.inst_regs.
[sst_width] 193
[signals_width] 214
[sst_expanded] 1
[sst_vpaned_height] 278
@420
top.tb_wb_indirect.done
@28
top.tb_wb_indirect.clk
top.tb_wb_indirect.rst_n
top.tb_wb_indirect.wb_out.ack
@22
#{top.tb_wb_indirect.wb_out.dat[31:0]} top.tb_wb_indirect.wb_out.dat[31] top.tb_wb_indirect.wb_out.dat[30] top.tb_wb_indirect.wb_out.dat[29] top.tb_wb_indirect.wb_out.dat[28] top.tb_wb_indirect.wb_out.dat[27] top.tb_wb_indirect.wb_out.dat[26] top.tb_wb_indirect.wb_out.dat[25] top.tb_wb_indirect.wb_out.dat[24] top.tb_wb_indirect.wb_out.dat[23] top.tb_wb_indirect.wb_out.dat[22] top.tb_wb_indirect.wb_out.dat[21] top.tb_wb_indirect.wb_out.dat[20] top.tb_wb_indirect.wb_out.dat[19] top.tb_wb_indirect.wb_out.dat[18] top.tb_wb_indirect.wb_out.dat[17] top.tb_wb_indirect.wb_out.dat[16] top.tb_wb_indirect.wb_out.dat[15] top.tb_wb_indirect.wb_out.dat[14] top.tb_wb_indirect.wb_out.dat[13] top.tb_wb_indirect.wb_out.dat[12] top.tb_wb_indirect.wb_out.dat[11] top.tb_wb_indirect.wb_out.dat[10] top.tb_wb_indirect.wb_out.dat[9] top.tb_wb_indirect.wb_out.dat[8] top.tb_wb_indirect.wb_out.dat[7] top.tb_wb_indirect.wb_out.dat[6] top.tb_wb_indirect.wb_out.dat[5] top.tb_wb_indirect.wb_out.dat[4] top.tb_wb_indirect.wb_out.dat[3] top.tb_wb_indirect.wb_out.dat[2] top.tb_wb_indirect.wb_out.dat[1] top.tb_wb_indirect.wb_out.dat[0]
@28
top.tb_wb_indirect.wb_out.err
top.tb_wb_indirect.wb_out.rty
top.tb_wb_indirect.wb_out.stall
@22
#{top.tb_wb_indirect.wb_in.adr[31:0]} top.tb_wb_indirect.wb_in.adr[31] top.tb_wb_indirect.wb_in.adr[30] top.tb_wb_indirect.wb_in.adr[29] top.tb_wb_indirect.wb_in.adr[28] top.tb_wb_indirect.wb_in.adr[27] top.tb_wb_indirect.wb_in.adr[26] top.tb_wb_indirect.wb_in.adr[25] top.tb_wb_indirect.wb_in.adr[24] top.tb_wb_indirect.wb_in.adr[23] top.tb_wb_indirect.wb_in.adr[22] top.tb_wb_indirect.wb_in.adr[21] top.tb_wb_indirect.wb_in.adr[20] top.tb_wb_indirect.wb_in.adr[19] top.tb_wb_indirect.wb_in.adr[18] top.tb_wb_indirect.wb_in.adr[17] top.tb_wb_indirect.wb_in.adr[16] top.tb_wb_indirect.wb_in.adr[15] top.tb_wb_indirect.wb_in.adr[14] top.tb_wb_indirect.wb_in.adr[13] top.tb_wb_indirect.wb_in.adr[12] top.tb_wb_indirect.wb_in.adr[11] top.tb_wb_indirect.wb_in.adr[10] top.tb_wb_indirect.wb_in.adr[9] top.tb_wb_indirect.wb_in.adr[8] top.tb_wb_indirect.wb_in.adr[7] top.tb_wb_indirect.wb_in.adr[6] top.tb_wb_indirect.wb_in.adr[5] top.tb_wb_indirect.wb_in.adr[4] top.tb_wb_indirect.wb_in.adr[3] top.tb_wb_indirect.wb_in.adr[2] top.tb_wb_indirect.wb_in.adr[1] top.tb_wb_indirect.wb_in.adr[0]
@28
top.tb_wb_indirect.wb_in.cyc
@29
top.tb_wb_indirect.wb_in.stb
@22
#{top.tb_wb_indirect.wb_in.dat[31:0]} top.tb_wb_indirect.wb_in.dat[31] top.tb_wb_indirect.wb_in.dat[30] top.tb_wb_indirect.wb_in.dat[29] top.tb_wb_indirect.wb_in.dat[28] top.tb_wb_indirect.wb_in.dat[27] top.tb_wb_indirect.wb_in.dat[26] top.tb_wb_indirect.wb_in.dat[25] top.tb_wb_indirect.wb_in.dat[24] top.tb_wb_indirect.wb_in.dat[23] top.tb_wb_indirect.wb_in.dat[22] top.tb_wb_indirect.wb_in.dat[21] top.tb_wb_indirect.wb_in.dat[20] top.tb_wb_indirect.wb_in.dat[19] top.tb_wb_indirect.wb_in.dat[18] top.tb_wb_indirect.wb_in.dat[17] top.tb_wb_indirect.wb_in.dat[16] top.tb_wb_indirect.wb_in.dat[15] top.tb_wb_indirect.wb_in.dat[14] top.tb_wb_indirect.wb_in.dat[13] top.tb_wb_indirect.wb_in.dat[12] top.tb_wb_indirect.wb_in.dat[11] top.tb_wb_indirect.wb_in.dat[10] top.tb_wb_indirect.wb_in.dat[9] top.tb_wb_indirect.wb_in.dat[8] top.tb_wb_indirect.wb_in.dat[7] top.tb_wb_indirect.wb_in.dat[6] top.tb_wb_indirect.wb_in.dat[5] top.tb_wb_indirect.wb_in.dat[4] top.tb_wb_indirect.wb_in.dat[3] top.tb_wb_indirect.wb_in.dat[2] top.tb_wb_indirect.wb_in.dat[1] top.tb_wb_indirect.wb_in.dat[0]
#{top.tb_wb_indirect.wb_in.sel[3:0]} top.tb_wb_indirect.wb_in.sel[3] top.tb_wb_indirect.wb_in.sel[2] top.tb_wb_indirect.wb_in.sel[1] top.tb_wb_indirect.wb_in.sel[0]
@28
top.tb_wb_indirect.wb_in.we
@200
-xwb_indirect
[pattern_trace] 1
[pattern_trace] 0
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.sim_wishbone.all;
entity tb_wb_indirect is
end tb_wb_indirect;
architecture arch of tb_wb_indirect is
signal rst_n : std_logic;
signal clk : std_logic;
signal wb_in : t_wishbone_slave_in;
signal wb_out : t_wishbone_slave_out;
signal master_wb_in : t_wishbone_master_in;
signal master_wb_out : t_wishbone_master_out;
signal last_addr : std_logic_vector (31 downto 0);
signal last_data : std_logic_vector (31 downto 0);
-- For end of test.
signal done : boolean := False;
begin
-- Clock.
process
begin
clk <= '0';
wait for 4 ns;
clk <= '1';
wait for 4 ns;
if done then
report "end of test";
wait;
end if;
end process;
rst_n <= '0', '1' after 8 ns;
-- Test process.
process
variable data : std_logic_vector (31 downto 0);
begin
wb_in.cyc <= '0';
wb_in.stb <= '0';
wait until rst_n = '1';
wait until rising_edge (clk);
-- Set the address.
write32_pl (clk, wb_in, wb_out, x"0000_0000", x"0000_2300");
wait until rising_edge (clk);
-- Read data.
read32_pl (clk, wb_in, wb_out, x"0000_0004", data);
assert data = x"0000_2300";
wait until rising_edge (clk);
write32_pl (clk, wb_in, wb_out, x"0000_0004", x"1234_5678");
assert last_addr = x"0000_2304";
assert last_data = x"1234_5678";
read32_pl (clk, wb_in, wb_out, x"0000_0004", data);
assert data = x"0000_2308";
assert last_data = x"1234_5678";
done <= true;
wait;
end process;
inst_xwb_indirect: entity work.xwb_indirect
port map (
rst_n_i => rst_n,
clk_i => clk,
wb_i => wb_in,
wb_o => wb_out,
master_wb_i => master_wb_in,
master_wb_o => master_wb_out);
-- WB slave.
process (clk)
begin
if rising_edge (clk) then
if rst_n = '0' then
master_wb_in <= (rty => '0',
err => '0',
ack => '0',
stall => '0',
dat => (others => 'U'));
else
master_wb_in.ack <= '0';
master_wb_in.stall <= '0';
if (master_wb_out.cyc and master_wb_out.stb) = '1' then
-- Start of transaction.
last_addr <= master_wb_out.adr;
if master_wb_out.we = '1' then
last_data <= master_wb_out.dat;
end if;
master_wb_in.dat <= master_wb_out.adr;
master_wb_in.ack <= '1';
master_wb_in.stall <= '1';
end if;
end if;
end if;
end process;
end arch;
......@@ -3,11 +3,27 @@
with open("buildinfo_pkg.vhd", "w") as f:
import subprocess
import time
# Extract current commit id.
try:
commitid = subprocess.check_output(
["git", "log", "-1", "--format=%H"]).decode().strip()
except:
commitid = "unknown"
# Extract current tag + dirty indicator.
# It is not sure if the definition of dirty is stable across all git versions.
try:
tag = subprocess.check_output(
["git", "describe", "--dirty", "--always"]).decode().strip()
if tag.endswith('-dirty'):
dirty = '-dirty'
else:
dirty = ''
except:
tag = 'unknown'
dirty = "-??"
try:
userid = subprocess.check_output(
["git", "config", "--get", "user.name"]).decode().strip()
......@@ -27,7 +43,8 @@ with open("buildinfo_pkg.vhd", "w") as f:
f.write(" constant buildinfo : string :=\n")
f.write(' "buildinfo:1" & LF\n')
f.write(' & "module:{}" & LF\n'.format(top))
f.write(' & "commit:{}" & LF\n'.format(commitid))
f.write(' & "commit:{}" & LF\n'.format(commitid + dirty))
f.write(' & "tag:{}" & LF\n'.format(tag))
f.write(' & "syntool:{}" & LF\n'.format(tool))
f.write(' & "syndate:{}" & LF\n'.format(
time.strftime("%F, %H:%M %Z", time.localtime())))
......
# Script to generate the buildinfo_pkg.vhd file
# Local parameter: project
with open("sourceid_{}_pkg.vhd".format(project), "w") as f:
import subprocess
import time
# Extract current commit id.
try:
sourceid = subprocess.check_output(
["git", "log", "-1", "--format=%H"]).decode().strip()
sourceid = sourceid[0:32]
except:
commitid = 16 * "00"
# Extract current tag + dirty indicator.
# It is not sure if the definition of dirty is stable across all git versions.
try:
tag = subprocess.check_output(
["git", "describe", "--dirty", "--always"]).decode().strip()
dirty = tag.endswith('-dirty')
except:
dirty = True
if dirty:
# There is no room for a dirty flag, just erase half of the bytes, so
# that's obvious it's not a real sha1, and still leaves enough to
# find the sha1 in the project.
sourceid = sourceid[:16] + (16 * '0')
f.write("-- Sourceid for project {}\n".format(project))
f.write("--\n")
f.write("-- This file was automatically generated; do not edit\n")
f.write("\n")
f.write("library ieee;")
f.write("use ieee.std_logic_1164.all;")
f.write("\n")
f.write("package sourceid_{}_pkg is\n".format(project))
f.write(" constant sourceid : std_logic_vector(127 downto 0) :=\n")
f.write(' x"{}";\n'.format(sourceid))
f.write('end sourceid_{}_pkg;\n'.format(project))
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