I am trying to simulate a destination control lift controller with n floors and m lifts. So from every floor, the user can enter a destination floor to go and gets a lift number in return. So to simulate this kind of lift controller, I need to have variable in ports (which would be equal to the number of floors), each of type integer. I tried searching on google but could not find anything useful. Can someone suggest me how we can do the above ?
Thanks in advance.
In VHDL you can use unconstrained arrays as ports:
entity myDevice is
port ( floors : in std_logic_vector;
lifts : in std_logic_vector
);
end entity myDevice;
The size of the port is the determined during elaboration by the size of the connected signal. If you need to know the size of the port in your architecture, you simply use the 'length, 'range or any other appropriate attribute:
architecture RTL of myDevice is
begin
pr_control : process(all) is
begin
-- Code, code, code...
for n in lifts'range loop
process_lift(n);
end loop;
-- More code ...
end process pr_controll;
end architecture RTL;
You can always do something like this:
entity controller is generic (
N : integer;
M : integer
); port (
Floors : in std_logic_vector(N-1 downto 0);
Lifts : in std_logic_vector(M-1 downto 0)
);
end controller;
You can find some more examples of this here.
Or perhaps:
package foo is
type integer_array is array (integer range <>) of integer;
end package;
entity controller is generic (
N : integer;
M : integer
); port (
Floors : in foo.integer_array(N-1 downto 0);
Lifts : in foo.integer_array(M-1 downto 0)
);
end controller;
Related
I have declared an array
type datastream is array(0 to 10) of signed (5 downto 0);
For simulation, I want to display the array as integer-numbers
So I created
type datastream_int is array(0 to 10) of integer;
and
signal DIN_ARRAY: datastream;
signal DIN_ARRAY_int: datastream_int;
...
DIN_ARRAY_real <= datastream_int(DIN_ARRAY);
But it fails. How to convert it? Dont want to use a for loop
The numeric_std package, that I assume you are using, provides a to_integer function to convert from a single signed value to a single integer object. For an array, you're going to have to use a for loop. Something like this:
for i in DIN_ARRAY'range loop
DIN_ARRAY_int <= to_integer(DIN_ARRAY(i));
end loop;
You could also provide a conversion function (it will also contain a for loop)
function datastream_to_datastream_int( d : datastream ) return datastream_int is
variable r : datastream_int;
begin
for i in d'range loop
r(i) := to_integer(d(i));
end loop;
return r;
end function;
....
--no loop required
DIN_ARRAY_int <= datastream_to_datastream_int(DIN_ARRAY);
So, there will be a for loop somewhere.
Your code fails because you have attempted a type conversion, which is only allowed between similar types - ie. array or record types where the element types match between the two types.
PS. VHDL 2008 provides an integer_vector type in the std.standard library (which is included by default) which may help by allowing you to do this:
signal DIN_ARRAY_int: integer_vector(DIN_ARRAY'range);
If you did decide to keep datastream_int as per your original, you could type convert it to an integer_vector, because the types are similar:
my_iv <= integer_vector(DIN_ARRAY_int);
I am reading the article (attached file) and making VCO circuit (Charged balance) to model on Matlab/Simulink using System Generator. I get some error and I don't know how to fix it. At one-shot timer module when I run, it notifies:
Error 0001: The inputs to this block cannot all be constant.
Block: 'VCO_v2/one-shot timer '
This is my diagram
This is the error I encounter
This is my VCO file I simulink
You've attached two entities. I'm assuming you're using oneshot v1.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity oneshot is
port ( clk : in STD_LOGIC;
ce : in STD_LOGIC;
trigger : in STD_LOGIC;
delay : in STD_LOGIC_VECTOR (7 downto 0);
pulse : out STD_LOGIC :='0');
end oneshot;
architecture Behavioral of oneshot is
signal count: INTEGER range 0 to 255; -- count variable
signal flag : STD_LOGIC := '0'; -- count variable
begin
process (flag,clk,delay)
begin
-- wait for trigger leading edge
if trigger = '1' then
count <= to_integer(unsigned(delay));
elsif rising_edge(clk) then
if count > 0 then
pulse <= '1';
count <= count - 1;
else
pulse <= '0';
--flag <='0';
end if;
end if;
end process;
end Behavioral;
So what's the flag signal doing there? Why is it in the sensitivity list? Why is there an unused ce input?
But let's look at the oneshot_config.m file. The error message originates from there:
function setup_as_single_rate(block,clkname,cename)
inputRates = block.inputRates;
uniqueInputRates = unique(inputRates);
if (length(uniqueInputRates)==1 & uniqueInputRates(1)==Inf)
block.addError('The inputs to this block cannot all be constant.');
return;
end
if (uniqueInputRates(end) == Inf)
hasConstantInput = true;
uniqueInputRates = uniqueInputRates(1:end-1);
end
if (length(uniqueInputRates) ~= 1)
block.addError('The inputs to this block must run at a single rate.');
return;
end
theInputRate = uniqueInputRates(1);
for i = 1:block.numSimulinkOutports
block.outport(i).setRate(theInputRate);
end
block.addClkCEPair(clkname,cename,theInputRate);
return;
And that is called here
if (this_block.inputRatesKnown)
setup_as_single_rate(this_block,'clk','ce')
end % if(inputRatesKnown)
So the matlab code checks the inputRates of all inputs of this_block input. It has concluded that all the inputs are constant (you have no variable inputs to you system) and it has concluded that this will not work. This is because it tries to automatically determine the clock frequency from its inputs, which is impossible with constants.
So you'lll have to configure the clock rate manually. You could modify the oneshot_config.m. But probably you can assign a rate to the constant block. It should be something like block.outport.setRate(...); <-- some clock rate. Check the System Generator user guide.
I don't have System Generator installed on my Matlab pc, so I cannot check this.
I found the answer for this problem. Just change constant block of Matlab instead of using constant block of Xilinx.
I want to make subprogram for adding array's elements with Ada.
subprogram "Add_Data" have 3 parameters-
first parameter = generic type array (array of INTEGER or array of REAL)
second parameter = INTEGER (size of array)
third parameter = generic type sum (array of INTEGER -> sum will be INTEGER, array of REAL -> sum will be REAL)
I programmed it from ideone.com.
(I want to see just result by array of INTEGER. After that, I will test by array of REAL)
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
procedure test is
generic
type T is private;
type Tarr is array (INTEGER range <>) of T;
--function "+" (A,B : T) return T;
--function "+" (A, B : T) return T is
--begin
-- return (A+B);
--end "+";
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T);
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T) is
temp : T;
count : INTEGER;
begin
count := 1;
loop
temp :=temp+ X(count); //<-This is problem.
count := count + 1;
if count > Y then
exit;
end if;
end loop;
Z:=temp;
end Add_Data;
type intArray is array (INTEGER range <>) of INTEGER;
intArr : intArray := (1=>2, 2=>10, 3=>20, 4=>30, 5=>8);
sum : INTEGER;
procedure intAdd is new Add_Data(Tarr=>intArray, T=>INTEGER);
begin
sum := 0;
intAdd(intArr, 5, sum);
put (sum);
end test;
when I don't overload operator "+", It makes error.
"There is no applicable operator "+" for private type "T" defined."
What can I do for this?
If a generic’s formal type is private, then nothing in the generic can assume anything about the type except that it can be assigned (:=) and that it can be compared for equality (=) and inequality (/=). In particular, no other operators (e.g. +) are available in the generic unless you provide them.
The way to do that is
generic
type T is private;
with function "+" (L, R : T) return T is <>;
This tells the compiler that (a) there is a function "+" which takes two T’s and returns a T; and (b) if the actual T has an operator "+" which matches that profile, to allow it as the default.
So, you could say
procedure intAdd is new Add_Data (T => Integer, ...
or, if you didn’t feel like using the default,
procedure intAdd is new Add_Data (T => Integer, "+" => "+", ...
In addition to not knowing how to declare a generic formal subprogram (Wright has shown how to do this for functions), your code has a number of other issues that, if addressed, might help you move from someone who thinks in another language and translates it into Ada into someone who actually uses Ada. Presuming that you want to become such a person, I will point some of these out.
You declare your array types using Integer range <>. It's more common in Ada to use Positive range <>, because people usually refer to positions starting from 1: 1st, 2nd, 3rd, ...
Generics are used for code reuse, and in real life, such code is often used by people other than the original author. It is good practice not to make unstated assumptions about the values clients will pass to your operations. You assume that, for Y > 0, for all I in 1 .. Y => I in X'range and for Y < 1, 1 in X'range. While this is true for the values you use, it's unlikely to be true for all uses of the procedure. For example, when an array is used as a sequence, as it is here, the indices are immaterial, so it's more natural to write your array aggreate as (2, 10, 20, 30, 8). If I do that, Intarr'First = Integer'First and Intarr'Last = Integer'First + 4, both of which are negative. Attempting to index this with 1 will raise Constraint_Error.
Y is declared as Integer, which means that zero and negative values are acceptable. What does it mean to pass -12 to Y? Ada's subtypes help here; if you declare Y as Positive, trying to pass non-positive values to it will fail.
Z is declared mode in out, but the input value is not referenced. This would be better as mode out.
Y is not needed. Ada has real arrays; they carry their bounds around with them as X'First, X'Last, and X'Length. Trying to index an array outside its bounds is an error (no buffer overflow vulnerabilities are possible). The usual way to iterate over an array is with the 'range attribute:
for I in X'range loop
This ensures that I is always a valid index into X.
Temp is not initialized, so it will normally be initialized to "stack junk". You should expect to get different results for different calls with the same inputs.
Instead of
if count > Y then
exit;
end if;
it's more usual to write exit when Count > Y;
Since your procedure produces a single, scalar output, it would be more natural for it to be a function:
generic -- Sum
type T is private;
Zero : T;
type T_List is array (Positive range <>) of T;
with function "+" (Left : T; Right : T) return T is <>;
function Sum (X : T_List) return T;
function Sum (X : T_List) return T is
Result : T := Zero;
begin -- Sum
Add_All : for I in X'range loop
Result := Result + X (I);
end loop Add_All;
return Result;
end Sum;
HTH
I'm currently working on AES encryption using keys of three different sizes (128,192, and 256 bit).
I was wondering if I can declare / use a std_logic_vector of a variable size? For example, can I just have one input port and I get to know wether it's 128,192, or 256 bit based on the user input?
Or else if I choose the max key length, which is 256 bit, can I assign a 128 or 192 bit key to that std_logic_vector? Or will an error message appear?
If the size of key changes at run-time, you will have to declare
the corresponding objects (signals, constants, variables) with the
maximum possible size. The actual key length will then be defined by another
signal or variable. The maximum size may be defined as below.
If you declare an object of type std_logic_vector with the maximum possible size, then assigning a shorter std_logic_vector will result in an error. You will have to extend the right-hand aside of the assignment to the size of the target object first, e.g. using the following resize function from the PoC Library where I'm one of the authors:
function resize(vec : std_logic_vector; length : natural; fill : std_logic := '0') return std_logic_vector is
constant high2b : natural := vec'low+length-1;
constant highcp : natural := imin(vec'high, high2b);
variable res_up : std_logic_vector(vec'low to high2b);
variable res_dn : std_logic_vector(high2b downto vec'low);
begin
if vec'ascending then
res_up := (others => fill);
res_up(vec'low to highcp) := vec(vec'low to highcp);
return res_up;
else
res_dn := (others => fill);
res_dn(highcp downto vec'low) := vec(highcp downto vec'low);
return res_dn;
end if;
end function;
For example, given a 128-bit std_logic_vector named source, this can be re-sized to 256 bit with:
resize(source, 256) -- returns a 256-bit std_logic_vector
The function works like the resize function on unsigned and signed from package numeric_std.
If the key size is known at compile (elaboraton) time, then you will
have two options. A usual approach is to define the key size by a
constant and passing the key size via generics to sub-components.
The following entity test has a generic SIZE specifying the key
size. The length of ports as well as other objects, can now be defined
depending on this generic.
library ieee;
use ieee.std_logic_1164.all;
entity test is
generic (
SIZE : positive := 128); -- the default value can be omitted
port (
x : in std_logic_vector(SIZE-1 downto 0);
y : out std_logic_vector(SIZE-1 downto 0));
end entity test;
architecture rtl of test is
begin -- architecture rtl
y <= not x;
end architecture rtl;
The generic can now be bound during the instantiation of this entity,
for example:
library ieee;
use ieee.std_logic_1164.all;
entity test_tb is
end entity test_tb;
architecture rtl of test_tb is
constant SIZE : positive := 192;
signal x : std_logic_vector(SIZE-1 downto 0) := (others => '0');
signal y : std_logic_vector(SIZE-1 downto 0);
begin -- architecture rtl
dut: entity work.test
generic map (
SIZE => SIZE)
port map (
x => x,
y => y);
end architecture rtl;
Of course, the length of the actuals (right side in port map) must
match the length of the formals (left side in port map). This approach
is supported by all (major) VHDL synthesis tools. If default values
for the generics are present, then test can be directly synthesized as
top-level module.
The second option, for a fixed key-size during elaboration, would be
to use unconstrained arrays (std_logic_vector) in the port
declaration of the entity. The actual size of the array can be
determined with the length atribute, and the actual range with the
range attribute, for example:
library ieee;
use ieee.std_logic_1164.all;
entity test2 is
port (
x : in std_logic_vector;
y : out std_logic_vector);
end entity test2;
architecture rtl of test2 is
signal z : std_logic_vector(x'range);
begin -- architecture rtl
z <= x;
y <= not z;
assert false report "x'length=" & integer'image(x'length) severity note;
end architecture rtl;
The range (and length) of the port signals will then be
constrained by the associated actual in the component instantiation.
library ieee;
use ieee.std_logic_1164.all;
entity test2_tb is
end entity test2_tb;
architecture rtl of test2_tb is
constant SIZE : positive := 192;
signal x : std_logic_vector(SIZE-1 downto 0) := (others => '0');
signal y : std_logic_vector(SIZE-1 downto 0);
begin -- architecture rtl
dut: entity work.test2
port map (
x => x,
y => y);
end architecture rtl;
This works in simulation. But, I'm not sure whether it is supported by
the (major) VHDL synthesis tools. Of course, for synthesis of test2
another top-level entity is required which instantiates test2 to
constraint the array ranges.
I was trying to return type std_logic_vector by type conversion in vhdl.
Here is my code:
function mul(num1,num2 : in std_logic_vector(7 DOWNTO 0)) return std_logic_vector is
variable v_TEST_VARIABLE1 : integer;
variable v_TEST_VARIABLE2 : integer;
variable n_times: integer:=1;
variable product: integer:=0;
begin
for n_times in 1 to v_TEST_VARIABLE2 loop
product:=product + v_TEST_VARIABLE1;
end loop;
return std_logic_vector(product);
end mul;
It gives "Illegal type conversion from std.standard.integer to ieee.std_logic_1164.std_logic_vector (numeric to array)." on compilation.
How do I return std_logic_vector in such a code?
See Russell's post first. If you use the VHDL-2008, numeric_std_unsigned package, then you can use just one conversion:
use ieee.numeric_std_unsigned.all ;
...
return to_std_logic_vector(product, length) ; -- long form
-- alternate short form
return to_slv(product, length) ;
Usage warning: for synthesis, I consider VHDL-2008 items to be on the bleeding edge of support. Hence, while I use VHDL-2008 frequently in my testbenches, I try to limit the usage of it in my RTL code to what can't be done using other methods. However, if you ever want to use code like this, it is it is important to try it out in your synthesis tool and submit a bug report against it if it does not work - that is the only way change happens.
You must first convert it to an unsigned. I hope you're using numeric_std? If so, your code looks like this. Note that to use to_unsigned you must know the length of your output std_logic_vector. So this either needs to be an input to your function or you can bound the return vector:
return std_logic_vector(to_unsigned(product, length));
More information about how to convert std_logic_vector to integer.