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 (51)
Showing
with 1163 additions and 241 deletions
modules = {
"local" : [
"modules/axi",
"modules/common",
"modules/genrams",
"modules/wishbone",
......
......@@ -21,7 +21,9 @@ In [modules/common](modules/common) there are general purpose cores:
doesn't ensure coherency between these signals.
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)
[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
data.
To pass one pulse from one domain to another, use module
[gc_pulse_synchronizer](modules/common/gc_pulse_synchronizer.vhd)
......@@ -110,3 +112,101 @@ In [modules/common](modules/common) there are general purpose cores:
- [gc_frequency_meter](modules/common/gc_frequency_meter.vhd) provides a
single channel counter.
- [gc_multichannel_frequency_meter](modules/common/gc_multichannel_frequency_meter.vhd) is an optimized version for multiple channels.
In [modules/genrams](modules/genrams) there are fifo and ram cores:
The convention is to use generic_xxx modules whose implementation may depend
on the target.
* The package [genram_pkg](modules/genrams/genram_pkg.vhd) declares ram types,
utility functions and the components.
* The package [memory_loader_pkg](modules/genrams/memory_loader_pkg.vhd)
declares functions that reads data from a file. They are useful to
initialize the rams (and can be used for synthesis).
* The module generic_spram available for
[altera](modules/genrams/altera/generic_spram.vhd) and for
[xilinx](modules/genrams/xilinx/generic_spram.vhd) is a simple port synchronous
ram.
* The module generic_simple_dpram available for
[altera](modules/genrams/altera/generic_simple_dpram.vhd) and for
[xilinx](modules/genrams/xilinx/generic_simple_dpram.vhd) is a dual port,
dual clock, synchronous ram. The port A is write-only, the port B is
read-only.
* The module generic_dpram available for
[altera](modules/genrams/altera/generic_dpram.vhd) and for
[xilinx](modules/genrams/xilinx/generic_dpram.vhd) is a dual port,
dual clock, synchronous ram. Both ports are read/write.
* The module generic_dpram_mixed available for
[altera](modules/genrams/altera/generic_dpram_mixed.vhd) is a dual port,
dual clock, synchronous ram. Both ports are read/write, and the size of
the ports can be different.
* The module [generic_sync_fifo](modules/genrams/generic/generic_sync_fifo.vhd)
is a synchronous fifo, with multiple flags available.
* The module [generic_async_fifo](modules/genrams/generic/generic_async_fifo.vhd)
is also a fifo with multiple flags available, but with different clocks for
inputs and outputs.
* The module [generic_async_fifo_dual_rst](modules/genrams/generic/generic_async_fifo_dual_rst.vhd)
is also a fifo with multiple flags available, but with different clocks for
inputs and outputs and with a reset input for each clock domain.
* The module [generic_shiftreg_fifo](modules/genrams/common/generic_shiftreg_fifo.vhd)
is a synchronous fifo based on shift registers.
Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
* The package [wishbone_pkg](modules/wishbone/wishbone_pkg.vhd) declare
the records for the wishbone bus and some utilities.
* There are several peripherals:
- [wb_dma](modules/wishbone/wb_dma) is a dma controller.
- [wb_dpram](modules/wishbone/wb_dpram) is a dual port ram controlled by two
wishbone buses.
- [wb_gpio_port](modules/wishbone/wb_gpio_port) is a gpio controller.
- [wb_i2c_bridge](modules/wishbone/wb_i2c_bridge) is an i2c slave to
wishbone master.
- [wb_i2c_master]](modules/wishbone/wb_i2c_master) is an i2c master.
- [wb_irq](modules/wishbone/wb_irq) contains irq controllers and generators.
- [wb_onewire_master](modules/wishbone/wb_onewire_master) is a onewire master.
- [wb_serial_lcd](modules/wishbone/wb_serial_lcd) is an lcd controller.
- [wb_simple_pwm](modules/wishbone/wb_simple_pwm) is a pwm controller supporting
up to 8 channels.
- [wb_simple_timer](modules/wishbone/wb_simple_timer) is a simple counter.
- [wb_spi](modules/wishbone/wb_spi) is an spi controller
- [wb_spi_flash](modules/wishbone/wb_spi_flash) is an spi flash controller
- [wb_uart](modules/wishbone/wb_uart) is an uart.
- [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.
* There are utilities to handle a wishbone bus:
- [wb_clock_crossing](modules/wishbone/wb_clock_crossing) handle clock domain
crossing.
- [wb_register](modules/wishbone/wb_register) add a pipeline register.
* There are modules to convert to a different bus
- [wb_async_bridge](modules/wishbone/wb_async_bridge) is a bridge with the
AT91SAM9x CPU external bus interface.
- [wb_axi4lite_bridge](modules/wishbone/wb_axi4lite_bridge) is an axi4lite
to wishbone bridge
* There a modules to build a bus hierarchy:
- [wb_bus_fanout](modules/wishbone/wb_bus_fanout) is a simple master to
multiple slave decoder.
- [wb_crossbar](modules/wishbone/wb_crossbar) is a generic multiple masters
and multiple slaves crossbar.
- [wb_split](modules/wishbone/wb_split) is a very simple crossbar for 1
master and 2 slaves.
- [wb_remapper](modules/wishbone/wb_remapper) allows to remap addresses.
- [wb_conmax](modules/wishbone/wb_conmax) is an interconnect matrix,
superseeded by the crossbar.
- [wb_metadata](modules/wishbone/wb_metadata) is a little helper to
create metadata for the convention.
......@@ -147,6 +147,13 @@ Note that if ACK is combinational, a transaction requires at least 2 cycles:
{name: 'ack', wave: '0.10'}
]}
_
_| |_
____ __
_^ v____/ \__[]
_____ ____
X_____X____
For block read/write, STB has to be deasserted before starting a transfer:
{signal: [
......
modules = { "local" : [
"z7_axi_gpio_expander",
"axi4lite_wb_bridge",
]}
files = [
"axi4_pkg.vhd"
]
files = [
"xaxi4lite_wb_bridge.vhd",
];
files = [
"axi_gpio_expander.vhd",
];
-------------------------------------------------------------------------------
-- Title : AXI PS_GPIO Expander for Zynq-7
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : axi_gpio_expander.vhd
-- Author : Grzegorz Daniluk <grzegorz.daniluk@cern.ch>
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Description:
--
-- This module can be used with Zynq-7 platforms to access PS GPIOs (MIO) from
-- PL. It implements AXI-Lite Master interface that controlls (through internal
-- PS AXI interconnect) PS GPIO AXI slave to ensure transparent I/O access for PL.
-- The module should be connected to AXI Slave port of PS (S_AXI_GP*).
-- The module requires PS to be initialized, i.e. ps7_init() and
-- ps7_post_config() have to be executed either by the FSBL or custom
-- bare metal software.
--
-------------------------------------------------------------------------------
-- Copyright (c) 2019 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 ieee.numeric_std.all;
use ieee.std_logic_misc.all;
use work.axi4_pkg.all;
entity axi_gpio_expander is
generic (
g_num : integer := 8);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
error_o : out std_logic;
gpio_out : in std_logic_vector(g_num-1 downto 0);
gpio_oe : in std_logic_vector(g_num-1 downto 0);
gpio_dir : in std_logic_vector(g_num-1 downto 0); -- '1' for output
gpio_in : out std_logic_vector(g_num-1 downto 0);
ARVALID : out std_logic;
AWVALID : out std_logic;
BREADY : out std_logic;
RREADY : out std_logic;
WVALID : out std_logic;
ARADDR : out std_logic_vector (31 downto 0);
AWADDR : out std_logic_vector (31 downto 0);
WDATA : out std_logic_vector (31 downto 0);
WSTRB : out std_logic_vector (3 downto 0);
ARREADY : in std_logic;
AWREADY : in std_logic;
BVALID : in std_logic;
RLAST : in std_logic;
RVALID : in std_logic;
WREADY : in std_logic;
BRESP : in std_logic_vector (1 downto 0);
RRESP : in std_logic_vector (1 downto 0);
RDATA : in std_logic_vector (31 downto 0));
end axi_gpio_expander;
architecture behav of axi_gpio_expander is
-------------------------------------------
-- Zynq-7 PS GPIO parameters
-------------------------------------------
constant c_GPIOPS_BASE : unsigned := x"e000a000";
-- GPIO PS control registers
type t_gpiops_adr is array (natural range <>) of std_logic_vector(31 downto 0);
constant c_GPIOPS_R_OUT : t_gpiops_adr(0 to 1) := (x"e000a040", x"e000a044");
constant c_GPIOPS_R_IN : t_gpiops_adr(0 to 1) := (x"e000a060", x"e000a064");
constant c_GPIOPS_R_DIR : t_gpiops_adr(0 to 1) := (x"e000a204", x"e000a244");
constant c_GPIOPS_R_OEN : t_gpiops_adr(0 to 1) := (x"e000a208", x"e000a248");
constant c_GPIOPS_BANK0 : integer := 32;
constant c_GPIOPS_BANK1 : integer := 54;
-------------------------------------------
-------------------------------------------
function pad_data (data : std_logic_vector; pad : std_logic)
return std_logic_vector is
variable tmp : std_logic_vector(31 downto 0);
begin
if data'length = 32 then
return data;
elsif data'length < 32 then
tmp(31 downto data'length) := (others=>pad);
tmp(data'length-1 downto 0) := data;
end if;
return tmp;
end function;
-------------------------------------------
function f_split_bank (gpio_dat : std_logic_vector; bank : integer)
return std_logic_vector is
begin
if (bank = 0 and g_num < 32) then
return pad_data(gpio_dat, '0');
elsif (bank = 1 and g_num <= 32) then
return x"00000000"; -- return empty word if there is no Bank1
elsif (bank = 0 and g_num >= 32) then
return gpio_dat(c_GPIOPS_BANK0-1 downto 0);
elsif (bank = 1 and g_num > 32) then
return pad_data(gpio_dat(g_num-1 downto c_GPIOPS_BANK0), '0');
end if;
end function;
-------------------------------------------
function f_update_prev (orig : std_logic_vector; new_val : std_logic_vector; bank : integer)
return std_logic_vector is
variable tmp : std_logic_vector(g_num-1 downto 0);
begin
tmp := orig;
if (bank = 0 and g_num <= c_GPIOPS_BANK0) then
-- there is no Bank1, everythin in _prev needs to be updated
tmp := new_val(g_num-1 downto 0);
elsif (bank = 0 and g_num > c_GPIOPS_BANK0) then
tmp(c_GPIOPS_BANK0-1 downto 0) := new_val(c_GPIOPS_BANK0-1 downto 0);
elsif (bank = 1 and g_num > c_GPIOPS_BANK0) then
tmp(g_num-1 downto c_GPIOPS_BANK0) := new_val(g_num-1 downto c_GPIOPS_BANK0);
end if;
return tmp;
end function;
-------------------------------------------
function f_update_gpio_in (orig : std_logic_vector; rdata : std_logic_vector; bank : integer)
return std_logic_vector is
variable tmp : std_logic_vector(g_num-1 downto 0);
begin
tmp := orig;
if (bank = 0 and g_num >= c_GPIOPS_BANK0) then
tmp(c_GPIOPS_BANK0-1 downto 0) := rdata;
elsif (bank = 0 and g_num < c_GPIOPS_BANK0) then
tmp := rdata(g_num-1 downto 0);
else
tmp(g_num-1 downto c_GPIOPS_BANK0) := rdata(g_num-c_GPIOPS_BANK0-1 downto 0);
end if;
return tmp;
end function;
-------------------------------------------
type t_state is (IDLE, INIT_READ, READ, INIT_WRITE_DIR, WRITE_DIR,
INIT_WRITE_TRI, WRITE_TRI, INIT_WRITE_OUT, WRITE_OUT, CHANGE_BANK);
signal state : t_state;
signal gpio_in_reg : std_logic_vector(g_num-1 downto 0);
signal gpio_oe_prev : std_logic_vector(g_num-1 downto 0);
signal gpio_dir_prev : std_logic_vector(g_num-1 downto 0);
signal gpio_out_prev : std_logic_vector(g_num-1 downto 0);
signal gpio_oe_changed : std_logic_vector(1 downto 0);
signal gpio_dir_changed : std_logic_vector(1 downto 0);
signal gpio_out_changed : std_logic_vector(1 downto 0);
signal refresh_all : std_logic;
signal current_bank : integer range 0 to 1;
begin
gpio_oe_changed (0) <= or_reduce(f_split_bank(gpio_oe, 0) xor f_split_bank(gpio_oe_prev, 0));
gpio_dir_changed(0) <= or_reduce(f_split_bank(gpio_dir, 0) xor f_split_bank(gpio_dir_prev, 0));
gpio_out_changed(0) <= or_reduce(f_split_bank(gpio_out, 0) xor f_split_bank(gpio_out_prev, 0));
gpio_oe_changed (1) <= or_reduce(f_split_bank(gpio_oe, 1) xor f_split_bank(gpio_oe_prev, 1));
gpio_dir_changed(1) <= or_reduce(f_split_bank(gpio_dir, 1) xor f_split_bank(gpio_dir_prev, 1));
gpio_out_changed(1) <= or_reduce(f_split_bank(gpio_out, 1) xor f_split_bank(gpio_out_prev, 1));
gpio_in <= gpio_in_reg;
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
ARVALID <= '0';
ARADDR <= (others=>'X');
RREADY <= '0';
AWVALID <= '0';
AWADDR <= (others=>'X');
WVALID <= '0';
WDATA <= (others=>'X');
WSTRB <= "0000";
BREADY <= '0';
error_o <= '0';
gpio_in_reg <= (others=>'0');
gpio_oe_prev <= (others=>'0');
gpio_dir_prev <= (others=>'0');
gpio_out_prev <= (others=>'0');
refresh_all <= '1';
current_bank <= 0;
state <= IDLE;
else
case state is
-------------------------------------------
when IDLE =>
ARVALID <= '0';
ARADDR <= (others=>'X');
RREADY <= '0';
AWVALID <= '0';
AWADDR <= (others=>'X');
WVALID <= '0';
WDATA <= (others=>'X');
WSTRB <= "0000";
BREADY <= '0';
-- decide where to go depending what has changed
if (refresh_all = '1') then
state <= INIT_WRITE_DIR;
elsif (gpio_dir_changed(current_bank) = '1') then
state <= INIT_WRITE_DIR;
elsif (gpio_oe_changed(current_bank) = '1') then
state <= INIT_WRITE_TRI;
elsif (gpio_out_changed(current_bank) = '1') then
state <= INIT_WRITE_OUT;
else
state <= INIT_READ;
end if;
-------------------------------------------
-- set the direction of I/Os
-------------------------------------------
when INIT_WRITE_DIR =>
-- AXI: set address for write cycle
AWVALID <= '1';
AWADDR <= c_GPIOPS_R_DIR(current_bank);
-- AXI: set data for write cycle
WVALID <= '1';
WDATA <= f_split_bank(gpio_dir, current_bank);
WSTRB <= "1111";
BREADY <= '0';
gpio_dir_prev <= f_update_prev(gpio_dir_prev, gpio_dir, current_bank);
state <= WRITE_DIR;
-------------------------------------------
when WRITE_DIR =>
BREADY <= '1';
if (AWREADY = '1') then
AWVALID <= '0';
end if;
if (WREADY = '1') then
WVALID <= '0';
end if;
if (BVALID = '1' and BRESP = c_AXI4_RESP_OKAY) then
-- write accepted, let's proceed
BREADY <= '0';
state <= INIT_WRITE_TRI;
elsif (BVALID = '1') then
-- error on write, let's retry
BREADY <= '0';
refresh_all <= '1';
error_o <= '1';
state <= IDLE;
end if;
-------------------------------------------
-- set Output Enable (Tristate Buffs) for I/Os
-------------------------------------------
when INIT_WRITE_TRI =>
-- AXI: set address for write cycle
AWVALID <= '1';
AWADDR <= c_GPIOPS_R_OEN(current_bank);
-- AXI: set data for write cycle
WVALID <= '1';
WDATA <= f_split_bank(gpio_oe, current_bank);
WSTRB <= "1111";
BREADY <= '0';
gpio_oe_prev <= f_update_prev(gpio_oe_prev, gpio_oe, current_bank);
state <= WRITE_TRI;
-------------------------------------------
when WRITE_TRI =>
BREADY <= '1';
if (AWREADY = '1') then
AWVALID <= '0';
end if;
if (WREADY = '1') then
WVALID <= '0';
end if;
if (BVALID = '1' and BRESP = c_AXI4_RESP_OKAY and (refresh_all = '1' or gpio_out_changed(current_bank) = '1')) then
-- write accepted, let's proceed
BREADY <= '0';
state <= INIT_WRITE_OUT;
elsif (BVALID = '1' and BRESP = c_AXI4_RESP_OKAY) then
-- nothing to update in GPIO_OUT, skip to GPIO reading
BREADY <= '0';
state <= INIT_READ;
elsif (BVALID = '1') then
-- error on write, let's retry
BREADY <= '0';
refresh_all <= '1';
error_o <= '1';
state <= IDLE;
end if;
-------------------------------------------
-- set state of outputs
-------------------------------------------
when INIT_WRITE_OUT =>
-- AXI: set address for write cycle
AWVALID <= '1';
AWADDR <= c_GPIOPS_R_OUT(current_bank);
-- AXI: set data for write cycle
WVALID <= '1';
WDATA <= f_split_bank(gpio_out, current_bank);
WSTRB <= "1111";
BREADY <= '0';
gpio_out_prev <= f_update_prev(gpio_out_prev, gpio_out, current_bank);
state <= WRITE_OUT;
-------------------------------------------
when WRITE_OUT =>
BREADY <= '1';
if (AWREADY = '1') then
AWVALID <= '0';
end if;
if (WREADY = '1') then
WVALID <= '0';
end if;
if (BVALID = '1' and BRESP = c_AXI4_RESP_OKAY) then
-- write accepted, let's proceed
BREADY <= '0';
state <= INIT_READ;
elsif (BVALID = '1') then
-- error on write, let's retry
BREADY <= '0';
refresh_all <= '1';
error_o <= '1';
state <= IDLE;
end if;
-------------------------------------------
-- get state of inputs
-------------------------------------------
when INIT_READ =>
AWVALID <= '0';
AWADDR <= (others=>'X');
WVALID <= '0';
WDATA <= (others=>'X');
WSTRB <= "0000";
BREADY <= '0';
-- AXI: set address for read cycle
ARVALID <= '1';
ARADDR <= c_GPIOPS_R_IN(current_bank);
-- AXI: ready to accept data from slave
RREADY <= '1';
state <= READ;
-------------------------------------------
when READ =>
RREADY <= '1';
if (ARREADY = '1') then
-- AXI: address received by slave
ARVALID <= '0';
end if;
if (RVALID = '1' and RRESP = c_AXI4_RESP_OKAY) then
RREADY <= '0';
-- received valid data, pass it to I/Os
gpio_in_reg <= f_update_gpio_in(gpio_in_reg, RDATA, current_bank);
error_o <= '0';
state <= CHANGE_BANK;
elsif (RVALID = '1') then
RREADY <= '0';
-- error on read
error_o <= '1';
state <= IDLE;
end if;
-------------------------------------------
-- change I/O bank if needed
-------------------------------------------
when CHANGE_BANK =>
ARVALID <= '0';
ARADDR <= (others=>'X');
RREADY <= '0';
AWVALID <= '0';
AWADDR <= (others=>'X');
WVALID <= '0';
WDATA <= (others=>'X');
WSTRB <= "0000";
BREADY <= '0';
if (current_bank = 1) then
refresh_all <= '0';
current_bank <= 0;
elsif (g_num > c_GPIOPS_BANK0) then
-- Don't touch refresh_all flag yet, if it's the first cycle, full
-- config setting has to be done for both banks.
current_bank <= 1;
else -- current_bank = 0 and g_num =< c_GPIOPS_BANK0
-- Only Bank0 is used, reset refresh_all flag, Bank0 registers are
-- all set here.
refresh_all <= '0';
end if;
state <= IDLE;
end case;
end if;
end if;
end process;
end behav;
......@@ -31,6 +31,9 @@ files = [
"gc_dec_8b10b.vhd",
"gc_dyn_extend_pulse.vhd",
"gc_ds182x_interface.vhd",
"gc_ds182x_readout.vhd",
"gc_ds182x_readout/gc_ds182x_readout.vhd",
"gc_sfp_i2c_adapter.vhd",
"gc_async_counter_diff.vhd",
"gc_sync_word_wr.vhd",
"gc_sync_word_rd.vhd",
];
--------------------------------------------------------------------------------
-- CERN
-- general-cores
-- https://www.ohwr.org/project/general-cores
--------------------------------------------------------------------------------
--
-- unit name : gc_async_counter_diff.vhd
-- author : Tomasz Wlostowski
-- description:
--
-- The module counts pulses on inc_i and dec_i inputs. Each input can be
-- in its own clock domain. The module outputs difference in the number of
-- pulses counted on inc_i and dec_i. The output is in the clock domain
-- selected with the g_output_clock generic (that of inc_i or of dec_i).
--
-- Internally, Grey Codes are used and count encoded with Grey Code is
-- resynchronized to the output clock domain. Therefore, the output
-- is provided few clock cycles after pulse actually occured.
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN BE/CO/HT
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- 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;
use work.gencores_pkg.all;
entity gc_async_counter_diff is
generic (
g_bits : integer := 8;
g_output_clock : string := "inc"
);
port
(
-- reset (g_output_clock clock domain)
rst_n_i : in std_logic;
-- increment clock
clk_inc_i : in std_logic;
-- decrement clock
clk_dec_i : in std_logic;
-- increment enable (clk_inc_i clock domain)
inc_i : in std_logic;
-- decrement enable (clk_inc_i clock domain)
dec_i : in std_logic;
-- current counter value, signed (g_output_clock clock domain)
counter_o : out std_logic_vector(g_bits downto 0)
);
end gc_async_counter_diff;
architecture rtl of gc_async_counter_diff is
signal cnt1_bin, cnt2_bin : unsigned(g_bits downto 0);
signal cnt1_gray, cnt2_gray : std_logic_vector(g_bits downto 0);
signal cnt1_gray_out : std_logic_vector(g_bits downto 0);
signal cnt2_gray_out : std_logic_vector(g_bits downto 0);
signal rst_n_inc, rst_n_dec : std_logic;
begin
U_SyncReset_to_IncClk : gc_sync_ffs
port map (
clk_i => clk_inc_i,
rst_n_i => '1',
data_i => rst_n_i,
synced_o => rst_n_inc);
U_SyncReset_to_DecClk : gc_sync_ffs
port map (
clk_i => clk_dec_i,
rst_n_i => '1',
data_i => rst_n_i,
synced_o => rst_n_dec);
p_count_up : process(clk_inc_i)
begin
if rising_edge(clk_inc_i) then
if rst_n_inc = '0' then
cnt1_bin <= (others => '0');
cnt1_gray <= (others => '0');
else
if inc_i = '1' then
cnt1_bin <= cnt1_bin + 1;
end if;
cnt1_gray <= f_gray_encode(std_logic_vector(cnt1_bin));
end if;
end if;
end process;
p_count_down : process(clk_dec_i)
begin
if rising_edge(clk_dec_i) then
if rst_n_dec = '0' then
cnt2_bin <= (others => '0');
cnt2_gray <= (others => '0');
else
if dec_i = '1' then
cnt2_bin <= cnt2_bin + 1;
end if;
cnt2_gray <= f_gray_encode(std_logic_vector(cnt2_bin));
end if;
end if;
end process;
gen_out_clock_is_inc : if g_output_clock = "inc" generate
cnt1_gray_out <= cnt1_gray;
U_Sync : gc_sync_register
generic map (
g_width => g_bits+1)
port map (
clk_i => clk_inc_i,
rst_n_a_i => rst_n_i,
d_i => cnt2_gray,
q_o => cnt2_gray_out);
end generate gen_out_clock_is_inc;
gen_out_clock_is_dec : if g_output_clock = "dec" generate
cnt2_gray_out <= cnt2_gray;
U_Sync : gc_sync_register
generic map (
g_width => g_bits+1)
port map (
clk_i => clk_dec_i,
rst_n_a_i => rst_n_i,
d_i => cnt1_gray,
q_o => cnt1_gray_out);
end generate gen_out_clock_is_dec;
counter_o <= std_logic_vector(unsigned(cnt2_gray_out) - unsigned(cnt1_gray_out));
end rtl;
## gc_ds182x_readout
The gc_ds182x_readout core provides a direct interface to the high-precision 1-wire digital termometer DS1820 chip.
The temperature is read every second. The read process is either triggered by the `pps_p_i` input or started automatically from the clock if the generic `g_USE_INTERNAL_PPS` is set to True. Note that the DS18B20 chip needs up to 750ms to read the temperature.
It is important to correctly set the frequency as the 1-wire protocol is time based.
When using the DS18B20 (like on the SPEC), the temperature is in 1/16 degrees.
\ No newline at end of file
......@@ -59,8 +59,8 @@ architecture arch of gc_ds182x_readout is
constant SLOT_CNT_START : unsigned(15 downto 0) := to_unsigned(0*g_CLOCK_FREQ_KHZ/40000, 16);
constant SLOT_CNT_START_PLUSONE : unsigned(15 downto 0) := SLOT_CNT_START + 1;
constant SLOT_CNT_SET : unsigned(15 downto 0) := to_unsigned(60*g_CLOCK_FREQ_KHZ/40000, 16);
constant SLOT_CNT_RD : unsigned(15 downto 0) := to_unsigned(600*g_CLOCK_FREQ_KHZ/40000, 16);
constant SLOT_CNT_STOP : unsigned(15 downto 0) := to_unsigned(3600*g_CLOCK_FREQ_KHZ/40000, 16);
constant SLOT_CNT_RD : unsigned(15 downto 0) := to_unsigned(600*g_CLOCK_FREQ_KHZ/40000, 16); -- 15us
constant SLOT_CNT_STOP : unsigned(15 downto 0) := to_unsigned(3600*g_CLOCK_FREQ_KHZ/40000, 16); -- 90us
constant SLOT_CNT_PRESTOP : unsigned(15 downto 0) := to_unsigned((3600-60)*g_CLOCK_FREQ_KHZ/40000, 16);
constant READ_ID_HEADER : std_logic_vector(7 downto 0) := X"33";
......@@ -225,6 +225,7 @@ begin
case state_op is
when READ_ID_OP =>
-- Read the ROM (unique ID). This is done once after reset.
header <= READ_ID_HEADER;
bit_top <= ID_LGTH;
if state_cm = IDLE_CM then
......@@ -232,14 +233,17 @@ begin
end if;
when CONV_OP1 =>
-- Start conversion.
header <= CONVERT_HEADER;
cm_only <= '1';
when SKIP_ROM_OP1 =>
-- Skip rom to directly reads the registers.
header <= SKIPHEADER;
cm_only <= '1';
when READ_TEMP_OP =>
-- Read registers
header <= READ_TEMPER_HEADER;
bit_top <= TEMPER_LGTH;
if state_cm = IDLE_CM then
......@@ -247,10 +251,12 @@ begin
end if;
when SKIP_ROM_OP2 =>
-- Skip rom to directly reads the registers.
header <= SKIPHEADER;
cm_only <= '1';
when CONV_OP2 =>
-- Start conversion.
header <= CONVERT_HEADER;
cm_only <= '1';
......@@ -364,11 +370,13 @@ begin
crc_ok <= '0';
case state_cm is
when RST_CM =>
-- Reset pulse.
rst_bit_cnt <= '1';
nx_serial_id_out <= '0';
nx_serial_id_oe <= '1';
init <= start_p;
when PREP_WR_CM =>
-- Presence pulse.
rst_bit_cnt <= start_p;
nx_serial_id_oe <= '0';
nx_serial_id_out <= '0';
......
-------------------------------------------------------------------------------
-- Title : Frequency meter
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : gc_frequency_meter.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Copyright (c) 2012-2015 CERN
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_frequency_meter
--
-- description: Frequency meter with internal or external timebase.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2012-2019
--------------------------------------------------------------------------------
-- 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.
-- 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
-- "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;
......@@ -31,86 +31,79 @@ library work;
use work.gencores_pkg.all;
entity gc_frequency_meter is
generic(
g_with_internal_timebase : boolean := true;
g_clk_sys_freq : integer;
g_counter_bits : integer := 32);
port(
generic (
g_WITH_INTERNAL_TIMEBASE : boolean := TRUE;
g_CLK_SYS_FREQ : integer;
-- if true, sync freq_o to the clk_sys domain
g_SYNC_OUT : boolean := FALSE;
g_COUNTER_BITS : integer := 32);
port (
clk_sys_i : in std_logic;
clk_in_i : in std_logic;
rst_n_i : in std_logic;
rst_n_i : in std_logic; -- not used, kept for backward compatibility
pps_p1_i : in std_logic;
freq_o : out std_logic_vector(g_counter_bits-1 downto 0);
freq_valid_o : out std_logic
);
-- synced to clk_in_i or clk_sys_i, depending on g_SYNC_OUT value
freq_o : out std_logic_vector(g_COUNTER_BITS-1 downto 0);
-- synced to clk_sys_i, always
freq_valid_o : out std_logic);
end gc_frequency_meter;
architecture arch of gc_frequency_meter is
architecture behavioral of gc_frequency_meter is
signal gate_pulse, gate_pulse_synced : std_logic := '0';
signal gate_pulse, gate_pulse_synced : std_logic;
signal cntr_gate : unsigned(g_COUNTER_BITS-1 downto 0) := (others => '0');
signal cntr_meas : unsigned(g_COUNTER_BITS-1 downto 0) := (others => '0');
signal cntr_gate : unsigned(g_counter_bits-1 downto 0);
signal cntr_meas : unsigned(g_counter_bits-1 downto 0);
signal freq_reg : std_logic_vector(g_counter_bits-1 downto 0);
signal freq_reg : std_logic_vector(g_COUNTER_BITS-1 downto 0) := (others => '0');
begin
gen_internal_timebase : if(g_with_internal_timebase = true) generate
gen_internal_timebase : if g_WITH_INTERNAL_TIMEBASE = TRUE generate
p_gate_counter : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
if cntr_gate = g_CLK_SYS_FREQ-1 then
cntr_gate <= (others => '0');
gate_pulse <= '0';
gate_pulse <= '1';
else
if(cntr_gate = g_clk_sys_freq-1) then
cntr_gate <= (others => '0');
gate_pulse <= '1';
else
cntr_gate <= cntr_gate + 1;
gate_pulse <= '0';
end if;
cntr_gate <= cntr_gate + 1;
gate_pulse <= '0';
end if;
end if;
end process;
U_Sync_Gate : gc_pulse_synchronizer
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_in_i,
rst_n_i => rst_n_i,
d_ready_o => freq_valid_o,
d_p_i => gate_pulse,
q_p_o => gate_pulse_synced);
U_Sync_Gate : gc_pulse_synchronizer
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_in_i,
rst_n_i => '1',
d_ready_o => freq_valid_o,
d_p_i => gate_pulse,
q_p_o => gate_pulse_synced);
end generate gen_internal_timebase;
gen_external_timebase : if(g_with_internal_timebase = false) generate
gen_external_timebase : if g_WITH_INTERNAL_TIMEBASE = FALSE generate
U_Sync_Gate : gc_pulse_synchronizer
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_in_i,
rst_n_i => rst_n_i,
d_ready_o => freq_valid_o,
d_p_i => pps_p1_i,
q_p_o => gate_pulse_synced);
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_in_i,
rst_n_i => '1',
d_ready_o => freq_valid_o,
d_p_i => pps_p1_i,
q_p_o => gate_pulse_synced);
end generate gen_external_timebase;
p_freq_counter : process (clk_in_i, rst_n_i)
p_freq_counter : process (clk_in_i)
begin
if rst_n_i = '0' then -- asynchronous reset (active low)
cntr_meas <= (others => '0');
freq_reg <= (others => '0');
elsif rising_edge(clk_in_i) then
if(gate_pulse_synced = '1') then
if rising_edge(clk_in_i) then
if gate_pulse_synced = '1' then
freq_reg <= std_logic_vector(cntr_meas);
cntr_meas <= (others => '0');
else
......@@ -119,7 +112,22 @@ begin
end if;
end process p_freq_counter;
freq_o <= freq_reg;
end behavioral;
gen_with_sync_out : if g_SYNC_OUT generate
cmp_gc_sync_word_wr : gc_sync_word_wr
generic map (
g_AUTO_WR => TRUE,
g_WIDTH => g_COUNTER_BITS)
port map (
clk_in_i => clk_in_i,
rst_in_n_i => '1',
clk_out_i => clk_sys_i,
rst_out_n_i => '1',
data_i => freq_reg,
data_o => freq_o);
end generate gen_with_sync_out;
gen_without_sync_out : if not g_SYNC_OUT generate
freq_o <= freq_reg;
end generate gen_without_sync_out;
end arch;
......@@ -40,6 +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.
d_ack_p_o : out std_logic;
-- pulse input (clk_in_i domain)
d_p_i : in std_logic;
-- pulse output (clk_out_i domain)
......@@ -49,9 +53,13 @@ end gc_pulse_synchronizer2;
architecture rtl of gc_pulse_synchronizer2 is
signal ready, d_p_d0 : std_logic;
signal in_ext, out_ext : std_logic;
signal out_feedback : std_logic;
signal ready : std_logic := '1';
signal d_ack : std_logic := '1';
signal d_ack_d0 : std_logic := '0';
signal d_p_d0 : std_logic := '0';
signal in_ext : std_logic := '0';
signal out_ext : std_logic := '0';
signal out_feedback : std_logic := '0';
begin -- rtl
......@@ -73,27 +81,33 @@ begin -- rtl
npulse_o => open,
ppulse_o => open);
p_input_ack : process(clk_in_i, rst_in_n_i)
p_input_ack : process(clk_in_i)
begin
if rst_in_n_i = '0' then
ready <= '1';
in_ext <= '0';
d_p_d0 <= '0';
elsif rising_edge(clk_in_i) then
if rising_edge(clk_in_i) then
d_p_d0 <= d_p_i;
d_p_d0 <= d_p_i;
d_ack_d0 <= d_ack;
if ready = '1' and d_p_i = '1' and d_p_d0 = '0'then
in_ext <= '1';
d_ack <= '0';
ready <= '0';
elsif in_ext = '1' and out_feedback = '1' then
in_ext <= '0';
elsif in_ext = '0' and out_feedback = '0' then
d_ack <= '1';
ready <= '1';
end if;
if ready = '0' then
assert d_p_i = '0' or (d_p_i = '1' and d_p_d0 = '1')
report "request while previous one not completed"
severity ERROR;
end if;
end if;
end process p_input_ack;
d_ack_p_o <= d_ack and not d_ack_d0;
d_ready_o <= ready;
end rtl;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_sync_word_rd
--
-- description: Synchronizer for reading a word with an ack.
--
-- Used to transfer a word from the output clock domain to the input clock
-- domain. The user provided data is constantly read. When a read request
-- arrives (on the output side), the user data is frozen (not read anymore),
-- and sent to the output side. A pulse is generated on the output side
-- when the transfer is done, and the data is unfrozen. A pulse is also
-- generated on the input side.
--
--------------------------------------------------------------------------------
-- Copyright CERN 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.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
entity gc_sync_word_rd is
generic (
g_WIDTH : positive := 8);
port (
-- Output clock and reset (wishbone side)
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
-- Input clock and reset (user side)
clk_in_i : in std_logic;
rst_in_n_i : in std_logic;
-- Input data (user side)
data_in_i : in std_logic_vector (g_WIDTH - 1 downto 0);
-- Trigger a read (wishbone side)
rd_out_i : in std_logic := '0';
-- Pulse when the read is available (wishbone side)
ack_out_o : out std_logic;
-- Output data (wishbone side)
data_out_o : out std_logic_vector (g_WIDTH - 1 downto 0);
-- Pulse when a data is transfered (user side)
rd_in_o : out std_logic);
end entity;
architecture arch of gc_sync_word_rd is
signal gc_sync_word_data :
std_logic_vector (g_WIDTH - 1 downto 0) := (others => '0');
attribute keep : string;
attribute keep of gc_sync_word_data : signal is "true";
signal d_ready : std_logic;
signal wr_in : std_logic;
signal rd_out : std_logic;
begin
cmp_pulse_sync : entity work.gc_pulse_synchronizer2
port map (
clk_in_i => clk_out_i,
rst_in_n_i => rst_out_n_i,
clk_out_i => clk_in_i,
rst_out_n_i => rst_in_n_i,
d_ready_o => d_ready,
d_ack_p_o => wr_in,
d_p_i => rd_out_i,
q_p_o => rd_out);
p_reader : process(clk_in_i)
begin
if rising_edge(clk_in_i) then
if rd_out = '1' then
gc_sync_word_data <= data_in_i;
end if;
end if;
end process;
p_writer : process (clk_out_i)
begin
if rising_edge(clk_out_i) then
if rst_in_n_i = '0' then
ack_out_o <= '0';
elsif wr_in = '1' then
-- Data is stable.
data_out_o <= gc_sync_word_data;
ack_out_o <= '1';
else
ack_out_o <= '0';
end if;
end if;
end process;
end arch;
......@@ -7,12 +7,14 @@
-- unit name: gc_sync_word_wr
--
-- description: Synchronizer for writing a word with an ack.
--
-- Used to transfer a word from the input clock domain to the output clock
-- domain. User provides the data and a pulse write signal to transfer the
-- data. When the data are transfered, a write pulse is generated on the
-- output side along with the data, and an acknowledge is generated on the
-- input side. Once the user request a transfer, no new data should be
-- requested for a transfer until the ack was received.
-- input side. Once the user requests a transfer, no new data should be
-- requested for a transfer until the ack is received. A busy flag is also
-- available for this purpose (user should not push new data if busy).
--
--------------------------------------------------------------------------------
-- Copyright CERN 2019
......@@ -31,106 +33,87 @@
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
entity gc_sync_word_wr is
generic (
width : positive := 8);
-- automatically write next word when not busy
g_AUTO_WR : boolean := FALSE;
g_WIDTH : positive := 8);
port (
-- Input clock and reset
clk_in_i : in std_logic;
rst_in_n_i : in std_logic;
-- Output clock.
-- Output clock and reset
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
rst_out_n_i : in std_logic;
-- Input data
data_i : in std_logic_vector (width - 1 downto 0);
-- Input wr
wr_i : in std_logic;
data_i : in std_logic_vector (g_WIDTH - 1 downto 0);
-- Input control and status
-- wr_i is ignored if g_AUTO_WR is set
wr_i : in std_logic := '0';
busy_o : out std_logic;
ack_o : out std_logic;
-- Output data
data_o : out std_logic_vector (width - 1 downto 0);
data_o : out std_logic_vector (g_WIDTH - 1 downto 0);
-- Output status
wr_o : out std_logic);
end entity;
architecture behav of gc_sync_word_wr is
signal data : std_logic_vector (width - 1 downto 0);
signal in_busy : std_logic;
signal start_wr : std_logic;
architecture arch of gc_sync_word_wr is
signal gc_sync_word_data :
std_logic_vector (g_WIDTH - 1 downto 0) := (others => '0');
attribute keep : string;
attribute keep of gc_sync_word_data : signal is "true";
signal d_ready : std_logic;
signal wr_in : std_logic;
signal wr_out : std_logic;
signal dat_out : std_logic_vector(g_WIDTH -1 downto 0) := (others => '0');
-- Synchronized extended wr_i signal.
signal wr_out : std_logic;
signal last_wr_out : std_logic;
signal wr_out_fb : std_logic;
signal last_wr_out_fb : std_logic;
begin
-- Handle incoming request.
process(clk_in_i)
wr_in <= d_ready when g_AUTO_WR else wr_i;
cmp_pulse_sync : gc_pulse_synchronizer2
port map (
clk_in_i => clk_in_i,
rst_in_n_i => rst_in_n_i,
clk_out_i => clk_out_i,
rst_out_n_i => rst_out_n_i,
d_ready_o => d_ready,
d_ack_p_o => ack_o,
d_p_i => wr_in,
q_p_o => wr_out);
busy_o <= not d_ready;
p_writer : process(clk_in_i)
begin
if rising_edge(clk_in_i) then
if rst_in_n_i = '0' then
start_wr <= '0';
in_busy <= '0';
data <= (others => '0');
ack_o <= '0';
last_wr_out_fb <= '0';
else
ack_o <= '0';
if in_busy = '0' then
if wr_i = '1' then
-- Write requested.
-- Toggle start_wr ...
start_wr <= not start_wr;
in_busy <= '1';
data <= data_i;
end if;
else
assert wr_i = '0' report "request while previous one not completed"
severity error;
-- ... and wait until wr_out_fb has been toggled.
if (wr_out_fb xor last_wr_out_fb) = '1' then
-- Set ack (for one cycle).
ack_o <= '1';
last_wr_out_fb <= wr_out_fb;
-- Ready for a new request.
in_busy <= '0';
end if;
end if;
if d_ready = '1' and wr_in = '1' then
-- Write requested, save the input data
gc_sync_word_data <= data_i;
end if;
end if;
end process;
cmp_wr_sync : entity work.gc_sync_ffs
port map (
clk_i => clk_out_i,
rst_n_i => rst_out_n_i,
data_i => start_wr,
synced_o => wr_out);
end process p_writer;
-- Outputs.
process (clk_out_i)
p_reader : process (clk_out_i)
begin
if rising_edge(clk_out_i) then
if rst_out_n_i = '0' then
data_o <= (others => '0');
wr_o <= '0';
last_wr_out <= '0';
if wr_out = '1' then
-- Data is stable.
dat_out <= gc_sync_word_data;
wr_o <= '1';
else
if (wr_out xor last_wr_out) = '1' then
-- Data are stable.
data_o <= data;
wr_o <= '1';
last_wr_out <= wr_out;
else
wr_o <= '0';
end if;
wr_o <= '0';
end if;
end if;
end process;
end process p_reader;
-- Ack.
cmp_ack_sync : entity work.gc_sync_ffs
port map (
clk_i => clk_in_i,
rst_n_i => rst_in_n_i,
data_i => wr_out,
synced_o => wr_out_fb);
end behav;
data_o <= dat_out;
end arch;
......@@ -165,6 +165,24 @@ package gencores_pkg is
busy_o : out std_logic);
end component;
------------------------------------------------------------------------------
-- Comparator
------------------------------------------------------------------------------
component gc_comparator is
generic (
g_IN_WIDTH : natural := 32);
port (
clk_i : in std_logic;
rst_n_i : in std_logic := '1';
pol_inv_i : in std_logic := '0';
enable_i : in std_logic := '1';
inp_i : in std_logic_vector(g_IN_WIDTH-1 downto 0);
inn_i : in std_logic_vector(g_IN_WIDTH-1 downto 0);
hys_i : in std_logic_vector(g_IN_WIDTH-1 downto 0) := (others => '0');
out_o : out std_logic;
out_p_o : out std_logic);
end component gc_comparator;
------------------------------------------------------------------------------
-- Synchronisation FF chain
------------------------------------------------------------------------------
......@@ -203,24 +221,46 @@ package gencores_pkg is
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
d_ready_o : out std_logic;
d_ack_p_o : out std_logic;
d_p_i : in std_logic;
q_p_o : out std_logic);
end component;
------------------------------------------------------------------------------
-- Word synchroniser
------------------------------------------------------------------------------
component gc_sync_word_wr is
generic (
g_AUTO_WR : boolean := FALSE;
g_WIDTH : positive := 8);
port (
clk_in_i : in std_logic;
rst_in_n_i : in std_logic;
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
data_i : in std_logic_vector (g_WIDTH - 1 downto 0);
wr_i : in std_logic := '0';
busy_o : out std_logic;
ack_o : out std_logic;
data_o : out std_logic_vector (g_WIDTH - 1 downto 0);
wr_o : out std_logic);
end component gc_sync_word_wr;
------------------------------------------------------------------------------
-- Frequency meters
------------------------------------------------------------------------------
component gc_frequency_meter
generic (
g_with_internal_timebase : boolean;
g_clk_sys_freq : integer;
g_counter_bits : integer);
g_WITH_INTERNAL_TIMEBASE : boolean := TRUE;
g_CLK_SYS_FREQ : integer;
g_SYNC_OUT : boolean := FALSE;
g_COUNTER_BITS : integer);
port (
clk_sys_i : in std_logic;
clk_in_i : in std_logic;
rst_n_i : in std_logic;
pps_p1_i : in std_logic;
freq_o : out std_logic_vector(g_counter_bits-1 downto 0);
freq_o : out std_logic_vector(g_COUNTER_BITS-1 downto 0);
freq_valid_o : out std_logic);
end component;
......@@ -608,6 +648,17 @@ package gencores_pkg is
id_ok_o : out std_logic);
end component gc_ds182x_readout;
component gc_dec_8b10b is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
in_10b_i : in std_logic_vector(9 downto 0);
ctrl_o : out std_logic;
code_err_o : out std_logic;
rdisp_err_o : out std_logic;
out_8b_o : out std_logic_vector(7 downto 0));
end component gc_dec_8b10b;
------------------------------------------------------------------------------
-- SFP I2C Adapter
------------------------------------------------------------------------------
......@@ -623,6 +674,22 @@ package gencores_pkg is
sfp_data_i : in std_logic_vector (127 downto 0));
end component gc_sfp_i2c_adapter;
------------------------------------------------------------------------------
-- Asynchronous counter inc/dec pulses
------------------------------------------------------------------------------
component gc_async_counter_diff is
generic (
g_bits : integer := 8;
g_output_clock : string := "inc");
port (
rst_n_i : in std_logic;
clk_inc_i : in std_logic;
clk_dec_i : in std_logic;
inc_i : in std_logic;
dec_i : in std_logic;
counter_o : out std_logic_vector(g_bits downto 0));
end component gc_async_counter_diff;
--============================================================================
-- Procedures and functions
--============================================================================
......
......@@ -124,11 +124,11 @@ architecture syn of inferred_async_fifo is
signal wr_count, rd_count : t_counter;
signal rd_int, we_int : std_logic;
signal wr_empty_x : std_logic;
signal rd_full_x : std_logic;
signal wr_empty_x : std_logic := '0';
signal rd_full_x : std_logic := '0';
signal almost_full_x : std_logic;
signal almost_empty_x : std_logic;
signal almost_full_x : std_logic := '0';
signal almost_empty_x : std_logic := '0';
signal q_int : std_logic_vector(g_data_width-1 downto 0) := (others => '0');
......@@ -225,23 +225,27 @@ begin -- syn
end if;
end process p_gen_empty;
U_Sync_Empty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => rst_n_i,
data_i => empty_int,
synced_o => wr_empty_x);
U_Sync_Full : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => rst_n_i,
data_i => full_int,
synced_o => rd_full_x);
gen_with_wr_empty : if g_with_wr_empty = TRUE generate
U_Sync_Empty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => rst_n_i,
data_i => empty_int,
synced_o => wr_empty_x);
end generate gen_with_wr_empty;
gen_with_rd_full : if g_with_rd_full = TRUE generate
U_Sync_Full : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => rst_n_i,
data_i => full_int,
synced_o => rd_full_x);
end generate gen_with_rd_full;
rd_empty_o <= empty_int;
wr_empty_o <= wr_empty_x;
......@@ -286,14 +290,16 @@ begin -- syn
end if;
end process p_reg_almost_full;
U_Sync_AlmostFull : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => rst_n_i,
data_i => almost_full_int,
synced_o => almost_full_x);
gen_with_rd_almost_full : if g_with_rd_almost_full = TRUE generate
U_Sync_AlmostFull : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => rst_n_i,
data_i => almost_full_int,
synced_o => almost_full_x);
end generate gen_with_rd_almost_full;
wr_almost_full_o <= almost_full_int;
rd_almost_full_o <= almost_full_x;
......@@ -312,14 +318,16 @@ begin -- syn
end if;
end process p_reg_almost_empty;
U_Sync_AlmostEmpty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => rst_n_i,
data_i => almost_empty_int,
synced_o => almost_empty_x);
gen_with_wr_almost_empty : if g_with_wr_almost_empty = TRUE generate
U_Sync_AlmostEmpty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => rst_n_i,
data_i => almost_empty_int,
synced_o => almost_empty_x);
end generate gen_with_wr_almost_empty;
rd_almost_empty_o <= almost_empty_int;
wr_almost_empty_o <= almost_empty_x;
......
......@@ -114,11 +114,11 @@ architecture arch of inferred_async_fifo_dual_rst is
signal wr_count, rd_count : t_counter;
signal rd_int, we_int : std_logic;
signal wr_empty_x : std_logic;
signal rd_full_x : std_logic;
signal wr_empty_x : std_logic := '0';
signal rd_full_x : std_logic := '0';
signal almost_full_x : std_logic;
signal almost_empty_x : std_logic;
signal almost_full_x : std_logic := '0';
signal almost_empty_x : std_logic := '0';
signal q_int : std_logic_vector(g_data_width-1 downto 0) := (others => '0');
......@@ -215,23 +215,28 @@ begin -- arch
end if;
end process p_gen_empty;
U_Sync_Empty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => '1',
data_i => empty_int,
synced_o => wr_empty_x);
U_Sync_Full : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => '1',
data_i => full_int,
synced_o => rd_full_x);
gen_with_wr_empty : if g_with_wr_empty = TRUE generate
U_Sync_Empty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => '1',
data_i => empty_int,
synced_o => wr_empty_x);
end generate gen_with_wr_empty;
gen_with_rd_full : if g_with_rd_full = TRUE generate
U_Sync_Full : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => '1',
data_i => full_int,
synced_o => rd_full_x);
end generate gen_with_rd_full;
rd_empty_o <= empty_int;
wr_empty_o <= wr_empty_x;
......@@ -280,14 +285,16 @@ begin -- arch
end if;
end process p_reg_almost_full;
U_Sync_AlmostFull : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => '1',
data_i => almost_full_int,
synced_o => almost_full_x);
gen_with_rd_almost_full : if g_with_rd_almost_full = TRUE generate
U_Sync_AlmostFull : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_rd_i,
rst_n_i => '1',
data_i => almost_full_int,
synced_o => almost_full_x);
end generate gen_with_rd_almost_full;
wr_almost_full_o <= almost_full_int;
rd_almost_full_o <= almost_full_x;
......@@ -308,14 +315,16 @@ begin -- arch
end if;
end process p_reg_almost_empty;
U_Sync_AlmostEmpty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => '1',
data_i => almost_empty_int,
synced_o => almost_empty_x);
gen_with_wr_almost_empty : if g_with_wr_almost_empty = TRUE generate
U_Sync_AlmostEmpty : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_wr_i,
rst_n_i => '1',
data_i => almost_empty_int,
synced_o => almost_empty_x);
end generate gen_with_wr_almost_empty;
rd_almost_empty_o <= almost_empty_int;
wr_almost_empty_o <= almost_empty_x;
......