Commit 971c2e77 authored by Dimitris Lampridis's avatar Dimitris Lampridis

Merge branch 'bugfix/gc_sync_ffs_negedge' into proposed_master

This bugfix has been tested by myself on the latest development version of SPEC-based FMC-ADC, as
well as by M. Lipinski on BTrain test setup.

Closes #23.
parents 9f7ee4a5 047aa746
......@@ -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,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",
......
......@@ -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;
......@@ -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;
......@@ -63,23 +63,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
......
......@@ -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
......
......@@ -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;
......
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