Division in VHDL (int/float) - math

I want to divide two numbers(16-bit binary) in VHDL in 1 cycle (combinational circuit). Numerator is an integer. Denominator is a float. Result should be float. What algorithm do i use to perform the division.
Please help

Here is an entity that does what you want (if I understand the question correctly):
library ieee;
use ieee.numeric_std.all;
use ieee.float_pkg.all;
entity integer_by_float_division is
port (
numerator: in signed(15 downto 0);
denominator: in signed(15 downto 0);
result: out float(6 downto -9)
);
end;
architecture rtl of integer_by_float_division is
subtype float16 is float(6 downto -9);
signal numerator_float: float16;
signal denominator_float: float16;
begin
numerator_float <= to_float(numerator, numerator_float);
denominator_float <= to_float(denominator, denominator_float);
result <= numerator_float / denominator_float;
end;

I don't think this is possible. Is there any reason that you need to do it in 1 clock cycle? The only way to get close would be to use a look-up table, but you would have to sacrifice some precision on the output.

Related

convert and resize vector

I have following code (simplified):
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use ieee.std_logic_arith.all;
entity foo is
end entity;
architecture fum of foo is
signal slv16 : STD_LOGIC_VECTOR(15 DOWNTO 0);
signal slv5 : STD_LOGIC_VECTOR(7 DOWNTO 0);
begin
slv16 <= std_logic_vector(resize(unsigned(slv5), slv16'length));
end architecture;
I get an error message that 'resize' can not be matched to a subprogram. Why?
I think I found out the problem. I used this two libraies:
USE ieee.numeric_std.all;
USE ieee.std_logic_arith.all;
while both have the same implemenation for unsigned as follows:
type UNSIGNED is array (NATURAL range <>) of STD_LOGIC;
after deleting the synopsis library the error message is gone. Although I understand the problem here the error message above gave me a wrong direction to look at.
Thanks!

subtracting std_logic_vector from integer

I have a problem subtracting a STD_LOGIC_VECTOR from a integer.
This is the code I have right now:
entity ROM is
Port ( hcount: in STD_LOGIC_VECTOR(9 downto 0);
vcount: in STD_LOGIC_VECTOR(9 downto 0);
hpos: in integer;
vpos: in integer;
clk25: in STD_LOGIC;
Pixeldata: out std_logic);
end ROM;
architecture Behavioral of ROM is
signal romtemp : std_logic_vector(9 downto 0);
shared variable yas : integer range 0 to 9 := 0;
shared variable xas : integer range 0 to 9 := 0;
Type RomType is array (9 downto 0) of std_logic_vector(9 downto 0);
Constant Rom: RomType :=
( "0001111000", "0111111110", "0111111110", "1111111111", "1111111111"
, "1111111111", "1111111111", "0111111110", "0111111110", "0001111000");
begin
process(clk25)
begin
if(hpos > hcount - 10) and (hpos <= hcount) and (vpos > vcount - 10) and (vpos <= vcount) then
xas := hpos - to_integer(unsigned(hcount));
end if;
end process;
end Behavioral;
The problem is the following line of code:
xas := hpos - to_integer(unsigned(hcount));
I am trying to put the subtraction in the integer named xas.
The following errors occur on that line:
Error: Multiple declarations of unsigned included via multiple use clauses; none are made directly visible
Error: Expecting type unsigned for < unsigned(hcount) >.
Error: Formal < arg > has no actual or default value.
Error: Type integer is not an array type and cannot be indexed
Error: found '0' definitions of operator "=", cannot determine exact overload matching definition for "-"
Someone that can help me with this error? (I am a beginner in VHDL)
You haven't included your use clauses at the top of the file, but what this error is saying is that from the use clauses, it found two different definitions of unsigned. Because of this, the tool has ignored both definitions, generating an error and forcing you to deal with the problem.
The most likely explanation is that you have:
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
std_logic_arith is nonstandard, and you should implement your design using the types and functions available in numeric_std only. Remove the std_logic_arith line.
In general, if something is a number, use a numeric type to represent it. For example, your hcount and vcount inputs are clearly counters, and could use type unsigned. If you use more appropriate types in the first place, you avoid the need for awkward looking type conversions, for example:
xas := hpos - to_integer(unsigned(hcount));
would become
xas := hpos - hcount;
Additional problems in your code:
Your process sensitivity list contains only clk25, but the process is not actually a synchronous process, and so all the input signals used should be in the list (or you can use the reserved all keyword to generate an automatic list, i.e. process(all)).
Unless this is some special case, you are better off getting into the habit of writing synchronous processes. These look like this:
process(clk)
begin
if (rising_edge(clk)) then
-- Do things
end if;
end process;
xas is a shared variable, which implies that you might be assigning it in other processes as well. This will probably not work how you expect it to. You should avoid shared variables altogether until you have a good understanding of exactly how they work, and when it might be appropriate to use them.

VHDL Vector passing

I want to pass a value from one vector to another.
Can I simply do it this way?
vector_one : out STD_LOGIC_VECTOR (3 downto 0);
vector_two : out STD_LOGIC_VECTOR (3 downto 0);
vector_one <= vector_two;
The vector_one is an output port (mode out), and reading this is allowed in VHDL-2008, so you can do:
vector_one <= vector_two;
However, in VHDL-2002 it is not allowed to read an output port, so you must drive both outputz from the source, say vector_source, like:
vector_one <= vector_source;
vector_two <= vector_source;
Generally, it should be avoided to duplicate an output signal like that, since it is not obvious from the use of that module that some output are driven with identical values, which makes it harder to understand the module use.
you can but you need to take note that if you will need to use vector_one in your module before it gets used outside meaning that the module will need to hold information about it. Then you will need to declare an internal signal in order to work on it.
example:
entity exampleModule is
port( iClk : in STD_LOGIC;
iTrigger : in STD_LOGIC;
iVector_one : out STD_LOGIC_VECTOR (3 downto 0);
oVector_two : out STD_LOGIC_VECTOR (3 downto 0));
end exampleModule ;
Architecture RTL of exampleModule is
signal mVectorBuff : std_logic_vector (3 downto 0);
begin
process (iClk) begin
if rising_edge (iClk) then
if iTrigger then mVectorBuff <= iVector_one;
end if;
end if;
end process;
oVector_two <= mVector_one;
end Architecture RTL;

using a VHDL generate statement in a function

I want to use generate statement but in my code I have a case statements which only takes sequential statements.
Then I thought I will use it in a package where I can define a function such that there also I am getting error as : 'Illegal Sequential statement'.
So what can be done. Any suggestions?
Code block:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE work.my_package.all;
-- Entity for ALU component
-- Use this Entity for your C&A project
ENTITY ALU_E IS
PORT(
reset_n : in std_logic;
clk : in std_logic;
OperandA : in std_logic_vector(3 downto 0);
OperandB : in std_logic_vector(3 downto 0);
Operation : in std_logic_vector(2 downto 0);
Start : in std_logic;
Result_Low : out std_logic_vector(3 downto 0);
Result_High : out std_logic_vector(3 downto 0);
Ready : out std_logic;
Errorsig : out std_Logic);
END ALU_E;
architecture Behavioral_ALU of ALU_E is
signal c : std_logic_vector(7 downto 0);
signal carry_internal :std_logic_vector(4 downto 0);
COMPONENT fulladder IS
PORT(
a: IN std_logic;
b: IN std_logic;
cin : IN std_logic;
cout: OUT std_logic;
s: OUT std_logic );
END component fulladder;
begin
adders: for N in 0 to 3 generate
ff1:fulladder
port map
(a => OperandA(N),b => OperandB(N),cin => carry_internal(N),cout => carry_internal(N+1),s => c(N));
end generate adders;
c(4) <= carry_internal(4);
process(clk,reset_n)
begin
if reset_n = '0' then
if (clk'event) then
case Operation is
when "000" => --no operation
NULL;
when "001" => --Rotate left logical operator ?0000?&A by B steps
c <= rotlef (OperandA,OperandB);
when "010" => --Rotate right logical operator ?0000?&A by B steps (result width is 8 bit)
c <= rotrig (OperandA,OperandB);
when "011" => --Bitwise XOR operation
Result_Low <= OperandA xor OperandB;
when "100" => --Sum of A and B
--here i want to use a statement such that i can call the gatelevel --add function
--I have already all functions gatelevel defined when i try to use portmap or ----generate it gives an error illegal sequential statement
when Others =>
NULL;
end case;
end if;
end if;
end process;
end Behavioral_ALU;
There are a couple of misconceptions in the question.
First the title : there is no function in your actual code. What you have done with the for ... generate statement is generate a separate piece of hardware, operating in parallel with the main process. It will always operate, and always drive signal 'c' with the sum, as if you had written c <= a + b; in place of the for ... generate. It's always, continuously working, not a function you can call only when you want to.
Second, that means that both the adder and the clocked process drive c all the time, with different values. This will not go well... in fact you should see "XXXX" on signal c in simulation.
What I think you want to do is create a new signal, called sum for the adder's output, and drive sum, not c, in the for ... generate. Then, in the Case statement, assigning sum to c will accomplish the Add operation.
As far as why you get the error messages you do, a component instantiation statement or generate statement is a concurrent statement, while a case choice or a function body is comprised of sequential statements.
You don't need a function, you need the sum and carry out from the generate statement instantiated four fulladders.
o
Dummy up an entity/architecture pair for fulladder:
library ieee;
use ieee.std_logic_1164.all;
entity fulladder is
port (
a: in std_logic;
b: in std_logic;
cin: in std_logic;
cout: out std_logic;
s: out std_logic
);
end entity;
architecture foo of fulladder is
begin
s <= a xor b xor cin;
cout <= (a and b) or (a and cin) or (b and cin);
end architecture;
Dummy up a non functional my_package:
library ieee;
use ieee.std_logic_1164.all;
package my_package is
function rotlef (a, b: std_logic_vector) return std_logic_vector;
function rotrig (a, b: std_logic_vector) return std_logic_vector;
end package;
package body my_package is
function rotlef (a, b: std_logic_vector) return std_logic_vector is
variable ret_val: std_logic_vector (a'range);
begin
return ret_val;
end function;
function rotrig (a, b: std_logic_vector) return std_logic_vector is
variable ret_val: std_logic_vector (a'range);
begin
return ret_val;
end function;
end package body;
(note the function return value lengths match the left operand length)
Add a new declaration for the output of the generated fulladders:
architecture changed of alu_e is
signal c: std_logic_vector(7 downto 0);
signal carry_internal: std_logic_vector(4 downto 0);
signal s: std_logic_vector(3 downto 0); -- added
Change the generate statement to use the new signal for the sum:
adders:
for n in 0 to 3 generate
ff1:
fulladder
port map (
a => operanda(n),
b => operandb(n),
cin => carry_internal(n),
cout => carry_internal(n+1),
s => s(n) -- was c(n)
);
end generate;
-- c(4) <= carry_internal(4);
(eliminating the assignment to c(4))
And change the sequence of statements for choice "100":
when "100" => --sum of a and b
result_low <= s; -- added
result_high(0) <= carry_internal(4); --(un)signed?
And your design analyzes, elaborates and simulates (while not doing much - no assignments in the process for case others when operation is undriven and all Us, I didn't write a testbench to drive operation or provide it with a default value).
Notice the declaration of c has a length of 8 while the return value of the two functions will match their a input (length 4).
If you were to execute the dummy functions for operations "001" or "010" you'd get a simulation error due to length mismatch on the right hand side. I left this as is with no insight in to whether or not your rotlef or rotrig functions actually return a longer length.
In general you only want an 8 bit result for multiplies. The length of c and how it get's assigned to result_low and result_high aren't apparent (as yet).
It wasn't possible to discern whether you're doing signed or unsigned arithmetic without more detail. Instead of:
result_high(0) <= carry_internal(4); --(un)signed?
A signed sign extension could look like:
result_high <= (others => carry_internal(4)); --sign extended
Note that when you instantiate your multiplier you'd also want to use a new signal declaration for the 8 bit result. Modifying your rotate operations to assign result_low and result_high would allow c to be used for an instantiated multiply, although you might choose to rename it.
Think of the case statement in the process statement as instantiating a multiplexer, and in some cases you happen to be also expressing logic on inputs. The xor or the sign extension or function calls (which are expressions) are examples.
When you have instantiated components providing function you want to connect their output to a multiplexer input.

Is N-1 the largest term which could be used for Generic in VHDL

I am new to VHDL and I wanted to ask that what generic term could I use If i wanted to write any size of input vector which could be developed?
GENERIC (n1 : integer);
x:IN BIT_VECTOR(n1-1 downto 0);
Is that a correct example?
Your generic has no default value visible.
Your declaration for x is incomplete. It appears to be an entity declarative item with a mode while you don't have a port declaration.
This VHDL code is syntactically and semantically valid:
entity foo is
generic ( n1: integer);
port (
x: in bit_vector(n1-1 downto 0)
);
end entity;
architecture fum of foo is
begin
end architecture;
It will analyze. It can't be elaborated without the value of n1 being known:
entity foo_tb is
constant N_1: integer := 4;
end entity;
architecture fum of foo_tb is
signal x: bit_vector (N_1-1 downto 0);
begin
DUT:
entity work.foo
generic map (n1 => N_1)
port map ( x => x);
end architecture;
Entity foo by itself can't be the top level of an elaborated model because n1 isn't defined for elaboration.
Entity foo_tb can be elaborated, it uses the constant N_1 to supply a value to n1.
foo_tb can even be simulated, but it will exit immediately because there are no pending signal assignments after initialization.
Neither foo nor foo_tb can be synthesize. foo_tb because it has no ports and any logic in it's design hierarchy would be optimized away as unused. foo because it only has an output and is at best a constant.
If foo had multiple ports, with outputs depending on inputs it would be eligible for synthesis or simulation as long as the generic was defined for elaboration.
(And the moral here is to use a Minimal, Complete, and Verifiable example so someone doesn't have to wave their hands around it's shortcomings).
You can use every term, as far as it's result does not exceed the BIT_VECTORS's array range.
BIT_VECTOR definition: type BIT_VECTOR is array (NATURAL range <>) of BIT;
So your term can have results from 0 to 2**32 - 1
Term examples:
4*n1 - 1 downto 0
n1/4 + 8 downto 0
log2ceilnz(n1) - 1 downto 0
2**n1 - 1 downto 0
According to the " Paebbels" comment I edit this answer :
Every time you want to synthesize your code, synthesis tool should know about the size of parameters you used, Otherwise what exactly you want to synthesize ?!!! (what hardware ?!)
If you want to synthesize your top module code which contains a generic parameter in it's own entity, you can assign it with a default value such as the following code :
ENTITY ... IS
GENERIC(n1 : INTEGER := 8);
PORT(
-- use generic parameter
);
END ENTITY;
Also you can use the generic parameter inside architecture ( size of signals, index of loops, ... ).

Resources