How to convert std_logic to unsigned in an expression - vhdl

So if wanted to assign a std_logic to a 1-bit usnigned I could just write...
signal X : unsigned(0 downto 0);
signal Y : std_logic;
X(0) <= unsigned(Y)
But what s the best way to convert a std_logic to an unsigned when used in an expression.
That is to say, without directly doing an assignment to a signal of type unsigned.
The scenario I have is this. I have two flags A and B that are signals of type std_logic.
Each flag has a strobe (A_valid , B_valid) of type std_logic that assert for 1 clock cycle each time their flag (A , B) is valid.
I have a counter (CNT) that is a signal of type unsigned that must count the number of times that either of the flags is '1'.
On any given clock cycle I must incrment CNT by 0, 1, or 2 depending on how many flags are 1.
Here is the straight forward way of doing it with an "if" statement.
signal A : std_logic;
signal A_valid : std_logic;
signal B : std_logic;
signal B_valid : std_logic;
signal CNT : unsigned;
if rising_edge(clk) then
if (A and A_valid and B and B_valid) = '1' then
CNT <= CNT + 2;
elsif (A and A_valid) = '1' then
CNT <= CNT + 1;
elsif (B and B_valid) = '1' then
CNT <= CNT + 1;
end if;
end if;
The problem with the code above is that it doesn't generalize very well since the number of cases goes up exponentially with the number of flags. For example if I had 5 flags I would have to write out 32 branches in the IF statement.
A more compact way of representing the same thing using an aggregate and a type mark is...
This is better becasue I just write one expression for each flag.
if rising_edge(clk) then
CNT <= CNT + unsigned'(0=> A AND A_valid) + unsigned'(0=> B AND B_valid);
end if;
Are there any other built-in ways (other than writing a function) to convert std_logic to unsigned in an expression in VHDL?

The easiest way is to concatenate the std_logic with a null array, yielding an array of length 1.
Cnt <= cnt + ("" & a_valid);
It should be able to work out the type from the context, otherwise you may need to qualify it with unsigned'

Related

Getting "test2.vhd(43): VHDL Compiler exiting" error with if-statement on commented out lines but not with the "sum2" lines

As the title says, I'm getting a compiler exiting error with the if-statement when I use the lines commented out with the "sum" value but not with the "sum" 2 value and I'm not sure why.
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.std_logic_unsigned.all;
entity test2 is port
(
a, b : IN unsigned( 3 DOWNTO 0 );
cin : IN unsigned;
sum : OUT unsigned( 4 DOWNTO 0 )
);
end test2;
architecture behavioral of test2 is
signal a_5, b_5, cin_5, sum2 : unsigned(4 downto 0) := (others => '0');
signal x, y : unsigned(4 downto 0) := (others => '0');
signal z : std_logic;
begin
a_5 <= ('0' & a);
b_5 <= ('0' & b);
cin_5 <= ('0' & '0' & '0' & '0' & cin);
sum <= a_5 + b_5 + cin_5;
sum2 <= a_5 + b_5 + cin_5;
process (sum2, b_5)
--process (sum, b_5)
begin
if (sum2 > b_5) then
--if (sum > b_5) then
z <= '1';
else
z <= '0';
end if;
end process;
end behavioral;
For some context:
I'm working on an adder that adds two 4bit numbers and eventually displays the decimal value on a 7seg display.
I want to take the "sum" value and check if it is greater than decimal value 9 and if so then it sets a flag to always have the 7seg display for the 10s value display a 1. (I only need to count up to decimal value 19). I can probably do this another method but I started doing it this way and got stuck here and I think this is something fundamental I am just not understanding.
sum is a port, which has the type "out". Ports out type "out" can't be read. If you want to read an output port, you must use the type "buffer". sum2 instead is a signal, which can always be read
(By the way you should only use numeric_std and not std_logic_unsigned, which is an old solution and not preferred anymore).

Incompatibile Slices in VHDL

I am learning VHDL and for first project I picked up simple Brainfuck processor. When I try to compile it, I get error about incompatibile slices. I am using EdWinXP. How do I fix my code? Are there many mistakes in my code? Is there alternative of VHDL that would be simpler for C programmer?
use ieee.std_logic_1164.all;
entity BFCPU is
port (
I0 : in std_logic; --INPUT
I1 : in std_logic; --PROGRAM
I2 : in std_logic; --PROGRAM READY
O1 : out std_logic; --PROGRAM NEEDED
O2 : out std_logic; --OUTPUT
O3 : out std_logic; --OUTPUT WRITTEN
O4 : out std_logic); --INPUT NEEDED
--O5 : out std_logic); --INPUT POOLING CLOCK
end BFCPU;
architecture work of BFCPU is
type t_Memory is array (0 to 127) of std_logic_vector(7 downto 0);
signal rammem : t_Memory;
signal pointer : std_logic;
begin
pointer <= 0;
workflow: process (I2) is
begin
if I1=1 then
rammem(pointer) <= std_logic_vector(unsigned(rammem(pointer)) + 1);
elsif I1=2 then
rammem(pointer) <= std_logic_vector(unsigned(rammem(pointer)) - 1);
elsif I1=3 then
pointer <= pointer - 1;
elsif I1=4 then
pointer <= pointer + 1;
elsif I1=5 then
O2 <= rammem(pointer);
elsif I1=6 then
O4 <= not O4;
inwait: while( I0 = 0 ) loop
if not (I0 = 0) then
rammem(pointer) <= I0;
end if;
end loop inwait;
O4 <= not O4;
end if;
end process workflow;
end work;
What you're writing below the begin statement and outside a process is always true, so this isn't sequential in any form. Imagine like an FPGA pin, which is soldered to ground.
You try to manipulate the pointer signal from within a process, but you can't because your pointer is fixed to '0'.
If you want the pointer initializing to '0', as it looks like, you have to put this line within the process. However, i see you try to call arithmetic operations with the pointer signal, but you are defining the signal as std_logic. std_logic can represent '0', '1' and several other states, like High-Z, but not a number. You should take an integer or natural for calculations.

Constructing a 20kbit bit_vector data from 16bit unsigned_vector

I'm very new in VHDL and having a problem about assigning values I guess.
Let's say that I've a module that get an 16 bit input signal noisein_mono for every positive edge of the clock source. What I want is to construct a 20 Kbit long bit vector from this 16-bit inputs. So I'm gonna perform random number tests on it FIPS_140-2
The code I end up with is shown below:
-- Entity Decleration
entity MonoTestModule is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
start : in STD_LOGIC;
noisein_mono : in STD_LOGIC_VECTOR (15 downto 0);
running_mono : out STD_LOGIC;
tok_mono : out STD_LOGIC
);
end MonoTestModule;
architecture Behavioral of MonoTestModule is
-- Signal to communication between processes.
signal enable_20k_bit_stream : std_logic;
begin
process (rst, clk, start, noisein_mono)
variable count : integer := 0;
variable twnty_k_bit_stream : bit_vector(19999 to 0);
begin
if(start = '1') then
if (rising_edge(clk)) then
count := count + 1;
twnty_k_bit_stream := twnty_k_bit_stream or to_bitvector(noisein_mono);
twnty_k_bit_stream := twnty_k_bit_stream sll 16;
end if;
if (rst = '1') then
count := 0;
enable_20k_bit_stream <= '0';
end if;
-- if count is reached to 1250, 20kbit is constructed.
if(count = 1250) then
enable_20k_bit_stream <= '1';
else
enable_20k_bit_stream <= '0';
end if;
end if;
end process;
I'm using Xilinx ISE 14.7. The compiler pops up error says Line 52: Unequal length arguments for operator "or".
How can I solve this problem?
My best regards.
In simulation this would be two different run-time errors.
There's actually two bounds mismatch errors, one for the "or" on two array values:
twnty_k_bit_stream := twnty_k_bit_stream or
to_bitvector(noisein_mono);
And one for the assignment to twnty_k_bit_stream where the length doesn't match following an implicit subtype conversion.
And that's because
variable twnty_k_bit_stream : bit_vector(19999 to 0);
that to should be downto. When the direction is wrong you'll end up with a null range (an array with no elements).
See IEEE Std 1076-2008 9.2.2 Logical operators, para 3:
If both operands are one-dimensional arrays, the operands shall be arrays of the same length, the operation is performed on matching elements of the arrays, and the result is an array with the same index range as the left operand. If one operand is a scalar and the other operand is a one-dimensional array, the operation is performed on the scalar operand with each element of the array operand. The result is an array with the same index range as the array operand.
So uneven length arrays don't work.
Also see 10.6.2.1 (Variable assignment), paras 5 and 7:
For the execution of a variable assignment whose target is a variable name, the variable name and the expression are first evaluated. A check is then made that the value of the expression belongs to the subtype of the variable, except in the case of a variable that is of a composite type (in which case the assignment involves a subtype conversion). Finally, each subelement of the variable that is not forced is updated with the corresponding subelement of the expression. A design is erroneous if it depends on the order of evaluation of the target and source expressions of an assignment statement.
...
An error occurs if the aforementioned subtype checks fail.
And that error occurs if there isn't a corresponding element in both the target and right hand side expression of the variable assignment.
5.3.2.2 Index constrains and discrete ranges, para 4:
An array constraint of the first form is compatible with the type if, and only if, the constraint defined by each discrete range is compatible with the corresponding index subtype and the array element constraint, if present, is compatible with the element subtype of the type. If any of the discrete ranges defines a null range, any array thus constrained is a null array, having no elements. An array value satisfies an index constraint if at each index position the array value and the index constraint have the same index range. (Note, however, that assignment and certain other operations on arrays involve an implicit subtype conversion.)
Fix both those things:
begin
process (rst, clk) -- , start, noisein_mono) -- not needed
variable count: integer := 0;
variable twnty_k_bit_stream: bit_vector(19999 downto 0); -- was to
begin
if start = '1' then
if rising_edge(clk) then
count := count + 1;
-- twnty_k_bit_stream := twnty_k_bit_stream or
-- to_bitvector(noisein_mono);
-- twnty_k_bit_stream := twnty_k_bit_stream sll 16;
twnty_k_bit_stream (twnty_k_bit_stream'LEFT downto noisein_mono'LENGTH) :=
twnty_k_bit_stream (twnty_k_bit_stream'LEFT - noisein_mono'LENGTH downto 0);
twnty_k_bit_stream (noisein_mono'RANGE) :=
to_bitvector(noisein_mono);
end if;
noting I also fixed the sensitivity list and we get something that doesn't have a bounds check error. Instead of using an "or" this shifts then writes the lower 16 bits with noisein_mono.
Adding a testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity monoblahblah_tb is
end entity;
architecture foo of monoblahblah_tb is
signal clk: std_logic := '0';
signal rst: std_logic;
signal start: std_logic;
signal noisein_mono: std_logic_vector (15 downto 0);
signal running_mono: std_logic;
signal tok_mono: std_logic;
begin
DUT:
entity work.monotestmodule
port map (
clk => clk,
rst => rst,
start => start,
noisein_mono => noisein_mono,
running_mono => running_mono,
tok_mono => tok_mono
);
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if now > 12680 ns then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 6 ns;
rst <= '0';
start <= '0';
noisein_mono <= (others => '0');
wait for 10 ns;
rst <= '1';
wait for 10 ns;
rst <= '0';
wait for 100 ns;
start <= '1';
for i in 0 to 1249 loop -- 20,000 / 16
noisein_mono <=
std_logic_vector(to_unsigned(i, noisein_mono'length))
xor
x"dead";
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
And we get:
And if I had thought about it I would have XOR'd different values in consecutively, these values are simply unique from 0 to 1249 as binary XOR'd with x"DEAD". (It seemed outré to write a random number generator for a simple testbench, considering the state of twnty_k_bit_stream isn't displayed. The purpose is to show there are no bounds check failures.)
So there were two semantic errors detectable at run time (or synthesis) and an incorrect sensitivity list.

Error for if statement condition in adder/subtractor

I am new to the VHDL language, so please bear with me and please help me out.
I have written code for a addition/subtraction unit which will operate on signed integer but at the "if else" part in the last, the compiler is giving an error.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(A,B : in std_logic_vector(3 downto 0);
SUM : out std_logic_vector(3 downto 0);
mode: in std_logic_vector(0 downto 0));
end adder;
architecture behave of adder is
component xorgate is
port( p,q: in std_logic_vector(3 downto 0);
r: out std_logic_vector(3 downto 0));
end component;
signal a1,b1,sum1,output1,mode1:integer;
signal tmp: std_logic_vector(3 downto 0);
variable output: std_logic_vector(3 downto 0);
begin
u1: xorgate port map (B, mode, output);
output1 <= to_integer(signed (output));
a1 <= to_integer(signed(A));
b1 <= to_integer(signed(B));
mode1 <= to_integer(signed(mode));
process(a1,output1,b1,tmp,mode1)
begin
if ( mode1 <= '1') then
sum1 <= a1 + output1 ;
else
sum1 <= a1 + b1;
end if;
tmp <= std_logic_vector(to_signed(sum1,4));
SUM <= tmp( 3 downto 0);
end process;
end behave;
XST Error Message:
ERROR: HDLCompiler:1731 - "E:\XILINX PROGRAM\FULLADD\FULLADD.vhd" Line 31: found '0' definitions of operator "<=", cannot determine exact overloaded matching definition for "<="
ERROR: HDLCompiler:854 - "E:\XILINX PROGRAM\FULLADD\FULLADD.vhd" Line 11: Unit ignored due to previous errors.
Line 31: if ( mode1 <= '1') then
you meant: if ( mode1 = 1) then
Line 11: This just means that because of the previous error, the compiler 'gave up'.
The <= operator in mode1 <= '1' is less-than-or-equal compare of integer with '1', which have no definition, thus the found '0' definitions of operator "<=". Change '1' to simply the integer literal1`.
Other issues with the code are listed below.
The ´variable output: ...´ must be signal output: when output is used as actual for in port map for xorgate. In typical design you don't have variables in the declaration section, between begin and end, of an architecture.
Length of mode is only 1 std_logic (bit), but actual for mode in xorgate port map, which is q in xorgate, is 4 bits. You probably meant to make mode as 3 downto 0 in the port declaration of adder, since compare like mode1 <= 1 will be trivial true if mode is 1 bit.
The intermediate integer signals named *1 and other signal are actually not required if the process uses signed additions from numeric_std package like:
process(A, B, mode, output) is
begin
if signed(mode) <= 1 then
SUM <= std_logic_vector(signed(A) + signed(output));
else
SUM <= std_logic_vector(signed(A) + signed(B));
end if;
end process;
And this can even be reduced to the below, with only output as intermediate signal:
SUM <= std_logic_vector(signed(A) + signed(output)) when (signed(mode) <= 1)
else std_logic_vector(signed(A) + signed(B));
Finally, if mode is to be treaded like unsigned, then replace with unsigned(mode), since unsigned is also defined in the numeric_std package.
The puzzle is probably why the error message is about failure to find an overloaded operator
'1' has at least two definitions, first as a character literal, then as a bit literal. Neither of these have a <= operator comparing them with type Integer, and that's why the compiler gave up.
If you had used an integer literal 1 instead, the compiler could have found a <= operator easily... so if mode1 <= '1' then would work.
Alternatively, you could write your own <= operator accepting inputs of these two types and returning a boolean :
function "<=" (a : Integer; b : Bit) return Boolean is ...
While it would work, it would also deserve a slap on the wrist!

Split n long bit logic vector to n individual binary values

I was wondering if there was a method where you can split a n bit long vector for example:
10100111
Into n individual binary units to be used later on? I'm trying to incorporate a method where i can get a 8 bit long vector and have 8 LED's light up depending if that n'th value is 0 or 1. Googling the question returns people cutting up a larger vector into smaller ones, but if we were to have 16 bits for example then i'd have to make 16 separate variables for it work using:
entity test is
port (
myVector : in std_logic_vector(16 downto 0);
LED : out std_logic_vector(16 downto 0)
);
END test
architecture behavior of test is
SIGNAL led1 : std_logic;
...
SIGNAL led16 : std_logic;
BEGIN
led1 <= myVector(0);
...
led16 <= myVector(16);
LED(1) <= '1' when led1 = '1' else '0';
...
LED(16) <= '1' when led16 = '1' else '0';
END behavior
Doesn't seem tidy when it needs to be repeated several times in the code.
If you want to declare and assign to identifiers with different names, then you have to make a line for each name, since there is no loop statement for identifier name manipulation in VHDL.
But VHDL provides arrays, where you can loop over the entries, like with this example code:
...
signal led_sig : std_logic_vector(16 downto 0);
begin
loop_g: for idx in myVector'range generate
led_sig(idx) <= myVector(idx);
LED(idx) <= '1' when led_sig(idx) = '1' else '0';
end generate;
...
Where the assigns are equivalent to the shorter:
led_sig <= myVector;
LED <= led_sig;

Resources