# Constructing a component with number of inputs variable

Status
Not open for further replies.

#### ChaXi

##### Junior Member level 1
Hello...
I'm trying to resolve a problem...
I need to have a component that does simply OR between bits of a vector which have a different length decided in top level by a generic map...

how can i write a correct sintax for this OR?
For example if i have
signal X : std_logic_vector (width-1 downto 0) --- my input;
signal MyOr: std_logic; --- my output
MyOr <= X(width-1) or ....:???:.... or X(0);

#### FvM

##### Super Moderator
Staff member
You can refer to this library function from "ieee.syn_misc"
Code:
function OR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is
variable result: STD_LOGIC;
-- Synthesis directive.
attribute SYNTHESIS_RETURN of result:variable is "REDUCE_OR" ;
begin
result := '0';
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;

ChaXi and blooz

points: 2

### ChaXi

points: 2

#### ChaXi

##### Junior Member level 1
Yes... that's perfect... very useful, thanks... I have other questions concerning this
subject.

I get these errors while synthesizing:
ERROR:HDLCompiler:432 - "C:\Xilinx\Clustering\ElementaryCell.vhd" Line 28: Formal <n_of_in> has no actual or default value.
ERROR:HDLCompiler:432 - "C:\Xilinx\Clustering\ElementaryCell.vhd" Line 29: Formal <n_of_out> has no actual or default value.

Here is my code:
entity ElementaryCell is
Generic ( n_of_in : integer;
n_of_out : integer
);
.......................................
.......................................
Port (
clk : in STD_LOGIC;
rst : in STD_LOGIC;
sel_from_near : in STD_LOGIC_VECTOR (n_of_in-1 downto 0);
sel_to_near : out STD_LOGIC_VECTOR (n_of_out-1 downto 0);
......................................
......................................
architecture FSM of ElementaryCell is

type StateType is (empty, hitted, selected);
signal state : StateType;

function OR_VAR(ARG: STD_LOGIC_VECTOR) return UX01 is
variable result: STD_LOGIC;
-- Synthesis directive.
attribute SYNTHESIS_RETURN of result:variable is "OR_VAR" ;
begin
result := '0';
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;
..........................................
..........................................
when hitted =>

if ( (OR_VAR(sel_from_near) = '1') or ((sel_hit and hit) = '1' ) ) then
..........................................
..........................................

Now my questions:
1) I still have to write the top level where i create more of this components with different values of <n_of_in>/<n_of_out>. So do I have error because I have not already used a port map?
And If i write let's say
Generic ( n_of_in : integer := 5;
n_of_out : integer := 5
);
when I will use port map on top level will the value of these parameters change?
2) Is the OR_REDUCE recognized correctly by the synthesizer? I mean does it put an OR port correctly? I'm asking this to know if I will have problem when translating, map and place and route...

#### FvM

##### Super Moderator
Staff member
The error is asserted, because you defined a generic, but didn't supply an actual value in the instantiation. Adding a default value to the component definition would help. It will be overwritten, if an actual value is given.

Using a function similar to or_reduce() has the advantage, that the actual argument size will be automatically retrieved for each instance, so you don't need a generic to specify the argument size. But a component definition will need generics instead.

or_reduce is originally a Synopsys library function from ieee.std_logic_misc (like ieee.std_logic_arith). It synthesizes correctly at least with Altera Quartus. But I would expect it to work with Xilinx as well.

ChaXi

### ChaXi

points: 2

#### ChaXi

##### Junior Member level 1
Ok I understand...thanks again...very nice...:grin:

#### permute

actually, VHDL also allows "unconstrained" ports for components in the same way it is allowed for functions. eg, a port could be declared as "in std_logic_vector;". There are some practical implications:

1.) 'length-1 downto 0, 'high downto 0, and really even "downto" may not work as expected. this is because the unconstrained port takes the dimension of the connected signal. eg connecting x(7 downto 4) to a 4 bit _unconstrained_ port means that the port is 7 downto 4, not 3 downto 0. trying to index bit 0 within the entity no longer works, while 'low still does.
2.) outputs must be connected to non-opens. outputs also must be properly sized even if not used. The latter is because the 'length of an output might be needed for the proper operation of the instance. This is an annoying requirement.
3.) inputs must be connected to the correct size signal, even when not used. "0000" defaults to 0 to 3, which again causes issues when the direction is assumed to be downto.
4.) there is no immediate context of the size of ports. eg, an unconstrained ram might be expected to have read/write data widths equal, and read/write addresses equal, and byte write enables equal to data width divided by 8. with unconstrained vectors, this might not be obvious -- the user might assumes the width conversions are done because there is nothing that prevents the connections of a 32b read port and 16b write port. when generics are used, the meaning is clear.
5.) size checking isn't done automatically. thus an output, y, defined in terms of an input x as x'length/8 can have issues when the user connects y to a larger vector. in such a case, the upper bits are not driven -- a warning.

Overall, unconstrained vectors are mixed. They can be used to make some modules easier to use, but the above nuances can allow for subtle bugs to creep into the design. eg, when bits N-1 downto 1 of an N-bit vector are used. If the user connects an N downto 1 vector, which has the same 'length as the expected N-1 downto 0 vector, the component will still synthesize. The results will not be as expected, as the lsb is now used.

as a result, entity that make use of unconstrained vectors often use a signal x_normal such that x_normal(N-1 downto 0) <= x; which maps "x" into the expected form. likewise, assert statements should be added, and size checking should be done.

ChaXi

### ChaXi

points: 2

#### ChaXi

##### Junior Member level 1
Thanks for the useful information...
By the way i synthesized my component with the OR_REDUCE and i found out that i give me an OR with n inputs...
In another part of my logic i need something similar to OR_REDUCE but this time I need a sort of OR "cascode" where the equation for the i-th out of or port is like

out_temp(i) = out_temp(i-1) OR in(i)

so it's like having a sort of ''carry''...I wrote this code where the only problem is for the first OR of the chain that is compared with a '0'...
I think that the if used into the for-generate is completely wrong... I also tried with if generate into the same for-generate but it gives me error... any ideas?

P.S.
aor is a simply OR port... I used it because i tried also a for loop with the equation wrote above but still compiler gives me 1 OR with N inputs....:-(
Code:
[INDENT][I]library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

Generic (
row : integer := 3
);
Port (
data : in  STD_LOGIC_VECTOR (row-1 downto 0);
y : buffer  STD_LOGIC
);

signal q : std_logic_vector(row-1 downto 0) <= "000";

component aor
Port ( a : in  STD_LOGIC;
b : in  STD_LOGIC;
c : out  STD_LOGIC);
end component;

begin

--ULTIMA DISPERATA PROVA
for i in 0 to row-1 generate
if i=0 then
aor port map(
a=>'0',
b=>data(i),
c=>q(i)
);
else
aor port map(
a=>q(i-1),
b=>data(i),
c=>q(i)
);
end generate;

y <= q(row-1)

end Behavioral;
[/I][/INDENT]

#### std_match

By the way i synthesized my component with the OR_REDUCE and i found out that i give me an OR with n inputs...
In another part of my logic i need something similar to OR_REDUCE but this time I need a sort of OR "cascode" where the equation for the i-th out of or port is like

out_temp(i) = out_temp(i-1) OR in(i)
Why do you care about the implementation when the logic function is identical?
The OR-gate witn n inputs seems to be the best solution for a LUT-based FPGA.

#### permute

I agree. However it can be useful if the goal is to learn about synthesis nuances. In this case, a generate would react badly to "keep_hierarchy", as the instances can't be flattened.

VHDL isn't verilog, and has a nestable if-generate. VHDL2008 has the "else" feature, while older versions do not. thus if x generate A else B doesn't work. it has to be if x generate A. if not x generate B. VHDL2008 adds the case and if-else features.

Verilog on the other hand has a single generate "block" with genvar's declared externally.

ChaXi

### ChaXi

points: 2

#### ChaXi

##### Junior Member level 1
I need this because

1) I want to have vhdl do what I want
2) now it's the best because i have very few inputs...in the future I will use clb of slice to implement a very fast carry for my or (I'm writing a sort of cellular automa)... by the way point one is more than enough :grin:

#### ChaXi

##### Junior Member level 1
So I found the way to prevent xst doing a n inputs or... I just added (copying from the internet) an attributed keep i used in my code written below... now the problem is that it doesn't work for the very first step (a OR with '0')... yes i know it does not have sense to have a or with a zero, but what i 'm trying to have is a regular structure that can be duplicated as i want and that can be placed where I want in my fpga... so can anyone explain me in detail how attribute works and if there some way I can resolve the problem for the first OR? Is there any way I can tell to XST that signal "massa" is connect to GND and that he don't have to sinplify? Maybe some synthesis or hdl option...

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity OR_ROW is
Generic (
row : integer := 3
);
Port (
data : in  STD_LOGIC_VECTOR (row-1 downto 0);
y : buffer  STD_LOGIC
);
end OR_ROW;

architecture Behavioral of OR_ROW is

signal q : std_logic_vector (row-1 downto 0);
signal massa : std_logic ;
attribute keep : string;
attribute keep of q: signal is "true";
attribute keep of massa: signal is "true";

begin
massa <= '0';

process(data,q,massa)
begin
for i in 0 to row-1 loop
if i=0 then
q(i) <= data(i) or massa;
else
q(i) <= data(i) or q(i-1);
end if;
end loop;
end process;

y <= q(row-1);

end Behavioral;
Here is my RTL schematics

Status
Not open for further replies.