Commit 8f6505c0 authored by Dimitris Lampridis's avatar Dimitris Lampridis

[hdl] Add edge sensitivity and async reset option to edge detectors.

This is necessary in order to properly "emulate" the previous implementation
of the gc_sync_ffs module.

Furthermore, a "new" module has been introduced, the gc_edge_detect, which
combines positive and negative pulse edge detection. gc_negedge and gc_posedge
have been rewritten to use internally the new gc_edge_detect.
Signed-off-by: Dimitris Lampridis's avatarDimitris Lampridis <dimitris.lampridis@cern.ch>
parent 72176200
......@@ -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.
......
......@@ -15,6 +15,7 @@ files = [
"gc_sync.vhd",
"gc_posedge.vhd",
"gc_negedge.vhd",
"gc_edge_detect.vhd",
"gc_sync_edge.vhd",
"gc_pulse_synchronizer.vhd",
"gc_pulse_synchronizer2.vhd",
......
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_edge_detect
--
-- description: Simple edge detector. Combinatorial.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity gc_edge_detect is
generic(
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
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
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;
......@@ -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;
......@@ -53,23 +53,15 @@ begin
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;
inst_gc_edge_detect : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => TRUE,
g_PULSE_EDGE => g_EDGE,
g_CLOCK_EDGE => "positive")
port map (
clk_i => clk_i,
rst_n_i => rst_n_a_i,
data_i => sync,
pulse_o => pulse_o);
sync_negedge : if g_EDGE = "negative" generate
inst_pedge : entity work.gc_negedge
port map (
clk_i => clk_i,
rst_n_i => rst_n_a_i,
data_i => sync,
pulse_o => pulse_o);
end generate;
end architecture arch;
......@@ -55,6 +55,9 @@ begin
q_o => sync);
cmp_gc_posedge : entity work.gc_posedge
generic map (
g_ASYNC_RST => TRUE,
g_CLOCK_EDGE => g_SYNC_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
......@@ -62,6 +65,9 @@ begin
pulse_o => ppulse);
cmp_gc_negedge : entity work.gc_negedge
generic map (
g_ASYNC_RST => TRUE,
g_CLOCK_EDGE => g_SYNC_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
......
......@@ -272,7 +272,22 @@ package gencores_pkg is
------------------------------------------------------------------------------
-- 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 +296,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;
......
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