How do I extract a single bit out of a std_logic_vector and convert it to an integer? - vhdl

I am struggling with type conversion in vhdl. I am pretty new to vhdl and apologize, if this is a really stupid question.
But what i want to do is, i want to go through the input vector and add all bits together to form an integer.
For example "11001010" shall result in 4 (or "100"). And "11101010" would result for example in 6 (or "110"). How can i achieve that?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity xyz is
port(
input: in std_logic_vector(7 downto 0);
output: out std_logic_vector(7 downto 0)
);
end entity;
architecture behaviour of xyz is
signal temp : integer := 0;
begin
evaluate_input :process is
begin
for i in input'left downto input'right loop
temp <= temp + to_integer(unsigned(input(i)));
end loop;
wait;
end process;
stop_simulation :process is
begin
wait for 100 ns; --run the simulation for this duration
assert false
report "simulation ended"
severity failure;
end process;
end xyz;

Don't think to complicated. You want to calculate the hamming weight.
for i in input'range loop
temp <= temp + (1 when (input(i) = '1') else 0);
end loop;
Or with your proposed way:
for i in input'range loop
temp <= temp + to_integer(unsigned(input(i downto i)));
end loop;
unsigned(...) needs an array of std_logic_vector. By using just i, you get a single std_logic. Whereas, i downto i creates another std_logic_vector of length 1, which can be used in unsigned.

Related

VHDL Error "Expecting constant slice on LHS"

I wrote a code. This should insert a "1" at a position, which is determined by the binary part of a signal E_reg_sig. The bits left to the "1" should be filled up by the fractional bits of a signal E_reg_sig.
There are some special cases:
The position is higher than the Output signals range: then all bits are set to high
There are more bits left right to the "1" than E_reg_sig has fractional bits: In this case the output should be filled up with the bits from E_reg_sig's fractional part, the rest should be "0"s
There is less space than E_reg_sig's bits widh: In this case the code should be filled up with the Bits from E_reg_sig from MSB to LSB till there are no bits from the output to fill up anymore
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.fixed_pkg.all;
use work.parameters.all;
entity log_mvm is
port (
CLK: IN std_logic;
E_reg: IN: ufixed(counter_log_mvm_WIDTH downto -(DATA_WIDTH_IN-2));
F_reg: OUT: unsigned(DATA_WIDTH_IN-2 downto 0);
);
end log_mvm;
architecture Behavioral of log_mvm is
begin
process(clk)
variable insert_position : NATURAL;
if rising_edge(CLK) then
insert_position:= to_integer(E_reg(E_reg'high downto 0));
if insert_position > F_reg'high then
F_reg<= (others=>'1');
else
F_reg(insert_position)<='1';
if insert_position>-1 then
If insert_position>=(-E_reg'low) then
F_reg(insert_position-1 downto insert_position+E_reg'low)<=unsigned(E_reg(-1 downto E_reg'low));
else
F_reg(insert_position-1 downto 0)<=unsigned(E_reg(-1 downto -insert_position));
END if;
END IF;
end if;
END IF;
END IF;
end process;
end Behavioral;
DATA_WIDTH_IN is defined as natural with the value 8
This codes works in simulation fine, but for synthezise, there is the error "[Synth 8-7138] Expecting constant slice on LHS" on part F_reg(insert_position-1 downto 0)<=unsigned(E_reg(-1 downto -insert_position));
How to avoid this
I am using VHDL 2008 with Vivad0 2021
You have to work with a loop:
for i in F_reg'range loop
if i<=insert_position-1 then
F_reg(i) <= E_reg(i-insert_position);
end if;
end loop;

signal statement must use <= to assign value to signal

I've got this error in the expression "individuos(x):=cout" of the following code. What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos", the same will happen if i trie to build a sequential statement with the assert function. How do I fix this?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
use ieee.numeric_std.all;
--package genetica_type is
--type genetica is array(0 to 49) of unsigned(7 downto 0);
--type fitness is array(0 to 49) of unsigned (2 downto 0);
--end package genetica_type;
use work.genetica_type.all;
entity conexao is
Port (
clk : in bit;
cout: in unsigned (7 downto 0);
individuos: out genetica
);
end entity;
architecture Behavioral of conexao is
--type genetica is array (0 to 49) of std_logic_vector (7 downto 0);
--signal s_individuos : genetica;
--signal i: genetica;
begin
process (clk)
begin
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) := cout;
end loop;
end if ;
end process;
end Behavioral;
I've got this error in the expression "individuos(x):=cout" of the following code.
That is a syntax error. Use <= exactly as the compiler says.
What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos"
That is exactly what you ask it to do :
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) <= cout;
end loop;
end if ;
On every rising clock edge, loop 50x performing 50 assignments, each of the same data, to all 50 addresses.
What I think you want to do, is, on every clock, perform ONE assignment, and increment the address to point to the next location.
signal x : natural range 0 to individuos'high;
...
if rising_edge(clk) then
individuos(x) <= cout;
x <= x + 1 mod individuos'length;
end if;
This code has several other differences from yours:
It uses the simpler rising_edge(clk) function
It will still work when you change the size of the input array.
It still has a bug : if you change the array lower bound to something other than 0, it will fail... for example:
type genetica is array(3 to 49) of ...
Easy to catch this with an assert:
Assert individuos'low = 0 report "Array Individuos bound error" severity failure;
It also runs continuously. If you want to start and stop it, or reset the address counter, or stop when it reaches 50, that takes additional logic.

How to assign bits from a changing STD_LOGIC output to a STD_LOGIC_VECTOR input

I'm new to this web site and I had a question I was hoping to get help with. I am writing VHDL code for a LFSR which consists of a transmitter and receiver.
The transmitter is supposed to generate a random binary number (preamble,which it does) and this binary number then has to be concatenated, but I first need to put it in a STD_LOGIC_VECTOR and that's what im having trouble with.
Here is my code for testbench in which this assignment must take place,thank for any help in advance:
library ieee;
use ieee.std_logic_1164.all;
entity testbench is --definig the entity
end testbench;
architecture tb1 of testbench is
component transmitter is port(
clk :in std_logic;
reset:in std_logic;
enable:in std_logic;
output :out std_logic);--output is the random generated binary which i need to pass to a vector
end component;
--type bit_vector is array (natural range <>) of bit; --this is so that we can define the whole thing otherwise bit can
--only be 1 or 0 this allows to define them as vectors
constant SOF: std_logic_vector(0 to 15) := "0101010100001010";
constant trailer: std_logic_vector(0 to 7) := "10111110";
constant payload: std_logic_vector(0 to 7) := "01110010";
constant L: std_logic_vector(0 to 7) := "00101110";
signal preamble: std_logic_vector(0 to 95);
signal clk , reset, enable : std_logic;--output signal
signal data_packet: std_logic_vector(0 to 135);
signal output: std_logic;
begin
--problem is here
--my attempt
get_preamble: process
variable i: std_logic;--this will be used to walk through the preamble vector and put the out put values in
--variable j: std_logic;
begin
n1: for i in 0 to 95 loop
if output = '1' then
preamble(i) <= '1';
end if;
end loop;
if output = '0' then
for i in 0 to 95 loop
preamble(i) <= '0';
end loop;
end if;
wait;
end process;--end of get_preamble
concatenation :process
begin
data_packet <= preamble & SOF & L & payload & trailer;
wait;
end process;
END tb1;
Based on your question, you're saying you're trying to concatenate the value output with the rest of the preamble vector. You should change this:
n1: for i in 0 to 95 loop
if output = '1' then
preamble(i) <= '1';
end if;
end loop;
if output = '0' then
for i in 0 to 95 loop
preamble(i) <= '0';
end loop;
end if;
to this:
n1: for i in 0 to 95 loop
wait until clk'EVENT and clk = '1';
preamble(i) <= output
end loop;
Since you have a clock, try to get each value when you have a positive edge in your clock. You do not need to check the value each time, you can just add it to the vector at once.
EDIT: You should either wait for the same things in the other process, or wait for the preamble to finish loading its 96 values, depending on what you want to accomplish.
Are you perhaps looking for something like this?
It will take a stream of 96 bits from "output" and put them in "preamble". Then concatenate preamble to the packet.
for i in 0 to 95 loop
wait until rising_edge(clk);
preamble(i) <= output;
end loop;
data_packet <= preamble & SOF & L & payload & trailer;

vhdl asynchronous assignment in for loop

I am doing something like this:
x : in STD_LOGIC_VECTOR(15 downto 0);
signal x_d: std_logic_vector(15 downto 0);
type inp_concat_array is array (0 to 15) of std_logic_vector(1 downto 0);
signal inp_concat : inp_concat_array;
process (clk, reset)
begin
if (rising_edge(clk)) then
if (reset = '1') then
for i in 0 to 15 loop
x_d(i) <= '0';
end loop;
else
for i in 0 to 15 loop
x_d(i) <= x(i);
end loop;
end if;
end if;
end process;
for j in 0 to 15 loop
inp_concat(j) <= x(j) & x_d(j);
end loop;
Xilinx ISE 14.2 gives following errors
Syntax error near "for"
Syntax error near "loop"
Can i use asynchronous assignments in FOR loop?
The concurrent for loop must be made with a generate statement like:
inp_concat_loop : for j in 0 to 15 generate
inp_concat(j) <= x(j) & x_d(j);
end generate;
or in a process as described in David Koontzs answer.
Without seeing an entire design description answering your question could be a bit risky. You present us with a code fragment and no line numbers for the syntax error. The code fragment contains three for loops.
Now if this fragment represents a continuous segment extracted from a design unit (an architecture) it would appear that you are trying to use a loop statement (the for loop, a sequential statement appropriate for a process or subprogram) in a place appropriate for a concurrent statement (the architecture body).
Providing missing bits for something that might analyze:
library ieee;
use ieee.std_logic_1164.all;
entity asyn is
port (
x : in STD_LOGIC_VECTOR(15 downto 0);
clk: in std_logic;
reset: in std_logic
);
end entity;
architecture foo of asyn is
signal x_d: std_logic_vector(15 downto 0);
type inp_concat_array is array (0 to 15) of std_logic_vector(1 downto 0);
signal inp_concat : inp_concat_array;
begin
process (clk, reset)
begin
if (rising_edge(clk)) then
if (reset = '1') then
for i in 0 to 15 loop
x_d(i) <= '0';
end loop;
else
for i in 0 to 15 loop
x_d(i) <= x(i);
end loop;
end if;
end if;
end process;
for j in 0 to 15 loop
inp_concat(j) <= x(j) & x_d(j);
end loop;
end architecture;
And using a different tool yields:
ghdl -a async.vhdl
async.vhdl:32:5: a generate statement must have a label
async.vhdl:32:22: 'generate' is expected instead of 'loop'
In a place appropriate for a concurrent statement in an architecture body the only statement that can have a for keyword is a generate statement, which requires a label.
There is no requirement in VHDL to look ahead to disambiguate syntax errors (which is why you have a vague error message).
A different tool provides a bit better illustration:
nvc -a async.vhdl
** Error: syntax error, unexpected for, expecting process
File async.vhdl, Line 32
for j in 0 to 15 loop
^^^
So if you put the for loop in a process instead it just might analyze:
NEW_PROCESS:
process (x,x_d)
begin
for j in 0 to 15 loop
inp_concat(j) <= x(j) & x_d(j);
end loop;
end process;
Below is a suggestion for a simpler, neater solution. Simulation results follow.
-----------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
-----------------------------------------------
entity test is
port (
clk, reset: in std_logic;
x: in std_logic_vector(15 downto 0);
--test signals:
test: out std_logic_vector(1 downto 0);
test_index: in natural range 0 to 15);
end entity;
-----------------------------------------------
architecture test of test is
signal x_d: std_logic_vector(15 downto 0);
type inp_concat_array is array (0 to 15) of
std_logic_vector(1 downto 0);
signal inp_concat: inp_concat_array;
begin
process (clk, reset)
begin
if rising_edge(clk) then
if reset = '1' then
x_d <= (others => '0');
else
x_d <= x;
end if;
end if;
end process;
gen: for i in 0 to 15 generate
inp_concat(i) <= x(i) & x_d(i);
end generate;
test <= inp_concat(test_index);
end architecture;
-----------------------------------------------
The problem is that your asynchronous for loop is not inside a process, and needs to be: This should do it
process(x,x_d)
begin
for j in 0 to 15 loop
inp_process(j) <= x(j) & x_d(j);
end loop;
end process;

vhdl "parse error, unexpected FOR"

I try to write programm on vhdl in ise 14.4 for crc16 calculation but dont understand why get "parse error, unexpected FOR" in it. Tried to put it into process but it dont works too.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity crc16 is port(
clk : in STD_LOGIC:='0');
end crc16;
architecture Behavioral of crc16 is
signal data:std_logic_vector(15 downto 0):="1010101010101010";
signal ext_data:std_logic_vector(31 downto 0);
signal crc16_original:std_logic_vector(15 downto 0):="1100000000000010";
signal crc16:std_logic_vector(15 downto 0);
signal position:std_logic_vector(5 downto 0);
signal crc_out:std_logic_vector(14 downto 0);
signal i:std_logic_vector(5 downto 0);
begin
for i in 1 to 15 loop
ext_data(i+16)<=data(i);
end loop;
for i in 1 to 15 loop
ext_data(i)<='0';
end loop;
while ext_data > "111111111111111" loop
for i in 0 to 31 loop
if ext_data(i)="1" position=i;
end loop;
crc16<= crc16_original srl 31-position;
ext_data<=ext_data xor crc16;
end loop;
for i in 0 to 14 loop
crc_out(i)<=ext_data(i);
end loop;
end Behavioral;
There are several issues to point out:
The for-loop must be in a process, so that is likely to cause the “parse error, unexpected FOR” that you see.
The relation compare with > may give unexpected result for std_logic_vector, so you may take a look at the numeric_std package for casting as for example unsigned(std_logic_vector) before comparison is made.
Compare ext_data(i) = "1" is illegal, since "1" is taken as std_logic_vector, where as ext_data(i) is std_logic; instead ext_data(i) = '1' will compile.
Illegal construction around if ext_data(i) = "1" position=i;, since no then etc.
There is an signal with identifier i, which i is also used as loop variable, with the result that position <= i is taken as an integer assign to std_logic_vector; use different names for signals and loop variables.
Assign to signal is not position = i but position <= i, like elsewhere.
Expression 31-position mixes integer and std_logic_vector, which can't be done with the selected packages. Use casting with unsigned.
The ext_data<=ext_data xor crc16 uses different size arguments, since ext_data is 32 bits and crc16 is 16 bits; this does probably not yield the expected result.
srl is not defined for std_logic_vector (VHDL-2002), so consider casting with unsigned for well-defined behavior.
Assuming that that your code is "sandbox" code, since it has no outputs.
Based on the above, you may consider doing some initial experiments with smaller designs, in order to get familiar with the different VHDL constructions, and learn how this simulates and maps to hardware; remember VHDL is a "Hardware Description Language" and not a programming language.
Below is some code that compiles in ModelSim, but is unlikely to give the expected result:
library ieee;
use ieee.std_logic_1164.all;
entity crc16 is port(
clk : in std_logic := '0');
end crc16;
library ieee;
use ieee.numeric_std.all;
architecture Behavioral of crc16 is
signal data : std_logic_vector(15 downto 0) := "1010101010101010";
signal ext_data : std_logic_vector(31 downto 0);
signal crc16_original : std_logic_vector(15 downto 0) := "1100000000000010";
signal crc16 : std_logic_vector(15 downto 0);
signal position : std_logic_vector(5 downto 0);
signal crc_out : std_logic_vector(14 downto 0);
signal i_sig : std_logic_vector(5 downto 0);
begin
process (clk) is
begin
if rising_edge(clk) then
for i in 1 to 15 loop
ext_data(i+16) <= data(i);
end loop;
for i in 1 to 15 loop
ext_data(i) <= '0';
end loop;
while ext_data > "111111111111111" loop
for i in 0 to 31 loop
if ext_data(i) = '1' then
position <= i_sig; -- TBD[Probably not right code, but compiles]
end if;
end loop;
crc16 <= std_logic_vector(unsigned(crc16_original) srl (31 - to_integer(unsigned(position))));
ext_data <= ext_data xor crc16;
end loop;
for i in 0 to 14 loop
crc_out(i) <= ext_data(i);
end loop;
end if;
end process;
end Behavioral;

Resources