From 26f9246ce4b1fee500d1ba8baa3ef4027eef42fc Mon Sep 17 00:00:00 2001 From: Andrey Smolyakov Date: Mon, 26 Jun 2023 22:45:03 +0300 Subject: [PATCH 1/5] Fix retiming attribute bug (pipelining_2008) "register_balancing" is an ISE synthesis engine (XST) attribute. It is not supported by Vivado, and ISE does not support VHDL-2008. So, the attribute is replaced by a pair of Vivado's ones. --- rtl/extras_2008/pipelining_2008.vhdl | 42 +++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/rtl/extras_2008/pipelining_2008.vhdl b/rtl/extras_2008/pipelining_2008.vhdl index a844292..85b9fb4 100644 --- a/rtl/extras_2008/pipelining_2008.vhdl +++ b/rtl/extras_2008/pipelining_2008.vhdl @@ -112,7 +112,7 @@ package pipelining is type ELEMENT_TYPE; --## Type of pipeline element function RESET_ELEMENT ( element : ELEMENT_TYPE ) return ELEMENT_TYPE; --## Defines how to reset pipeline element PIPELINE_STAGES : positive; --# Number of pipeline stages to insert - ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction (Xilinx only) + ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level ); port ( @@ -129,7 +129,7 @@ package pipelining is component pipeline_ul is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert - ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction (Xilinx only) + ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level ); port ( @@ -146,7 +146,7 @@ package pipelining is component pipeline_sulv is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert - ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction (Xilinx only) + ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level ); port ( @@ -166,7 +166,7 @@ package pipelining is component pipeline_u is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert - ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction (Xilinx only) + ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level ); port ( @@ -183,7 +183,7 @@ package pipelining is component pipeline_s is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert - ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction (Xilinx only) + ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level ); port ( @@ -405,11 +405,39 @@ entity pipeline_universal is end entity; architecture rtl of pipeline_universal is - attribute register_balancing : string; + function is_forward(attr_str : string) return integer is + variable r : integer; + begin + r := 1 when (attr_str = "forward") else 0; + return r; + end function; + + function is_backward(attr_str : string) return integer is + variable r : integer; + begin + r := 1 when (attr_str = "backward") else 0; + return r; + end function; + attribute syn_allow_retiming : boolean; - attribute register_balancing of Sig_out : signal is ATTR_REG_BALANCING; attribute syn_allow_retiming of Sig_out : signal is true; + + attribute retiming_forward : integer; + attribute retiming_forward of Sig_out : signal is + is_forward(ATTR_REG_BALANCING); + + attribute retiming_backward : integer; + attribute retiming_backward of Sig_out : signal is + is_backward(ATTR_REG_BALANCING); begin + + assert (ATTR_REG_BALANCING = "backward") or + (ATTR_REG_BALANCING = "forward") or + (ATTR_REG_BALANCING = "no") + report + "Unknown retiming attribute. Must be forward or backward." + severity FAILURE; + reg: process(Clock, Reset) type sig_word_vector is array ( natural range <> ) of ELEMENT_TYPE; variable pl_regs : sig_word_vector(1 to PIPELINE_STAGES); From e66e798b48edff5b43a667063f9f9ec5aea401d2 Mon Sep 17 00:00:00 2001 From: Andrey Smolyakov Date: Mon, 26 Jun 2023 23:11:34 +0300 Subject: [PATCH 2/5] Replace resetting function with default element (pipelining_2008) Breaks compatibility! An approach with default element tutned out to be much less wordy than the one with a resetting function. The function, basically, always contains a definition of a default element anyway. --- rtl/extras_2008/pipelining_2008.vhdl | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/rtl/extras_2008/pipelining_2008.vhdl b/rtl/extras_2008/pipelining_2008.vhdl index 85b9fb4..a4825a4 100644 --- a/rtl/extras_2008/pipelining_2008.vhdl +++ b/rtl/extras_2008/pipelining_2008.vhdl @@ -70,15 +70,12 @@ --# field_2 : std_ulogic; --# end record my_record; --# ---# function reset_my_record( rec : my_record ) return my_record is ---# begin ---# return ((others => '0'), '0'); ---# end function reset_my_record; +--# constant MY_EMPTY_RECORD : my_record := ((others => '0'), '0')' --# ... --# pipeline_inst : pipeline_universal --# generic map ( --# ELEMENT_TYPE => my_record, ---# RESET_ELEMENT => reset_my_record, +--# DEFAULT_ELEMENT => MY_EMPTY_RECORD, --# PIPELINE_STAGES => 3, --# ATTR_REG_BALANCING => "backward", --# RESET_ACTIVE_LEVEL => '1' ) @@ -110,7 +107,7 @@ package pipelining is component pipeline_universal is generic ( type ELEMENT_TYPE; --## Type of pipeline element - function RESET_ELEMENT ( element : ELEMENT_TYPE ) return ELEMENT_TYPE; --## Defines how to reset pipeline element + DEFAULT_ELEMENT : ELEMENT_TYPE; --## Reset pipeline element PIPELINE_STAGES : positive; --# Number of pipeline stages to insert ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level @@ -391,7 +388,7 @@ use ieee.std_logic_1164.all; entity pipeline_universal is generic ( type ELEMENT_TYPE; - function RESET_ELEMENT ( element : ELEMENT_TYPE ) return ELEMENT_TYPE; + DEFAULT_ELEMENT : ELEMENT_TYPE; PIPELINE_STAGES : positive; ATTR_REG_BALANCING : string := "backward"; RESET_ACTIVE_LEVEL : std_ulogic := '1' @@ -444,7 +441,7 @@ begin begin if Reset = RESET_ACTIVE_LEVEL then for i in pl_regs'range loop - pl_regs(i) := RESET_ELEMENT(pl_regs(i)); + pl_regs(i) := DEFAULT_ELEMENT; end loop; elsif rising_edge(Clock) then if PIPELINE_STAGES = 1 then @@ -477,15 +474,12 @@ entity pipeline_ul is end entity; architecture rtl of pipeline_ul is - function reset_ul (ul : std_ulogic) return std_ulogic is - begin - return '0'; - end function; + constant ZERO : std_ulogic := '0'; begin pipeline_inst : entity work.pipeline_universal(rtl) generic map ( ELEMENT_TYPE => Sig_in'subtype, - RESET_ELEMENT => reset_ul, + DEFAULT_ELEMENT => ZERO, PIPELINE_STAGES => PIPELINE_STAGES, ATTR_REG_BALANCING => ATTR_REG_BALANCING, RESET_ACTIVE_LEVEL => RESET_ACTIVE_LEVEL) @@ -511,15 +505,13 @@ entity pipeline_sulv is end entity; architecture rtl of pipeline_sulv is - function reset_sulv (ul : std_ulogic_vector) return std_ulogic_vector is - begin - return (ul'range => '0'); - end function; + constant ZEROS : std_ulogic_vector(Sig_in'range) := + (Sig_in'range => '0'); begin pipeline_inst : entity work.pipeline_universal(rtl) generic map ( ELEMENT_TYPE => Sig_in'subtype, - RESET_ELEMENT => reset_sulv, + DEFAULT_ELEMENT => ZEROS, PIPELINE_STAGES => PIPELINE_STAGES, ATTR_REG_BALANCING => ATTR_REG_BALANCING, RESET_ACTIVE_LEVEL => RESET_ACTIVE_LEVEL) From d40b47125c065d1bb3afbee6e320ae2e74d52bf7 Mon Sep 17 00:00:00 2001 From: Andrey Smolyakov Date: Tue, 27 Jun 2023 02:28:38 +0300 Subject: [PATCH 3/5] Allow reset type selection (pipelining_2008) pipeline_* components now allow selecting synchronous or asynchronous reset type. --- rtl/extras_2008/pipelining_2008.vhdl | 92 +++++++++++++++++++--------- 1 file changed, 64 insertions(+), 28 deletions(-) diff --git a/rtl/extras_2008/pipelining_2008.vhdl b/rtl/extras_2008/pipelining_2008.vhdl index a4825a4..5e2c53a 100644 --- a/rtl/extras_2008/pipelining_2008.vhdl +++ b/rtl/extras_2008/pipelining_2008.vhdl @@ -78,7 +78,8 @@ --# DEFAULT_ELEMENT => MY_EMPTY_RECORD, --# PIPELINE_STAGES => 3, --# ATTR_REG_BALANCING => "backward", ---# RESET_ACTIVE_LEVEL => '1' ) +--# RESET_ACTIVE_LEVEL => '1', +--# RESET_TYPE => "async") --# port map (Clock, Reset, sig_1, sig_2); --# --# RETIMING: Here are notes on how to activate retiming in various synthesis @@ -110,12 +111,13 @@ package pipelining is DEFAULT_ELEMENT : ELEMENT_TYPE; --## Reset pipeline element PIPELINE_STAGES : positive; --# Number of pipeline stages to insert ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) - RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level + RESET_ACTIVE_LEVEL : std_ulogic := '1'; --# Reset control level + RESET_TYPE : string := "async" --# Reset type: asynchronous ("async") or synchronous ("sync") ); port ( --# {{clocks|}} Clock : in std_ulogic; --# System clock - Reset : in std_ulogic; --# Asynchronous reset + Reset : in std_ulogic; --# Reset --# {{data|}} Sig_in : in ELEMENT_TYPE; --# Signal from block to be pipelined Sig_out : out ELEMENT_TYPE --# Pipelined result @@ -127,12 +129,13 @@ package pipelining is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) - RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level + RESET_ACTIVE_LEVEL : std_ulogic := '1'; --# Reset control level + RESET_TYPE : string := "async" --# Reset type: asynchronous ("async") or synchronous ("sync") ); port ( --# {{clocks|}} Clock : in std_ulogic; --# System clock - Reset : in std_ulogic; --# Asynchronous reset + Reset : in std_ulogic; --# Reset --# {{data|}} Sig_in : in std_ulogic; --# Signal from block to be pipelined Sig_out : out std_ulogic --# Pipelined result @@ -144,12 +147,13 @@ package pipelining is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) - RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level + RESET_ACTIVE_LEVEL : std_ulogic := '1'; --# Reset control level + RESET_TYPE : string := "async" --# Reset type: asynchronous ("async") or synchronous ("sync") ); port ( --# {{clocks|}} Clock : in std_ulogic; --# System clock - Reset : in std_ulogic; --# Asynchronous reset + Reset : in std_ulogic; --# Reset --# {{data|}} Sig_in : in std_ulogic_vector; --# Signal from block to be pipelined Sig_out : out std_ulogic_vector --# Pipelined result @@ -164,7 +168,8 @@ package pipelining is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) - RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level + RESET_ACTIVE_LEVEL : std_ulogic := '1'; --# Reset control level + RESET_TYPE : string := "async" --# Reset type: asynchronous ("async") or synchronous ("sync") ); port ( --# {{clocks|}} @@ -181,12 +186,13 @@ package pipelining is generic ( PIPELINE_STAGES : positive; --# Number of pipeline stages to insert ATTR_REG_BALANCING : string := "backward"; --# Control propagation direction ("backward", "forward" or "no", Xilinx only) - RESET_ACTIVE_LEVEL : std_ulogic := '1' --# Asynch. reset control level + RESET_ACTIVE_LEVEL : std_ulogic := '1'; --# Reset control level + RESET_TYPE : string := "async" --# Reset type: asynchronous ("async") or synchronous ("sync") ); port ( --# {{clocks|}} Clock : in std_ulogic; --# System clock - Reset : in std_ulogic; --# Asynchronous reset + Reset : in std_ulogic; --# Reset --# {{data|}} Sig_in : in u_signed; --# Signal from block to be pipelined Sig_out : out u_signed --# Pipelined result @@ -391,7 +397,8 @@ entity pipeline_universal is DEFAULT_ELEMENT : ELEMENT_TYPE; PIPELINE_STAGES : positive; ATTR_REG_BALANCING : string := "backward"; - RESET_ACTIVE_LEVEL : std_ulogic := '1' + RESET_ACTIVE_LEVEL : std_ulogic := '1'; + RESET_TYPE : string := "async" ); port ( Clock : in std_ulogic; @@ -435,19 +442,40 @@ begin "Unknown retiming attribute. Must be forward or backward." severity FAILURE; + assert (RESET_TYPE = "async") or (RESET_TYPE = "sync") + report + "Unknown reset type. Must be sync or async." + severity FAILURE; + reg: process(Clock, Reset) type sig_word_vector is array ( natural range <> ) of ELEMENT_TYPE; variable pl_regs : sig_word_vector(1 to PIPELINE_STAGES); begin - if Reset = RESET_ACTIVE_LEVEL then - for i in pl_regs'range loop - pl_regs(i) := DEFAULT_ELEMENT; - end loop; - elsif rising_edge(Clock) then - if PIPELINE_STAGES = 1 then - pl_regs(1) := Sig_in; - else - pl_regs := Sig_in & pl_regs(1 to pl_regs'high-1); + if RESET_TYPE = "async" then + if Reset = RESET_ACTIVE_LEVEL then + for i in pl_regs'range loop + pl_regs(i) := DEFAULT_ELEMENT; + end loop; + elsif rising_edge(Clock) then + if PIPELINE_STAGES = 1 then + pl_regs(1) := Sig_in; + else + pl_regs := Sig_in & pl_regs(1 to pl_regs'high-1); + end if; + end if; + elsif RESET_TYPE = "sync" then + if rising_edge(Clock) then + if Reset = RESET_ACTIVE_LEVEL then + for i in pl_regs'range loop + pl_regs(i) := DEFAULT_ELEMENT; + end loop; + else + if PIPELINE_STAGES = 1 then + pl_regs(1) := Sig_in; + else + pl_regs := Sig_in & pl_regs(1 to pl_regs'high-1); + end if; + end if; end if; end if; @@ -463,7 +491,8 @@ entity pipeline_ul is generic ( PIPELINE_STAGES : positive; ATTR_REG_BALANCING : string := "backward"; - RESET_ACTIVE_LEVEL : std_ulogic := '1' + RESET_ACTIVE_LEVEL : std_ulogic := '1'; + RESET_TYPE : string := "async" ); port ( Clock : in std_ulogic; @@ -482,7 +511,8 @@ begin DEFAULT_ELEMENT => ZERO, PIPELINE_STAGES => PIPELINE_STAGES, ATTR_REG_BALANCING => ATTR_REG_BALANCING, - RESET_ACTIVE_LEVEL => RESET_ACTIVE_LEVEL) + RESET_ACTIVE_LEVEL => RESET_ACTIVE_LEVEL, + RESET_TYPE => RESET_TYPE) port map (Clock, Reset, Sig_in, Sig_out); end architecture; @@ -494,7 +524,8 @@ entity pipeline_sulv is generic ( PIPELINE_STAGES : positive; ATTR_REG_BALANCING : string := "backward"; - RESET_ACTIVE_LEVEL : std_ulogic := '1' + RESET_ACTIVE_LEVEL : std_ulogic := '1'; + RESET_TYPE : string := "async" ); port ( Clock : in std_ulogic; @@ -514,7 +545,8 @@ begin DEFAULT_ELEMENT => ZEROS, PIPELINE_STAGES => PIPELINE_STAGES, ATTR_REG_BALANCING => ATTR_REG_BALANCING, - RESET_ACTIVE_LEVEL => RESET_ACTIVE_LEVEL) + RESET_ACTIVE_LEVEL => RESET_ACTIVE_LEVEL, + RESET_TYPE => RESET_TYPE) port map (Clock, Reset, Sig_in, Sig_out); end architecture; @@ -527,7 +559,8 @@ entity pipeline_u is generic ( PIPELINE_STAGES : positive; ATTR_REG_BALANCING : string := "backward"; - RESET_ACTIVE_LEVEL : std_ulogic := '1' + RESET_ACTIVE_LEVEL : std_ulogic := '1'; + RESET_TYPE : string := "async" ); port ( Clock : in std_ulogic; @@ -542,7 +575,8 @@ architecture rtl of pipeline_u is begin s1 <= std_ulogic_vector(Sig_in); pipeline_inst : entity work.pipeline_sulv(rtl) - generic map (PIPELINE_STAGES, ATTR_REG_BALANCING, RESET_ACTIVE_LEVEL) + generic map (PIPELINE_STAGES, ATTR_REG_BALANCING, + RESET_ACTIVE_LEVEL, RESET_TYPE) port map (Clock => Clock, Reset => Reset, Sig_in => s1, Sig_out => s2); Sig_out <= u_unsigned(s2); end architecture; @@ -556,7 +590,8 @@ entity pipeline_s is generic ( PIPELINE_STAGES : positive; ATTR_REG_BALANCING : string := "backward"; - RESET_ACTIVE_LEVEL : std_ulogic := '1' + RESET_ACTIVE_LEVEL : std_ulogic := '1'; + RESET_TYPE : string := "async" ); port ( Clock : in std_ulogic; @@ -571,7 +606,8 @@ architecture rtl of pipeline_s is begin s1 <= std_ulogic_vector(Sig_in); pipeline_inst : entity work.pipeline_sulv(rtl) - generic map (PIPELINE_STAGES, ATTR_REG_BALANCING, RESET_ACTIVE_LEVEL) + generic map (PIPELINE_STAGES, ATTR_REG_BALANCING, + RESET_ACTIVE_LEVEL, RESET_TYPE) port map (Clock => Clock, Reset => Reset, Sig_in => s1, Sig_out => s2); Sig_out <= u_signed(s2); end architecture; From f2191181c041420e605f3c4bc0c2f579cc06cac3 Mon Sep 17 00:00:00 2001 From: Andrey Smolyakov Date: Tue, 27 Jun 2023 03:24:05 +0300 Subject: [PATCH 4/5] Allow shift reg. inference style selection (pipelining_2008, Xilinx) A generic parameter ATTR_SRL_STYLE is added. The parameter allows one to select a shift register implementation method in Xilinx Vivado. --- rtl/extras_2008/pipelining_2008.vhdl | 91 +++++++++++++++++++++------- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/rtl/extras_2008/pipelining_2008.vhdl b/rtl/extras_2008/pipelining_2008.vhdl index 5e2c53a..c5f5242 100644 --- a/rtl/extras_2008/pipelining_2008.vhdl +++ b/rtl/extras_2008/pipelining_2008.vhdl @@ -204,7 +204,8 @@ package pipelining is component fixed_delay_line_universal is generic ( type ELEMENT_TYPE; --# Type of the element being delayed - STAGES : natural --# Number of delay stages (0 for short circuit) + STAGES : natural; --# Number of delay stages (0 for short circuit) + ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) ); port ( --# {{clocks|}} @@ -223,7 +224,8 @@ package pipelining is --## Fixed delay line for std_ulogic data. component fixed_delay_line is generic ( - STAGES : natural --# Number of delay stages (0 for short circuit) + STAGES : natural; --# Number of delay stages (0 for short circuit) + ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) ); port ( --# {{clocks|}} @@ -242,7 +244,8 @@ package pipelining is --## Fixed delay line for std_ulogic_vector data. component fixed_delay_line_sulv is generic ( - STAGES : natural --# Number of delay stages (0 for short circuit) + STAGES : natural; --# Number of delay stages (0 for short circuit) + ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) ); port ( --# {{clocks|}} @@ -261,7 +264,8 @@ package pipelining is --## Fixed delay line for signed data. component fixed_delay_line_signed is generic ( - STAGES : natural --# Number of delay stages (0 for short circuit) + STAGES : natural; --# Number of delay stages (0 for short circuit) + ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) ); port ( --# {{clocks|}} @@ -280,7 +284,8 @@ package pipelining is --## Fixed delay line for unsigned data. component fixed_delay_line_unsigned is generic ( - STAGES : natural --# Number of delay stages (0 for short circuit) + STAGES : natural; --# Number of delay stages (0 for short circuit) + ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) ); port ( --# {{clocks|}} @@ -620,7 +625,8 @@ use ieee.std_logic_1164.all; entity fixed_delay_line_universal is generic ( type ELEMENT_TYPE; - STAGES : natural + STAGES : natural; + ATTR_SRL_STYLE : string := "auto" ); port ( Clock : in std_ulogic; @@ -631,23 +637,56 @@ entity fixed_delay_line_universal is end entity; architecture rtl of fixed_delay_line_universal is + function is_auto(attr_gen : string) return boolean is + constant str_auto : string := "auto"; + begin + if attr_gen'length /= str_auto'length then + return false; + else + return (attr_gen = str_auto); + end if; + end function; + type elements_vector is array ( natural range <> ) of ELEMENT_TYPE; - signal dly : elements_vector(0 to STAGES-1); begin g : if STAGES = 0 generate Data_out <= Data_in; elsif STAGES > 0 generate - delay: process(Clock) is + + g2 : if not is_auto(ATTR_SRL_STYLE) generate + signal dly : elements_vector(0 to STAGES-1); + attribute srl_style : string; + attribute srl_style of dly : signal is ATTR_SRL_STYLE; begin - if rising_edge(Clock) then - if Enable = '1' then - dly <= Data_in & dly(0 to dly'high-1); + + delay: process(Clock) is + begin + if rising_edge(Clock) then + if Enable = '1' then + dly <= Data_in & dly(0 to dly'high-1); + end if; end if; - end if; - end process; + end process; + + Data_out <= dly(dly'high); + + else generate + signal dly : elements_vector(0 to STAGES-1); + begin + + delay: process(Clock) is + begin + if rising_edge(Clock) then + if Enable = '1' then + dly <= Data_in & dly(0 to dly'high-1); + end if; + end if; + end process; + + Data_out <= dly(dly'high); - Data_out <= dly(dly'high); + end generate g2; end generate; end architecture; @@ -658,7 +697,8 @@ use ieee.std_logic_1164.all; entity fixed_delay_line is generic ( - STAGES : natural + STAGES : natural; + ATTR_SRL_STYLE : string := "auto" ); port ( Clock : in std_ulogic; @@ -671,7 +711,8 @@ end entity; architecture rtl of fixed_delay_line is begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES) + generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE) port map (Clock, Enable, Data_in, Data_out); end architecture; @@ -681,7 +722,8 @@ use ieee.std_logic_1164.all; entity fixed_delay_line_sulv is generic ( - STAGES : natural + STAGES : natural; + ATTR_SRL_STYLE : string := "auto" ); port ( Clock : in std_ulogic; @@ -694,7 +736,8 @@ end entity; architecture rtl of fixed_delay_line_sulv is begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES) + generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE) port map (Clock, Enable, Data_in, Data_out); end architecture; @@ -705,7 +748,8 @@ use ieee.numeric_std.all; entity fixed_delay_line_signed is generic ( - STAGES : natural + STAGES : natural; + ATTR_SRL_STYLE : string := "auto" ); port ( Clock : in std_ulogic; @@ -718,7 +762,8 @@ end entity; architecture rtl of fixed_delay_line_signed is begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES) + generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE) port map (Clock, Enable, Data_in, Data_out); end architecture; @@ -729,7 +774,8 @@ use ieee.numeric_std.all; entity fixed_delay_line_unsigned is generic ( - STAGES : natural + STAGES : natural; + ATTR_SRL_STYLE : string := "auto" ); port ( Clock : in std_ulogic; @@ -742,7 +788,8 @@ end entity; architecture rtl of fixed_delay_line_unsigned is begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES) + generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE) port map (Clock, Enable, Data_in, Data_out); end architecture; From 59b8604ad9d021d6d9c2fc2690d83f4fa0601b23 Mon Sep 17 00:00:00 2001 From: Andrey Smolyakov Date: Tue, 27 Jun 2023 03:26:51 +0300 Subject: [PATCH 5/5] Allow delay line elements initialization (pipelining_2008) Breaks compatibility! In most cases, elements initialization is useful. It improves the quality of simulation results. However, it may prevent some optimizations (at least in Vivado). So, this commit adds a generic which controls whether the elements are initialized or not. By default the elements are initialized now. --- rtl/extras_2008/pipelining_2008.vhdl | 95 ++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 20 deletions(-) diff --git a/rtl/extras_2008/pipelining_2008.vhdl b/rtl/extras_2008/pipelining_2008.vhdl index c5f5242..4800981 100644 --- a/rtl/extras_2008/pipelining_2008.vhdl +++ b/rtl/extras_2008/pipelining_2008.vhdl @@ -204,8 +204,10 @@ package pipelining is component fixed_delay_line_universal is generic ( type ELEMENT_TYPE; --# Type of the element being delayed + DEFAULT_ELEMENT : ELEMENT_TYPE; --# Default value for an element initialization STAGES : natural; --# Number of delay stages (0 for short circuit) - ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + ATTR_SRL_STYLE : string := "auto"; --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + NEED_INIT : boolean := true --# Initialize delay line with DEFAULT_ELEMENT ); port ( --# {{clocks|}} @@ -225,7 +227,8 @@ package pipelining is component fixed_delay_line is generic ( STAGES : natural; --# Number of delay stages (0 for short circuit) - ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + ATTR_SRL_STYLE : string := "auto"; --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + NEED_INIT : boolean := true --# Initialize delay line with DEFAULT_ELEMENT ); port ( --# {{clocks|}} @@ -245,7 +248,8 @@ package pipelining is component fixed_delay_line_sulv is generic ( STAGES : natural; --# Number of delay stages (0 for short circuit) - ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + ATTR_SRL_STYLE : string := "auto"; --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + NEED_INIT : boolean := true --# Initialize delay line with DEFAULT_ELEMENT ); port ( --# {{clocks|}} @@ -265,7 +269,8 @@ package pipelining is component fixed_delay_line_signed is generic ( STAGES : natural; --# Number of delay stages (0 for short circuit) - ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + ATTR_SRL_STYLE : string := "auto"; --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + NEED_INIT : boolean := true --# Initialize delay line with DEFAULT_ELEMENT ); port ( --# {{clocks|}} @@ -285,7 +290,8 @@ package pipelining is component fixed_delay_line_unsigned is generic ( STAGES : natural; --# Number of delay stages (0 for short circuit) - ATTR_SRL_STYLE : string := "auto" --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + ATTR_SRL_STYLE : string := "auto"; --# Shift reg. style (Xilinx only; auto, register, srl, srl_reg, reg_srl, reg_srl_reg, or block) + NEED_INIT : boolean := true --# Initialize delay line with DEFAULT_ELEMENT ); port ( --# {{clocks|}} @@ -625,8 +631,10 @@ use ieee.std_logic_1164.all; entity fixed_delay_line_universal is generic ( type ELEMENT_TYPE; + DEFAULT_ELEMENT : ELEMENT_TYPE; STAGES : natural; - ATTR_SRL_STYLE : string := "auto" + ATTR_SRL_STYLE : string := "auto"; + NEED_INIT : boolean := true ); port ( Clock : in std_ulogic; @@ -654,7 +662,7 @@ begin Data_out <= Data_in; elsif STAGES > 0 generate - g2 : if not is_auto(ATTR_SRL_STYLE) generate + g2 : if (not is_auto(ATTR_SRL_STYLE)) and (not NEED_INIT) generate signal dly : elements_vector(0 to STAGES-1); attribute srl_style : string; attribute srl_style of dly : signal is ATTR_SRL_STYLE; @@ -671,7 +679,39 @@ begin Data_out <= dly(dly'high); - else generate + elsif (not is_auto(ATTR_SRL_STYLE)) and NEED_INIT generate + signal dly : elements_vector(0 to STAGES-1) := (others => DEFAULT_ELEMENT); + attribute srl_style : string; + attribute srl_style of dly : signal is ATTR_SRL_STYLE; + begin + + delay: process(Clock) is + begin + if rising_edge(Clock) then + if Enable = '1' then + dly <= Data_in & dly(0 to dly'high-1); + end if; + end if; + end process; + + Data_out <= dly(dly'high); + + elsif is_auto(ATTR_SRL_STYLE) and NEED_INIT generate + signal dly : elements_vector(0 to STAGES-1) := (others => DEFAULT_ELEMENT); + begin + + delay: process(Clock) is + begin + if rising_edge(Clock) then + if Enable = '1' then + dly <= Data_in & dly(0 to dly'high-1); + end if; + end if; + end process; + + Data_out <= dly(dly'high); + + elsif is_auto(ATTR_SRL_STYLE) and (not NEED_INIT) generate signal dly : elements_vector(0 to STAGES-1); begin @@ -698,7 +738,8 @@ use ieee.std_logic_1164.all; entity fixed_delay_line is generic ( STAGES : natural; - ATTR_SRL_STYLE : string := "auto" + ATTR_SRL_STYLE : string := "auto"; + NEED_INIT : boolean := true ); port ( Clock : in std_ulogic; @@ -709,10 +750,12 @@ entity fixed_delay_line is end entity; architecture rtl of fixed_delay_line is + constant ZERO : std_ulogic := '0'; begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, - ATTR_SRL_STYLE => ATTR_SRL_STYLE) + generic map (ELEMENT_TYPE => Data_in'subtype, DEFAULT_ELEMENT => ZERO, + STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE, NEED_INIT => NEED_INIT) port map (Clock, Enable, Data_in, Data_out); end architecture; @@ -723,7 +766,8 @@ use ieee.std_logic_1164.all; entity fixed_delay_line_sulv is generic ( STAGES : natural; - ATTR_SRL_STYLE : string := "auto" + ATTR_SRL_STYLE : string := "auto"; + NEED_INIT : boolean := true ); port ( Clock : in std_ulogic; @@ -734,10 +778,13 @@ entity fixed_delay_line_sulv is end entity; architecture rtl of fixed_delay_line_sulv is + constant ZEROS : std_ulogic_vector(Data_in'range) := + (Data_in'range => '0'); begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, - ATTR_SRL_STYLE => ATTR_SRL_STYLE) + generic map (ELEMENT_TYPE => Data_in'subtype, DEFAULT_ELEMENT => ZEROS, + STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE, NEED_INIT => NEED_INIT) port map (Clock, Enable, Data_in, Data_out); end architecture; @@ -749,7 +796,8 @@ use ieee.numeric_std.all; entity fixed_delay_line_signed is generic ( STAGES : natural; - ATTR_SRL_STYLE : string := "auto" + ATTR_SRL_STYLE : string := "auto"; + NEED_INIT : boolean := true ); port ( Clock : in std_ulogic; @@ -760,10 +808,13 @@ entity fixed_delay_line_signed is end entity; architecture rtl of fixed_delay_line_signed is + constant ZEROS : u_signed(Data_in'range) := + (Data_in'range => '0'); begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, - ATTR_SRL_STYLE => ATTR_SRL_STYLE) + generic map (ELEMENT_TYPE => Data_in'subtype, DEFAULT_ELEMENT => ZEROS, + STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE, NEED_INIT => NEED_INIT) port map (Clock, Enable, Data_in, Data_out); end architecture; @@ -775,7 +826,8 @@ use ieee.numeric_std.all; entity fixed_delay_line_unsigned is generic ( STAGES : natural; - ATTR_SRL_STYLE : string := "auto" + ATTR_SRL_STYLE : string := "auto"; + NEED_INIT : boolean := true ); port ( Clock : in std_ulogic; @@ -786,10 +838,13 @@ entity fixed_delay_line_unsigned is end entity; architecture rtl of fixed_delay_line_unsigned is + constant ZEROS : u_unsigned(Data_in'range) := + (Data_in'range => '0'); begin dl_inst : entity work.fixed_delay_line_universal(rtl) - generic map (ELEMENT_TYPE => Data_in'subtype, STAGES => STAGES, - ATTR_SRL_STYLE => ATTR_SRL_STYLE) + generic map (ELEMENT_TYPE => Data_in'subtype, DEFAULT_ELEMENT => ZEROS, + STAGES => STAGES, + ATTR_SRL_STYLE => ATTR_SRL_STYLE, NEED_INIT => NEED_INIT) port map (Clock, Enable, Data_in, Data_out); end architecture;