Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • project/general-cores
  • kblantos/general-cores
2 results
Show changes
Commits on Source (70)
Showing
with 465 additions and 23 deletions
---
# SPDX-FileCopyrightText: 2024 CERN (home.cern)
#
# SPDX-License-Identifier: BSD-3-Clause
version: '1.0.0'
name: 'Platform-independent core collection'
description: 'https://ohwr.org/project/general-cores/wikis/home'
website: 'https://ohwr.org/project/general-cores'
documentation: 'https://ohwr.org/project/general-cores/wikis'
issues: 'https://ohwr.org/project/general-cores/issues'
licenses:
- 'CC0-1.0'
- 'CERN-OHL-W-2.0'
- 'GPL-2.0'
- 'GPL-3.0'
- 'GPL-3.0-or-later'
forum: 'https://forums.ohwr.org/c/general-cores'
......@@ -9,9 +9,18 @@ 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.4 - 2023-10-18
==================
https://www.ohwr.org/project/general-cores/tags/v1.1.4
Fixed
-----
- sw: kernel compatibilty with modern version
1.1.3 - 2021-08-23
==================
https://www.ohwr.org/project/general-cores/tags/v1.1.2
https://www.ohwr.org/project/general-cores/tags/v1.1.3
Fixed
-----
......
......@@ -84,6 +84,9 @@ In [modules/common](modules/common) there are general purpose cores:
* Module [gc_bicolor_led_ctrl](modules/common/gc_bicolor_led_ctrl.vhd)
controls multiple bicolor leds, including the intensity.
* Module [gc_argb_led_drv](modules/common/gc_argb_led_drv.vhd)
controls one or several ARGB (aka intelligent) leds.
* Module [gc_big_adder](modules/common/gc_big_adder.vhd) provides a pipelined
adder for wide numbers.
......@@ -233,6 +236,9 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
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).
- [mpsoc_int_gen](modules/axi/mpsoc_int_gen) is a module that generates a
PCIe interrupt when a signal goes high (by writting a specific register
in the PS).
* There a modules to build a bus hierarchy:
- [wb_bus_fanout](modules/wishbone/wb_bus_fanout) is a simple master to
......@@ -250,14 +256,14 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
master driven by an address and a data registers.
In [modules/dsp](modules/dsp) there are digital signal processing-related cores:
- [gc_cordic](modules/dsp/gc_cordic) is a pipelined CORDIC core, capable of calculating
- [gc_cordic](modules/dsp/gc_cordic.vhd) is a pipelined CORDIC core, capable of calculating
sine/cosine/magnitude/argument of fixed-point complex numbers.
- [gc_iq_modulator](modules/dsp/gc_iq_modulator) is a Fs/4 IQ modulator (upconverter)
- [gc_iq_demodulator](modules/dsp/gc_iq_demodulator) is a Fs/4 IQ demodulator (downconverter)
- [gc_pipelined_fir_filter](modules/dsp/gc_pipelined_fir_filter) is a generic FIR filter IP inferring FPGA's DSP macros
- [gc_integer_divide](modules/dsp/gc_integer_divide) is a generic sequential integer/fixed-point divider IP.
- [gc_iq_modulator](modules/dsp/gc_iq_modulator.vhd) is a Fs/4 IQ modulator (upconverter)
- [gc_iq_demodulator](modules/dsp/gc_iq_demodulator.vhd) is a Fs/4 IQ demodulator (downconverter)
- [gc_pipelined_fir_filter](modules/dsp/gc_pipelined_fir_filter.vhd) is a generic FIR filter IP inferring FPGA's DSP macros
- [gc_integer_divide](modules/dsp/gc_integer_divide.vhd) is a generic sequential integer/fixed-point divider IP.
Can work with signed/unsigned numbers, also supports remainder calculation.
- [gc_soft_ramp_switch](modules/dsp/gc_soft_ramp_switch) is a "soft switch" to enable/disable a DAC output gently.
- [gc_soft_ramp_switch](modules/dsp/gc_soft_ramp_switch.vhd) is a "soft switch" to enable/disable a DAC output gently.
......@@ -3,6 +3,7 @@ modules = { "local" : [
"axi4lite_wb_bridge",
"axi4lite32_axi4full64_bridge",
"axi4lite_axi4full_bridge",
"mpsoc_int_gen",
]}
files = [
......
......@@ -29,8 +29,9 @@ use work.wishbone_pkg.all;
package axi4_pkg is
-- AXI4-Full interface, master output ports, 32 bits
type t_axi4_full_master_out_32 is record
-- AXI3-Full interface, master output ports, 32 bits
-- Note: this was previously incorrectly named axi4 (AxLOCK is 2 bit, AxLEN is 4 bit)
type t_axi3_full_master_out_32 is record
ARVALID : std_logic;
AWVALID : std_logic;
BREADY : std_logic;
......@@ -60,8 +61,9 @@ package axi4_pkg is
WSTRB : std_logic_vector (3 downto 0);
end record;
-- AXI4-Full interface, master input ports, 32 bits
type t_axi4_full_master_in_32 is record
-- AXI3-Full interface, master input ports, 32 bits
-- Note: this was previously named axi4.
type t_axi3_full_master_in_32 is record
ARREADY : std_logic;
AWREADY : std_logic;
BVALID : std_logic;
......@@ -75,6 +77,52 @@ package axi4_pkg is
RDATA : std_logic_vector (31 downto 0);
end record;
-- AXI4-Full interface, master output ports, 32 bits
type t_axi4_full_master_out_32 is record
ARVALID : std_logic;
AWVALID : std_logic;
BREADY : std_logic;
RREADY : std_logic;
WLAST : std_logic;
WVALID : std_logic;
ARID : std_logic_vector (15 downto 0);
AWID : std_logic_vector (15 downto 0);
WID : std_logic_vector (15 downto 0);
ARBURST : std_logic_vector (1 downto 0);
ARLOCK : std_logic;
ARSIZE : std_logic_vector (2 downto 0);
AWBURST : std_logic_vector (1 downto 0);
AWLOCK : std_logic;
AWSIZE : std_logic_vector (2 downto 0);
ARPROT : std_logic_vector (2 downto 0);
AWPROT : std_logic_vector (2 downto 0);
ARADDR : std_logic_vector (31 downto 0);
AWADDR : std_logic_vector (31 downto 0);
WDATA : std_logic_vector (31 downto 0);
ARCACHE : std_logic_vector (3 downto 0);
ARLEN : std_logic_vector (7 downto 0);
ARQOS : std_logic_vector (3 downto 0);
AWCACHE : std_logic_vector (3 downto 0);
AWLEN : std_logic_vector (7 downto 0);
AWQOS : std_logic_vector (3 downto 0);
WSTRB : std_logic_vector (3 downto 0);
end record;
-- AXI4-Full interface, master input ports, 32 bits
type t_axi4_full_master_in_32 is record
ARREADY : std_logic;
AWREADY : std_logic;
BVALID : std_logic;
RLAST : std_logic;
RVALID : std_logic;
WREADY : std_logic;
BID : std_logic_vector (15 downto 0);
RID : std_logic_vector (15 downto 0);
BRESP : std_logic_vector (1 downto 0);
RRESP : std_logic_vector (1 downto 0);
RDATA : std_logic_vector (31 downto 0);
end record;
-- AXI4-Lite interface, master output ports, 32 bits
type t_axi4_lite_master_out_32 is record
ARVALID : std_logic;
......
files = [
"mpsoc_int_gen.vhd",
];
-------------------------------------------------------------------------------
-- Title : Interrupt generator for ZynqUS mpsoc
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : mpsoc_int_gen.vhd
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Copyright (c) 2023 CERN
--
-- Generate an interrupt by writting a value in a specific address (in the pcie
-- bridge) when a line goes high.
--
-- 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 mpsoc_int_gen is
generic (
-- default values for AXIPCIE_DMA0, DMA_CHANNEL_PCIE_INTERRUPT_ASSERT
g_addr : std_logic_vector(31 downto 0) := x"FD0F_0070";
g_data : std_logic_vector(31 downto 0) := x"0000_0008"
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- A word is written each time this inputs goes high.
irq_i : in std_logic;
-- AXI4-Full master
S_AXI_awaddr : out std_logic_vector (48 downto 0);
S_AXI_awburst : out std_logic_vector (1 downto 0);
S_AXI_awcache : out std_logic_vector (3 downto 0);
S_AXI_awid : out std_logic_vector (5 downto 0);
S_AXI_awlen : out std_logic_vector (7 downto 0);
S_AXI_awlock : out std_logic;
S_AXI_awprot : out std_logic_vector (2 downto 0);
S_AXI_awready : in std_logic;
S_AXI_awsize : out std_logic_vector (2 downto 0);
S_AXI_awuser : out std_logic;
S_AXI_awvalid : out std_logic;
S_AXI_wdata : out std_logic_vector (31 downto 0);
S_AXI_wlast : out std_logic;
S_AXI_wready : in std_logic;
S_AXI_wstrb : out std_logic_vector (3 downto 0);
S_AXI_wvalid : out std_logic;
S_AXI_bid : in std_logic_vector (5 downto 0);
S_AXI_bready : out std_logic;
S_AXI_bresp : in std_logic_vector (1 downto 0);
S_AXI_bvalid : in std_logic
);
end mpsoc_int_gen;
architecture arch of mpsoc_int_gen is
type t_state is (S_IDLE, S_WAIT, S_DONE);
signal state : t_state;
begin
-- AW
S_AXI_awaddr (31 downto 0) <= g_addr;
S_AXI_awaddr (48 downto 32) <= (others => '0');
-- No burst.
S_AXI_awburst <= "01";
S_AXI_awlen <= x"00";
-- Word write
S_AXI_awsize <= "010";
-- Normal Non-cacheable Non-bufferable
S_AXI_awcache <= "0001"; -- 0001 is device, 0000 is strongly-ordered
-- Reuse the same id.
S_AXI_awid <= "000000";
S_AXI_awlock <= '0';
-- Data, unsecure, privileged.
S_AXI_awprot <= "001";
S_AXI_awuser <= '0';
-- S_AXI_awready : in std_logic;
-- S_AXI_awvalid : out std_logic;
-- W
S_AXI_wdata (31 downto 0) <= g_data;
S_AXI_wdata (S_AXI_wdata'left downto 32) <= (others => '0');
S_AXI_wlast <= '1';
S_AXI_wstrb(3 downto 0) <= "1111";
S_AXI_wstrb(s_AXI_wstrb'left downto 4) <= (others => '0');
process (clk_i)
begin
if rising_edge(clk_i) then
S_AXI_bready <= '1';
if rst_n_i = '0' then
S_AXI_awvalid <= '0';
S_AXI_wvalid <= '0';
state <= S_IDLE;
else
case state is
when S_IDLE =>
if irq_i = '1' then
-- Send the write.
S_AXI_awvalid <= '1';
S_AXI_wvalid <= '1';
state <= S_WAIT;
end if;
when S_WAIT =>
if S_AXI_awready = '1' then
S_AXI_awvalid <= '0';
end if;
if S_AXI_wready = '1' then
S_AXI_wvalid <= '0';
end if;
if S_AXI_bvalid = '1' then
-- Got the anwser.
state <= S_DONE;
end if;
when S_DONE =>
if irq_i = '0' then
-- Wait for irq release.
state <= S_IDLE;
end if;
end case;
end if;
end if;
end process;
end arch;
......@@ -42,4 +42,5 @@ files = [
"gc_async_counter_diff.vhd",
"gc_sync_word_wr.vhd",
"gc_sync_word_rd.vhd",
"gc_argb_led_drv.vhd",
];
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- Project : General Cores Collection library
--------------------------------------------------------------------------------
--
-- unit name: gc_argb_led_drv
--
-- description: Driver for argb (or intelligent) led like ws2812b
--
--------------------------------------------------------------------------------
-- Copyright CERN 2024
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gc_argb_led_drv is
generic (
g_clk_freq : natural
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Input: color + valid bit.
-- The input is read when both ready_o and valid_i are set.
-- It is then transmitted, and during the transmission, ready_o
-- is false.
g_i : in std_logic_vector(7 downto 0);
r_i : in std_logic_vector(7 downto 0);
b_i : in std_logic_vector(7 downto 0);
valid_i : in std_logic;
-- Output to the first led.
dout_o : out std_logic;
-- Set when ready to use the input.
ready_o : out std_logic;
-- If no new inputs are valid for 50us while ready_o is set,
-- res_o raises to indicate the led are reset. The next input
-- will be used by the first led.
res_o : out std_logic
);
end gc_argb_led_drv;
architecture arch of gc_argb_led_drv is
constant C_T0H : natural := g_clk_freq * 8 / 20_000_000 - 1; -- 0.4us
constant C_T0L : natural := g_clk_freq * 17 / 20_000_000 - 1; -- 0.85us
constant C_T1H : natural := g_clk_freq * 16 / 20_000_000 - 1; -- 0.8us
constant C_T1L : natural := g_clk_freq * 9 / 20_000_000 - 1; -- 0.45us
signal frame : std_logic_vector(23 downto 0);
signal counter : natural range 0 to C_T0L;
subtype t_reset is natural range 0 to g_clk_freq * 5 / 100_000 - 1;
signal res_counter : t_reset;
signal shift_cnt : natural range 0 to 23;
signal hi_lo : std_logic;
signal tx : std_logic;
signal msb : std_logic;
begin
ready_o <= not tx;
msb <= frame(23);
dout_o <= hi_lo;
process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
res_o <= '0';
res_counter <= 0;
else
if tx = '1' then
res_counter <= 0;
res_o <= '0';
elsif res_counter = t_reset'high then
res_o <= '1';
else
res_counter <= res_counter + 1;
end if;
end if;
end if;
end process;
process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
tx <= '0';
frame <= (others => '0');
hi_lo <= '0';
else
if tx = '0' then
if valid_i = '1' then
-- Note: the order depends on the manufacturer.
frame <= r_i & g_i & b_i;
tx <= '1';
shift_cnt <= 0;
counter <= 0;
hi_lo <= '1';
end if;
else
if hi_lo = '1'
and ((msb = '1' and counter = C_T1H) or (msb = '0' and counter = C_T0H))
then
hi_lo <= '0';
counter <= 0;
elsif hi_lo = '0'
and ((msb = '1' and counter = C_T1L) or (msb = '0' and counter = C_T0L))
then
if shift_cnt = 23 then
tx <= '0';
else
shift_cnt <= shift_cnt + 1;
frame <= frame(22 downto 0) & '0';
counter <= 0;
hi_lo <= '1';
end if;
else
counter <= counter + 1;
end if;
end if;
end if;
end if;
end process;
end arch;
\ No newline at end of file
......@@ -73,6 +73,9 @@ begin -- rtl
cmp_pulse_out : gc_edge_detect
generic map (
g_ASYNC_RST => true
)
port map (
clk_i => clk_out_i,
rst_n_i => rst_out_n_i,
......
......@@ -54,7 +54,8 @@ architecture arch of gc_reset_multi_aasd is
attribute keep : string;
attribute keep of gc_reset_async_in : signal is "TRUE";
attribute keep of rst_chains : signal is "TRUE";
begin
gc_reset_async_in <= arst_i;
......
......@@ -6,7 +6,7 @@
-- Author : Pablo Alvarez Sanchez
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2019-09-09
-- Last update: 2023-05-17
-- Platform : FPGA-generic
-- Standard : VHDL '87
-------------------------------------------------------------------------------
......@@ -34,6 +34,7 @@
-- 2010-02-25 1.1 twlostow Modified for rev 1.1 switch
-- 2016-08-24 1.2 jpospisi removed synchronous reset from
-- sensitivity lists
-- 2023-11-29 1.3 lihm added select to support
-------------------------------------------------------------------------------
library IEEE;
......@@ -76,6 +77,7 @@ entity gc_serial_dac is
dac_cs_n_o : out std_logic_vector(g_num_cs_select-1 downto 0);
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic;
dac_sel_i : in std_logic_vector(2 downto 0) := "000";
-- when 1, the SPI interface is busy sending data to the DAC.
busy_o : out std_logic
......@@ -96,6 +98,8 @@ architecture syn of gc_serial_dac is
signal divider_muxed : std_logic;
signal cs_sel_reg : std_logic_vector(g_num_cs_select-1 downto 0);
signal dac_sel : std_logic_vector(2 downto 0);
begin
......@@ -135,7 +139,7 @@ begin
process(clk_i)
begin
if rising_edge(clk_i) then
if iValidValue = '1' then
if iValidValue = '1' and sendingData = '0' then
divider <= (others => '0');
elsif sendingData = '1' then
if(divider_muxed = '1') then
......@@ -156,7 +160,7 @@ begin
if rst_n_i = '0' then
iDacClk <= '1'; -- 0
else
if iValidValue = '1' then
if iValidValue = '1' and sendingData = '0' then
iDacClk <= '1'; -- 0
elsif divider_muxed = '1' then
iDacClk <= not(iDacClk);
......@@ -167,6 +171,13 @@ begin
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
dac_sel <= dac_sel_i;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
......@@ -175,8 +186,14 @@ begin
else
if iValidValue = '1' and sendingData = '0' then
cs_sel_reg <= cs_sel_i;
dataSh(g_num_data_bits-1 downto 0) <= value_i;
dataSh(dataSh'left downto g_num_data_bits) <= (others => '0');
if(dac_sel = b"001") then -- AD5683R
dataSh(dataSh'left downto g_num_data_bits+4)<= "0011";
dataSh(g_num_data_bits+4-1 downto 4) <= value_i;
dataSh(3 downto 0) <= (others => '0');
else -- AD5662
dataSh(g_num_data_bits-1 downto 0) <= value_i;
dataSh(dataSh'left downto g_num_data_bits) <= (others => '0');
end if;
elsif sendingData = '1' and divider_muxed = '1' and iDacClk = '0' then
dataSh(0) <= dataSh(dataSh'left);
dataSh(dataSh'left downto 1) <= dataSh(dataSh'left - 1 downto 0);
......
......@@ -57,6 +57,7 @@ architecture arch of gc_sync is
attribute shreg_extract of sync1 : signal is "no";
attribute keep : string;
attribute keep of clk_i : signal is "true";
attribute keep of gc_sync_ffs_in : signal is "true";
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
......
......@@ -50,6 +50,7 @@ architecture rtl of gc_sync_register is
attribute shreg_extract of sync1 : signal is "no";
attribute keep : string;
attribute keep of clk_i : signal is "true";
attribute keep of gc_sync_register_in : signal is "true";
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
......
......@@ -45,6 +45,11 @@ package gencores_pkg is
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;
-- Returns the log2 of N such that 2**f_log2(N) >= N.
-- The result is the minimum value. Can return 0.
function f_log2(N : positive) return natural;
-- Slightly incorrect version of log2: the result is at least 1.
function f_log2_ceil(N : natural) return positive;
-- kept for backwards compatibility, same as f_log2_ceil()
function log2_ceil(N : natural) return positive;
......@@ -72,6 +77,9 @@ package gencores_pkg is
function f_pick (cond : std_logic; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
-- Return the maximum of L and R.
function f_max (l, r : natural) return natural;
-- Functions to convert characters and strings to upper/lower case
function to_upper(c : character) return character;
function to_lower(c : character) return character;
......@@ -209,6 +217,7 @@ package gencores_pkg is
cs_sel_i : in std_logic_vector(g_num_cs_select-1 downto 0);
load_i : in std_logic;
sclk_divsel_i : in std_logic_vector(2 downto 0);
dac_sel_i : in std_logic_vector(2 downto 0);
dac_cs_n_o : out std_logic_vector(g_num_cs_select-1 downto 0);
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic;
......@@ -885,6 +894,16 @@ package body gencores_pkg is
end if;
end f_gray_decode;
function f_log2(N : positive) return natural is
begin
for i in 0 to 30 loop
if N <= 2**i then
return i;
end if;
end loop;
report "N is too large" severity error;
end f_log2;
------------------------------------------------------------------------------
-- Returns log of 2 of a natural number
------------------------------------------------------------------------------
......@@ -1020,6 +1039,15 @@ package body gencores_pkg is
return f_pick (f_to_std_logic(cond), if_1, if_0);
end function f_pick;
function f_max (l, r : natural) return natural is
begin
if l >= r then
return l;
else
return r;
end if;
end f_max;
------------------------------------------------------------------------------
-- Functions to convert characters and strings to upper/lower case
------------------------------------------------------------------------------
......
......@@ -7,7 +7,7 @@
# with set_false_path because it has the highest priority.
set clk [get_clocks -of_objects [get_ports clk_i]]
set clk_period [get_property PERIOD $clk]
set clk_period [get_property -min PERIOD $clk]
# ATTENTION: we can't use "all_fanin" to find the source register because
# apparently this command doesn't traverse outside of scoped reference (even with -flat switch)
......
......@@ -7,7 +7,7 @@
# with set_false_path because it has the highest priority.
set clk [get_clocks -of_objects [get_ports clk_i]]
set clk_period [get_property PERIOD $clk]
set clk_period [get_property -min PERIOD $clk]
# ATTENTION: we can't use "all_fanin" to find the source register because
# apparently this command doesn't traverse outside of scoped reference (even with -flat switch)
......
......@@ -4,8 +4,8 @@
set src_clk [get_clocks -of_objects [get_ports clk_in_i]]
set dst_clk [get_clocks -of_objects [get_ports clk_out_i]]
set src_clk_period [get_property PERIOD $src_clk]
set dst_clk_period [get_property PERIOD $dst_clk]
set src_clk_period [get_property -min PERIOD $src_clk]
set dst_clk_period [get_property -min PERIOD $dst_clk]
set skew_value [expr {(($src_clk_period < $dst_clk_period) ? $src_clk_period : $dst_clk_period)}]
set src_ff [get_pins gc_sync_word_data*[*]/C]
......
......@@ -4,8 +4,8 @@
set src_clk [get_clocks -of_objects [get_ports clk_in_i]]
set dst_clk [get_clocks -of_objects [get_ports clk_out_i]]
set src_clk_period [get_property PERIOD $src_clk]
set dst_clk_period [get_property PERIOD $dst_clk]
set src_clk_period [get_property -min PERIOD $src_clk]
set dst_clk_period [get_property -min PERIOD $dst_clk]
set skew_value [expr {(($src_clk_period < $dst_clk_period) ? $src_clk_period : $dst_clk_period)}]
set src_ff [get_pins gc_sync_word_data*[*]/C]
......
......@@ -152,6 +152,7 @@ architecture syn of inferred_async_fifo is
begin -- syn
-- Protect against overflow and underflow.
rd_int <= rd_i and not empty_int;
we_int <= we_i and not full_int;
......@@ -167,9 +168,15 @@ begin -- syn
p_mem_read : process(clk_rd_i)
begin
if rising_edge(clk_rd_i) then
-- In show ahead mode, the output is valid (unless the fifo is empty), and 'rd'
-- ack the current value.
-- In no show ahead mode, the output is not valid, and 'rd' will output the value
-- on the next cycle.
if(rd_int = '1' and g_show_ahead) then
-- Read the next value.
q_int <= mem(to_integer(unsigned(rcb.bin_next(rcb.bin_next'LEFT-1 downto 0))));
elsif(rd_int = '1' or g_show_ahead) then
-- Read the current entry.
q_int <= mem(to_integer(unsigned(rcb.bin(rcb.bin'LEFT-1 downto 0))));
end if;
end if;
......@@ -243,6 +250,8 @@ begin -- syn
end if;
end process p_gen_empty;
-- Note: because of the synchronizer, wr_empty may not be fully accurate,
-- but this is usually ok (the writer shouldn't care).
gen_with_wr_empty : if g_with_wr_empty = TRUE generate
U_Sync_Empty : gc_sync_ffs
generic map (
......@@ -254,6 +263,8 @@ begin -- syn
synced_o => wr_empty_x);
end generate gen_with_wr_empty;
-- Likewise, because of the synchronizer the rd_full may not be fully
-- accurate.
gen_with_rd_full : if g_with_rd_full = TRUE generate
U_Sync_Full : gc_sync_ffs
generic map (
......@@ -272,10 +283,12 @@ begin -- syn
begin
if ((wcb.bin (wcb.bin'LEFT-1 downto 0) = rcb.bin_x(rcb.bin_x'LEFT-1 downto 0))
and (wcb.bin(wcb.bin'LEFT) /= rcb.bin_x(rcb.bin_x'LEFT))) then
-- It's already full!
going_full <= '1';
elsif (we_int = '1'
and (wcb.bin_next(wcb.bin'LEFT-1 downto 0) = rcb.bin_x(rcb.bin_x'LEFT-1 downto 0))
and (wcb.bin_next(wcb.bin'LEFT) /= rcb.bin_x(rcb.bin_x'LEFT))) then
-- Will probably be full (useless there is a read, but we are conservative)
going_full <= '1';
else
going_full <= '0';
......