- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page