Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16606 Discussions

Multi cycle path trough combinatoric logic circuit

Altera_Forum
Honored Contributor II
2,718 Views

Hi, i have an issue to fully understand and constraint multi cycle path for particular vhdl file. 

 

I created pipeline tree adder with enable input. This pipeline tree adder is created using recursion approach (see VHDL code). 

Enable signal is used to reduce calculation speed of this digital circuit, by allowing pipeline data to change only when enable signal's value is high. 

Such approach is used because the main system's clock is higher than the input data rate. Enable signal appears only once in every fifth clock (as fast as the input data), thus reducing the calculation speed by 5x times, allowing this circuit to work in the same clock domain as the main circuit. 

 

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library lib_packages; use lib_packages.util_pkg.all; library arith; use arith.arith_lib.all; library altera; use altera.altera_primitives_components.all; entity pipeline_tree_adder_signed_with_en is generic ( P : natural := 4; -- Number of inputs DATA_WIDTH : natural := 1 -- Data width ); port ( clk : in std_logic; wr_req_in : in std_logic; en_in : in std_logic; data_in_2d : in std_logic_2d(P-1 downto 0, DATA_WIDTH-1 downto 0); data_out : out std_logic_vector(DATA_WIDTH-1+log2c(P) downto 0); wr_req_out : out std_logic ); end entity; architecture rtl of pipeline_tree_adder_signed_with_en is subtype ubyte is signed(DATA_WIDTH-1 downto 0); type u_1d_array is array(natural range <>) of ubyte; subtype ubytew is signed(DATA_WIDTH downto 0); type u_1d_array_w is array(natural range <>) of ubytew; signal data_1d_reg, data_1d_next : u_1d_array(P-1 downto 0); signal sum_1d : u_1d_array_w(((P-(P mod 2))/2 + (P mod 2))-1 downto 0); signal sum_2d : std_logic_2d(((P-(P mod 2))/2 + (P mod 2))-1 downto 0, DATA_WIDTH downto 0); signal wr_req_in_reg, wr_req_tmp_reg, wr_req_tmp : std_logic := '0'; signal output_signal : std_logic_vector(DATA_WIDTH-1+log2c(P) downto 0) := (others => '0'); signal en_temp : std_logic := '0'; component signed_adder is generic ( DATA_WIDTH : natural ); port ( a : in signed (DATA_WIDTH-1 downto 0); b : in signed (DATA_WIDTH-1 downto 0); result : out signed (DATA_WIDTH-1 downto 0) ); end component; begin process(data_in_2d) begin for i in P-1 downto 0 loop for l in DATA_WIDTH-1 downto 0 loop data_1d_next(i)(l) <= data_in_2d(i, l); end loop; end loop; end process; process(clk) begin if rising_edge(clk) then if (en_in = '1') then wr_req_in_reg <= wr_req_in; else wr_req_in_reg <= wr_req_in_reg; end if; end if; end process; en_temp <= en_in and wr_req_in; -- component's process(clk) begin if rising_edge(clk) then if (en_temp = '1') then data_1d_reg <= data_1d_next; else data_1d_reg <= data_1d_reg; end if; end if; end process; sadder_gen : for i in 0 to ((P-(P mod 2))/2-1) generate sadder : signed_adder generic map (DATA_WIDTH => (DATA_WIDTH+1)) port map (a => (data_1d_reg(i*2)((data_1d_reg(i*2)'length)-1) & data_1d_reg(i*2)), b => (data_1d_reg(i*2+1)((data_1d_reg(i*2+1)'length)-1) & data_1d_reg(i*2+1)), result => sum_1d(i)); end generate; --1. if P = 2 Output_stage_gen: if (P = 2) generate output_signal <= std_logic_vector(sum_1d(0)); wr_req_out <= wr_req_in_reg; end generate; int_gen: if (P > 2) generate process(sum_1d) begin for i in (((P-(P mod 2))/2 + (P mod 2))-1) downto 0 loop for l in DATA_WIDTH downto 0 loop sum_2d(i,l) <= sum_1d(i)(l); end loop; end loop; end process; Even_stage_gen: if (P mod 2 = 0) generate even_gen: pipeline_tree_adder_signed_with_en generic map (P => P/2, DATA_WIDTH => DATA_WIDTH + 1) port map (clk => clk, wr_req_in => wr_req_in_reg, en_in => en_in, data_in_2d => sum_2d, data_out => output_signal, wr_req_out => wr_req_out); end generate; Odd_stage_gen: if (P mod 2 = 1) generate sum_1d(((P-(P mod 2))/2 + (P mod 2))-1) <= data_1d_reg(P-1)((data_1d_reg(P-1)'length)-1) & data_1d_reg(P-1); odd_gen: pipeline_tree_adder_signed_with_en generic map (P => (P-1)/2+1, DATA_WIDTH => DATA_WIDTH + 1) port map (clk => clk, wr_req_in => wr_req_in_reg, en_in => en_in, data_in_2d => sum_2d, data_out => output_signal, wr_req_out => wr_req_out); end generate; end generate; data_out <= output_signal; end architecture;  

 

Respective VHDL RTL: 

 

https://www.alteraforum.com/forum/attachment.php?attachmentid=8322  

 

My question is: how do i constraint multi cycle path for such design where is one common clock with short enable impulses. How to correctly specify in SDC file that enable_in signal appears every fifth clock cycle and is only 1 clock cycle long? 

See timing diagrams. 

 

https://www.alteraforum.com/forum/attachment.php?attachmentid=8323  

 

To constraint multi cycle path i have been using such SDC command, but it didn't work... 

# set_multicycle_path 3 -to [get_fanouts [get_pins -hier *en*|q*] -through [get_pins -hier *|*ena*]] 

 

In top level entity i have register what generates enable impulses. 

 

Regards, 

Rinalds
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
1,279 Views

What you need to do, is set the setup and hold times either "from" the input registers or "to" the output registers (or from and to if you only want specified paths. 

 

set_multicycle_path -from [get_keepers {my_input_regeres} ] -to [get_keepers {my_output_registers}] -setup N 

set_multicycle_path -from [get_keepers {my_input_regeres} ] -to [get_keepers {my_output_registers}] -hold N-1 

 

This is when enable is high once every N clocks. 

 

I notice the data out from your blcok is not registered - any reason?
0 Kudos
Altera_Forum
Honored Contributor II
1,279 Views

Another question - why have you made the design more complex that it needs to be? why not just put  

 

a <= b + c; 

 

in this code, rather than making a signed adder component?
0 Kudos
Altera_Forum
Honored Contributor II
1,279 Views

If your question was - why i need additional register between adders, when answer is to increase speed. In real design input number may achieve more than 32 inputs and each input could be more than 18bit width. 

 

If Your question was - why i use adder as a separate component when answer is to simplify recursion realization, in this way a can easily pass through generic values. Maybe there are different ways of creating such designs, but i simply don't know them ;) 

In this VHDL code i need only change generic values and Quartus II software generates required stages to sum all input values (tree shaped architecture). Input values can bee even or odd.
0 Kudos
Altera_Forum
Honored Contributor II
1,279 Views

Thanks for fast replay. 

I will start with easy part. 

 

 

--- Quote Start ---  

 

I notice the data out from your blcok is not registered - any reason? 

 

--- Quote End ---  

 

 

Output data will be registered in the next module. 

 

 

--- Quote Start ---  

What you need to do, is set the setup and hold times either "from" the input registers or "to" the output registers (or from and to if you only want specified paths. 

 

set_multicycle_path -from [get_keepers {my_input_regeres} ] -to [get_keepers {my_output_registers}] -setup N 

set_multicycle_path -from [get_keepers {my_input_regeres} ] -to [get_keepers {my_output_registers}] -hold N-1 

 

This is when enable is high once every N clocks. 

 

 

--- Quote End ---  

 

 

Yea it helped, but with some modifications: 

 

I looked in Altera home page and finally found SDC example where enable signals was used. 

 

http://www.altera.com/support/examples/timequest/exm-tq-clock-enable.html#figure1 (http://www.altera.com/support/examples/timequest/exm-tq-clock-enable.html#figure1

 

Applied same technique to my design and get such result 

 

set_multicycle_path -to [get_fanouts [get_pins -hier *en_in*] -through [get_pins -hier *|*ena*]] -setup 5 

set_multicycle_path -to [get_fanouts [get_pins -hier *en_in*] -through [get_pins -hier *|*ena*]] -hold 4 

 

https://www.alteraforum.com/forum/attachment.php?attachmentid=8324  

 

So is it correct? To my mind yes!
0 Kudos
Altera_Forum
Honored Contributor II
1,279 Views

No, the question is why is there no register after the adder at the output? Its usually best practice to have a register as the last bit of logic before a signal leaves a block. 

 

I just feel simple components (like a single adder) help obfuscate the design heirarchy, when a simple + function can be used. I dont understand the relevance of the inputs being odd or even? 

 

Altera already provides a parrellel add megafunction: 

http://www.altera.co.uk/literature/ug/ug_lpm_alt_mfug.pdf
0 Kudos
Altera_Forum
Honored Contributor II
1,279 Views

 

--- Quote Start ---  

 

I dont understand the relevance of the inputs being odd or even? 

 

--- Quote End ---  

 

 

It means what designed pipeline tree adder module can be even or odd count of inputs. No modifications are needed in VHDL code. 

 

RTL with 3 inputs 

https://www.alteraforum.com/forum/attachment.php?attachmentid=8334  

 

RTL with 4 inputs 

https://www.alteraforum.com/forum/attachment.php?attachmentid=8335  

 

 

Yes i know what Altera provides with huge set of megafunctions. But i wanted to raise my skill in VHDL - so i started to build my own basic blocs. 

 

P.S. sorry about my English.
0 Kudos
Altera_Forum
Honored Contributor II
1,279 Views

Ok: Challenge for you to help improve your VHDL further: 

 

1. Try and re-write this block without your custom adder component 

2. Now try it without using the hellish type that is altera's "std_logic_2d" type (hint: create you own type). Even preferably avoid std_logic_vector completly for any numerical values (it just adds to type conversions). 

 

The std_logic_2d type was creates by altera to try and be compatible with their graphical design files and AHDL. It is horrible to use, as you have found out as you have to pick it apart bit by bit.
0 Kudos
Reply