std_logic_vector (to_unsigned(X, Y)); - vhdl

This is a test-bench, and I have these signals:
signal DATA_INPUT :std_logic_vector(0 to 31);
signal rand_num :integer;
I am trying to put random numbers into this 32bit signal by this:
DATA_INPUT <= std_logic_vector(to_unsigned(rand_num, 32));
My question is, I need numbers more than 31bits but when the random numbers goes above this number: 2147483647 which is INTEGER'high, I am getting this error:
near "4294967295": (vcom-119) Integer value exceeds INTEGER'high.
# ** Error: tb.vhd: (vcom-1144) Value -1 (of type
std.STANDARD.NATURAL) is out of range 0 to 2147483647.
I tried to modify the TO_UNSIGNED() function and change the NATURAL input to something else but nothing.
Here is the TO_UNSIGNED function from IEEE and RANDOOM GENERATOR process:
function TO_UNSIGNED(ARG, SIZE: NATURAL) return UNSIGNED is
variable RESULT: UNSIGNED (SIZE-1 downto 0);
variable i_val: NATURAl := ARG;
begin
if (SIZE < 1) then return NAU; end if;
for i in 0 to RESULT'left loop
if (i_val MOD 2) = 0 then
RESULT(i) := '0';
else RESULT(i) := '1';
end if;
i_val := i_val/2;
end loop;
if not(i_val=0) then
assert NO_WARNING
report "numeric_std.TO_UNSIGNED : vector truncated"
severity WARNING;
end if;
return RESULT;
end TO_UNSIGNED;
Random generator:
process
variable seed1, seed2 :positive;
variable rand :real;
variable range_of_rand :real:= 46340.0;
begin
uniform(seed1, seed2, rand);
rand_num <= integer(rand*range_of_rand);
wait for 1 ns;
end process;

You can make a new,bigger random number by combining two.
The simplest solution is to convert two random integers to vectors and then concatenate until you get the number of bits you need. This gives you 64 bits:
DATA_INPUT <= std_logic_vector(to_unsigned(rand_num, 32)) & std_logic_vector(to_unsigned(rand_num, 32));

Related

Easy Count-Down Counters Integer vs Unsigned

Rather than having to build counters as follows -
signal my_counter : unsigned(3 downto 0) := to_unsigned(9, 4);
signal reset_value : unsigned(3 downto 0) := to_unsigned(9, 4);
--...
--...
process(clk)
begin
if rising_edge(clk) then
counter <= counter - 1;
if counter = 0 then
counter <= reset_value;
-- raise flag telling other logic to do stuff
end if;
end if;
end process;
Could you do this with an integer count down with a range? and therefore you wouldn't need to have the reset_value? Could this look something like...
signal my_counter_int : integer range 0 to 9 := 9;
--...
--...
process(clk)
begin
if rising_edge(clk) then
counter <= counter - 1;
if counter = 0 then
-- raise flag telling other logic to do stuff
end if;
end if;
end process;
I'm just seeing whether you can have an implied roll over to 9 with an integer with a set range.
Create your own subtype from integer with the proper range (0–9) and define the counter variable to be of that type:
subtype MY_COUNTER_TYPE is integer range 0 to 9;
signal counter : MY_COUNTER_TYPE := 9;
Declare a "rolling decrement" function for your own subtype, which folds the value back to the highest possible value in the range if the decrement would decrease the value under the range:
function r_decrement(val : MY_COUNTER_TYPE) return MY_COUNTER_TYPE is
begin
if val = MY_COUNTER_TYPE'LOW then
return MY_COUNTER_TYPE'HIGH;
else
return val - 1;
end if;
end function;
Now you can use the rolling decrement function of the type without worrying about the resetting the counter manually or checking if the decrement would result in the signal being out of the allowed range:
if rising_edge(clk) then
counter <= r_decrement(counter); -- "rolling" decrement
if counter = 0;
-- raise flag telling other logic to do stuff
end if;
end if;
So yes, it is possible. And if you're using a lot of counters like this in your design, you may avoid writing a lot of redundant code when checking the counter limits and resetting the value back to reset_value manually.

Vivado synthesis: complex assignment not supported

I implemented a Booth modified multiplier in vhdl. I need to make a synthesis with Vivado but it's not possible because of this error:
"complex assignment not supported".
This is the shifter code that causes the error:
entity shift_register is
generic (
N : integer := 6;
M : integer := 6
);
port (
en_s : in std_logic;
cod_result : in std_logic_vector (N+M-1 downto 0);
position : in integer;
shift_result : out std_logic_vector(N+M-1 downto 0)
);
end shift_register;
architecture shift_arch of shift_register is
begin
process(en_s)
variable shift_aux : std_logic_vector(N+M-1 downto 0);
variable i : integer := 0; --solo per comoditÃ
begin
if(en_s'event and en_s ='1') then
i := position;
shift_aux := (others => '0');
shift_aux(N+M-1 downto i) := cod_result(N+M-1-i downto 0); --ERROR!!
shift_result <= shift_aux ;
end if;
end process;
end shift_arch;
the booth multiplier works with any operator dimension. So I can not change this generic code with a specific one.
Please help me! Thanks a lot
There's a way to make your index addressing static for synthesis.
First, based on the loop we can tell position must have a value within the range of shift_aux, otherwise you'd end up with null slices (IEEE Std 1076-2008 8.5 Slice names).
That can be shown in the entity declaration:
library ieee;
use ieee.std_logic_1164.all;
entity shift_register is
generic (
N: integer := 6;
M: integer := 6
);
port (
en_s: in std_logic;
cod_result: in std_logic_vector (N + M - 1 downto 0);
position: in integer range 0 to N + M - 1 ; -- range ADDED
shift_result: out std_logic_vector(N + M - 1 downto 0)
);
end entity shift_register;
What's changed is the addition of a range constraint to the port declaration of position. The idea is to support simulation where the default value of can be integer is integer'left. Simulating your shift_register would fail on the rising edge of en_s if position (the actual driver) did not provide an initial value in the index range of shift_aux.
From a synthesis perspective an unbounded integer requires you take both positive and negative integer values in to account. Your for loop is only using positive integer values.
The same can be done in the declaration of the variable i in the process:
variable i: integer range 0 to N + M - 1 := 0; -- range ADDED
To address the immediate synthesis problem we look at the for loop.
Xilinx support issue AR# 52302 tells us the issue is using dynamic values for indexes.
The solution is to modify what the for loop does:
architecture shift_loop of shift_register is
begin
process (en_s)
variable shift_aux: std_logic_vector(N + M - 1 downto 0);
-- variable i: integer range 0 to N + M - 1 := 0; -- range ADDED
begin
if en_s'event and en_s = '1' then
-- i := position;
shift_aux := (others => '0');
for i in 0 to N + M - 1 loop
-- shift_aux(N + M - 1 downto i) := cod_result(N + M - 1 - i downto 0);
if i = position then
shift_aux(N + M - 1 downto i)
:= cod_result(N + M - 1 - i downto 0);
end if;
end loop;
shift_result <= shift_aux;
end if;
end process;
end architecture shift_loop;
If i becomes a static value when the loop is unrolled in synthesis it can be used in calculation of indexes.
Note this gives us an N + M input multiplexer where each input is selected when i = position.
This construct can actually be collapsed into a barrel shifter by optimization, although you might expect the number of variables involved for large values of N and M might take a prohibitive synthesis effort or simply fail.
When synthesis is successful you'll collapse each output element in the assignment into a separate multiplexer that will match Patrick's
barrel shifter.
For sufficiently large values of N and M we can defined the depth in number of multiplexer layers in the barrel shifter based on the number of bits in a binary expression of the integer range of distance.
That either requires a declared integer type or subtype for position or finding the log2 value of N + M. We can use the log2 value because it would only be used statically. (XST supports log2(x) where x is a Real for determining static values, the function is found in IEEE package math_real). This gives us the binary length of position. (How many bits are required to to describe the shift distance, the number of levels of multiplexers).
architecture barrel_shifter of shift_register is
begin
process (en_s)
use ieee.math_real.all; -- log2 [real return real]
use ieee.numeric_std.all; -- to_unsigned, unsigned
constant DISTLEN: natural := integer(log2(real(N + M))); -- binary lengh
type muxv is array (0 to DISTLEN - 1) of
unsigned (N + M - 1 downto 0);
variable shft_aux: muxv;
variable distance: unsigned (DISTLEN - 1 downto 0);
begin
if en_s'event and en_s = '1' then
distance := to_unsigned(position, DISTLEN); -- position in binary
shft_aux := (others => (others =>'0'));
for i in 0 to DISTLEN - 1 loop
if i = 0 then
if distance(i) = '1' then
shft_aux(i) := SHIFT_LEFT(unsigned(cod_result), 2 ** i);
else
shft_aux(i) := unsigned(cod_result);
end if;
else
if distance(i) = '1' then
shft_aux(i) := SHIFT_LEFT(shft_aux(i - 1), 2 ** i);
else
shft_aux(i) := shft_aux(i - 1);
end if;
end if;
end loop;
shift_result <= std_logic_vector(shft_aux(DISTLEN - 1));
end if;
end process;
end architecture barrel_shifter;
XST also supports ** if the left operand is 2 and the value of i is treated as a constant in the sequence of statements found in a loop statement.
This could be implemented with signals instead of variables or structurally in a generate statement instead of a loop statement inside a process, or even as a subprogram.
The basic idea here with these two architectures derived from yours is to produce something synthesis eligible.
The advantage of the second architecture over the first is in reduction in the amount of synthesis effort during optimization for larger values of N + M.
Neither of these architectures have been verified lacking a testbench in the original. They both analyze and elaborate.
Writing a simple case testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity shift_register_tb is
end entity;
architecture foo of shift_register_tb is
constant N: integer := 6;
constant M: integer := 6;
signal clk: std_logic := '0';
signal din: std_logic_vector (N + M - 1 downto 0)
:= (0 => '1', others => '0');
signal dout: std_logic_vector (N + M - 1 downto 0);
signal dist: integer := 0;
begin
DUT:
entity work.shift_register
generic map (
N => N,
M => M
)
port map (
en_s => clk,
cod_result => din,
position => dist,
shift_result => dout
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > (N + M + 2) * 20 ns then
wait;
end if;
end process;
STIMULI:
process
begin
for i in 1 to N + M loop
wait for 20 ns;
dist <= i;
din <= std_logic_vector(SHIFT_LEFT(unsigned(din),1));
end loop;
wait;
end process;
end architecture;
And simulating reveals that the range of position and the number of loop iterations only needs to cover the number of bits in the multiplier and not the multiplicand. We don't need a full barrel shifter.
That can be easily fixed in both shift_register architectures and has the side effect of making the shift_loop architecture much more attractive, it would be easier to synthesize based on the multiplier bit length (presumably M) and not the product bit length (N+ M).
And that would give you:
library ieee;
use ieee.std_logic_1164.all;
entity shift_register is
generic (
N: integer := 6;
M: integer := 6
);
port (
en_s: in std_logic;
cod_result: in std_logic_vector (N + M - 1 downto 0);
position: in integer range 0 to M - 1 ; -- range ADDED
shift_result: out std_logic_vector(N + M - 1 downto 0)
);
end entity shift_register;
architecture shift_loop of shift_register is
begin
process (en_s)
variable shift_aux: std_logic_vector(N + M - 1 downto 0);
-- variable i: integer range 0 to M - 1 := 0; -- range ADDED
begin
if en_s'event and en_s = '1' then
-- i := position;
shift_aux := (others => '0');
for i in 0 to M - 1 loop
-- shift_aux(N + M - 1 downto i) := cod_result(N + M - 1 - i downto 0);
if i = position then -- This creates an N + M - 1 input MUX
shift_aux(N + M - 1 downto i)
:= cod_result(N + M - 1 - i downto 0);
end if;
end loop; -- The loop is unrolled in synthesis, i is CONSTANT
shift_result <= shift_aux;
end if;
end process;
end architecture shift_loop;
Modifying the testbench:
STIMULI:
process
begin
for i in 1 to M loop -- WAS N + M loop
wait for 20 ns;
dist <= i;
din <= std_logic_vector(SHIFT_LEFT(unsigned(din),1));
end loop;
wait;
end process;
gives a result showing the shifts are over the range of the multiplier value (specified by M):
So the moral here is you don't need a full barrel shifter, only one that works over the multiplier range and not the product range.
The last bit of code should be synthesis eligible.
You are trying to create a range using a run-time varying value, and this is not supported by the synthesis tool. cod_result(N+M-1 downto 0); would be supported, because N, M, and 1 are all known at synthesis time.
If you're trying to implement a multiplier, you will get the best result using x <= a * b, and letting the synthesis tool choose the best way to implement it. If you have operands wider than the multiplier widths in your device, then you need to look at the documentation to determine the best route, which will normally involve pipelining of some sort.
If you need a run-time variable shift, look for a 'Barrel Shifter'. There are existing answers on these, for example this one.

How can i fill and display a matrix ? [VHDL]

I have a datain as an std_logic_vector and i want fill a matrix with datain's bits and then display it.
How can i fill and display the matrix ?
Here is my code:
signal datain : std_logic_vector(39 downto 0) := "1111011101100110011001010110011001100110";
for i1 in 1 to 5 loop
for j1 in 1 to 8 loop
for j2 in datain'range loop
mat1(i1,j1)<=datain(j2);
end loop;
end loop;
end loop;
------- display the matrix
for i2 in 1 to 5 loop
for i3 in 1 to 8 loop
for i4 in dataout'range loop
dataout(i4) <= mat1(i2,i3);
end loop;
end loop;
end loop;
Thank you,
First we construct a Minimal, Complete and Verifiable example from your code snippets:
library ieee;
use ieee.std_logic_1164.all;
entity abir is
end entity;
architecture foo of abir is
type mat_type is array (1 to 5, 1 to 8) of std_logic;
signal mat1: mat_type;
signal datain : std_logic_vector(39 downto 0) :=
"1111011101100110011001010110011001100110";
signal dataout: std_logic_vector (39 downto 0); -- MISSING
-- this function is predefined in VHDL -2008:
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
INITIALIZE_MATRIX:
process -- (datain)
begin
for i1 in 1 to 5 loop
for j1 in 1 to 8 loop
for j2 in datain'range loop
mat1(i1,j1)<=datain(j2);
end loop;
end loop;
end loop;
wait; -- Do only once, depends on the initial value of datain
end process; -- the wait statement can be removed if you add sensitivity
------- display the matrix
MATRIX_T0_DATAOUT:
process (mat1)
begin
for i2 in 1 to 5 loop
for i3 in 1 to 8 loop
for i4 in dataout'range loop
dataout(i4) <= mat1(i2,i3);
end loop;
end loop;
end loop;
end process;
DISPLAY_DATAOUT:
process -- (dataout)
begin -- wait statements so only disply valid datout
wait for 0 ns; -- first delta cycle all 'U's (dataout uninitialized)
wait for 0 ns; -- second delta cycle all 'U's (mat1 uninitialized)
report LF &
HT & "datain = " & to_string(datain) & LF &
HT & "dataout = " & to_string(dataout);
wait on dataout;
end process;
end architecture;
The function to_string is predefined in VHDL -2008, this MCVE should work with tools compliant earlier revisions of the VHDL standard.
It's specific to demonstrating your code. It gives:
ghdl -a abir.vhdl
ghdl -e abir
ghdl -r abir
abir.vhdl:58:9:#0ms:(report note):
datain = 1111011101100110011001010110011001100110
dataout = 0000000000000000000000000000000000000000
So there's something wrong with your nested loops (you can also verify this with a waveform viewer to determine mat1 is indeed all '0's).
So the cause of this is the very inner loops. With datain you assign each element of matrix mat1(i,j) N times where N is the length of datain (range of j2). With dataout you assign each indexed element of dataout (i4) every matrix element of mat(i2,i3).
So is it possible to have three loops performing these assignments?
Well, no.
In the INITIALIZE_MATRIX process every (i,j) location of mat1 was overwritten with all the index values of datain. Only the last one took affect. This filled the matrix with all '0's.
In the MATRIX_TO_DATAOUT process all the dataout indexes were 'scheduled' to have the last mat1(i2,i3) value of each i3 loop iteration, settling on the last loop iteration value of i2 and i3, a '0'.
We can modify the two sets of loops to decrement j2 or i4 as variables directly (the ranges of datain and dataout are in in descending order):
INITIALIZE_MATRIX:
process -- (datain)
variable j2: natural range datain'range;
begin
j2 := datain'LEFT; -- so the process can execute again.
for i1 in 1 to 5 loop
for j1 in 1 to 8 loop
-- for j2 in datain'range loop
mat1(i1,j1) <= datain(j2);
if j2 /= datain'RIGHT then
j2 := j2 - 1; -- datain has descending range
end if;
-- end loop;
end loop;
end loop;
wait; -- Do only once, depends on the initial value of datain
end process; -- the wait statement can be removed if you add sensitivity
------- display the matrix
MATRIX_T0_DATAOUT:
process (mat1)
variable i4: natural range dataout'range;
begin
i4 := dataout'LEFT; -- so the process can execute again
for i2 in 1 to 5 loop
for i3 in 1 to 8 loop
-- for i4 in dataout'range loop
dataout(i4) <= mat1(i2,i3);
if i4 /= dataout'RIGHT then
i4 := i4 - 1; -- dataout has descending range
end if;
-- end loop;
end loop;
end loop;
end process;
And that gives us:
abir.vhdl:68:9:#0ms:(report note):
datain = 1111011101100110011001010110011001100110
dataout = 1111011101100110011001010110011001100110
Where we find dataout matches datain. (A good thing.)
So the issue was the three nested loops in each process were incorrect. We wanted to manage the pointers to the input and output arrays separately.
We also manage the assignments to the variables j2 or i4 to prevent a bounds violation using if statements to prevent j2 or i4 being decremented when the variable assignment would be out of the value range of the variable. A bounds check failure on assignment would abort the simulation.
Note that signal assignment results in a value being written to a projected output waveform (a queue). Signal updates don't occur before any pending process has run and suspended. There's only one value for any time in the projected output waveform. (including the current simulation time).
These two modified processes could be used as the basis of conversion functions:
architecture fum of abir is
type mat_type is array (1 to 5, 1 to 8) of std_logic;
signal mat1: mat_type;
signal datain : std_logic_vector(39 downto 0) :=
"1111011101100110011001010110011001100110";
signal dataout: std_logic_vector (39 downto 0); -- MISSING
-- this function is predefined in VHDL -2008:
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
function to_matrix (inp: std_logic_vector) return mat_type is
alias input: std_logic_vector(0 to inp'length - 1) is inp; -- ascending
variable mat: mat_type;
variable inptr: natural range 0 to inp'length;
begin
assert input'length = mat'length(1) * mat'length(2)
report LF &
"to_matrix call, input length (" &
integer'image(inp'length) & ") " &
"/= " & integer'image( mat'length(1) * mat'length(2))
severity FAILURE;
for i in mat'range(1) loop -- first dimension
for j in mat'range(2) loop -- second dimension
mat(i,j) := input(inptr);
inptr := inptr + 1; -- inptr range allows last increment
end loop;
end loop;
return mat;
end function;
function to_std_logic_vector (mat: mat_type) return std_logic_vector is
variable retval:
std_logic_vector(0 to mat'length(1) * mat'length(2) - 1);
variable outptr: natural range 0 to retval'length;
begin
for i in mat'range(1) loop -- first dimension
for j in mat'range(2) loop -- second dimension
retval(outptr) := mat(i,j);
outptr := outptr + 1; -- outptr range allows last increment
end loop;
end loop;
return retval;
end function;
begin
INITIALIZE_MATRIX:
mat1 <= to_matrix(datain);
MATRIX_T0_DATAOUT:
dataout <= to_std_logic_vector(mat1);
DISPLAY_DATAOUT:
process -- (dataout)
begin -- wait statements so only disply valid datout
wait for 0 ns; -- first delta cycle all 'U's (dataout uninitialized)
wait for 0 ns; -- second delta cycle all 'U's (mat1 uninitialized)
report LF &
HT & "datain = " & to_string(datain) & LF &
HT & "dataout = " & to_string(dataout);
wait for 1 ns;
wait on dataout;
end process;
end architecture;
The two functions are dependent only on the matrix type declaration. You can change the mat_type declaration without having to modify declarations or the any of the sequence of statements found in the functions.
The new architecture with the to_matrix[std_logic_vector return mat_type] and to_std_logic_vector[mat_type return std_logic_vector] function calls provides the same answer as the MCVE with the corrected process statements.

How to write an integer to stdout as hexadecimal in VHDL?

I can print an integer as decimal to stdout with:
library std;
use std.textio.all;
entity min is
end min;
architecture behav of min is
begin
process is
variable my_line : line;
begin
write(my_line, 16);
writeline(output, my_line);
wait;
end process;
end behav;
which outputs:
16
But how to output instead either:
10
0x10
Assuming an integer i, and VHDL-2008, you could use:
write(output, integer'image(i) & LF); -- Plain integer value
write(output, "0x" & to_hstring(to_signed(i, 32)) & LF); -- Hexadecimal representation
You need to have use std.textio.all; for this to work. Change the 32 to reduce the length of the hex value. I chose 32 so that it can represent any integer value in most simulators.
These will also work for report statements, e.g.
report "i = 0x" & to_hstring(to_signed(i, 32));
There is no standard library implementation, but for example our PoC-Libary has several formatting function in the PoC.Strings package. On top of that, we have a to_string(...) function, which accepts a format character like h for hexadecimal outputs.
How to write such an integer to hex conversion?
Convert the INTEGER into a binary representation
Group the binary value into 4-bit groups
translate each group into an integer/alpha in range 0..F
prepend 0x if wished
So here is a wrapper to convert the integer to a binary representation:
-- format a natural as HEX string
function raw_format_nat_hex(Value : NATURAL) return STRING is
begin
return raw_format_slv_hex(std_logic_vector(to_unsigned(Value, log2ceil(Value+1))));
end function;
And now the grouping and transformation
-- format a std_logic_vector as HEX string
function raw_format_slv_hex(slv : STD_LOGIC_VECTOR) return STRING is
variable Value : STD_LOGIC_VECTOR(4*div_ceil(slv'length, 4) - 1 downto 0);
variable Digit : STD_LOGIC_VECTOR(3 downto 0);
variable Result : STRING(1 to div_ceil(slv'length, 4));
variable j : NATURAL;
begin
Value := resize(slv, Value'length);
j := 0;
for i in Result'reverse_range loop
Digit := Value((j * 4) + 3 downto (j * 4));
Result(i) := to_HexChar(unsigned(Digit));
j := j + 1;
end loop;
return Result;
end function;
-- convert an unsigned value(4 bit) to a HEX digit (0-F)
function to_HexChar(Value : UNSIGNED) return CHARACTER is
constant HEX : STRING := "0123456789ABCDEF";
begin
if (Value < 16) then
return HEX(to_integer(Value)+1);
else
return 'X';
end if;
end function;
-- return TRUE, if input is a power of 2
function div_ceil(a : NATURAL; b : POSITIVE) return NATURAL is -- calculates: ceil(a / b)
begin
return (a + (b - 1)) / b;
end function;
-- return log2; always rounded up
function log2ceil(arg : positive) return natural is
variable tmp : positive;
variable log : natural;
begin
if arg = 1 then return 0; end if;
tmp := 1;
log := 0;
while arg > tmp loop
tmp := tmp * 2;
log := log + 1;
end loop;
return log;
end function;
Note: These functions do not prepend 0x.
You could use the hwrite procedure in the IEEE.std_logic_textio package:
library IEEE; -- ADDED
use IEEE.std_logic_1164.all; -- ADDED
use IEEE.numeric_std.all; -- ADDED
use IEEE.std_logic_textio.all; -- ADDED
library std;
use std.textio.all;
entity min is
end min;
architecture behav of min is
begin
process is
variable my_line : line;
begin
hwrite(my_line, std_logic_vector(to_unsigned(16,8))); -- CHANGED
writeline(output, my_line);
wait;
end process;
end behav;
The hwrite procedure writes a std_logic_vector to a file. So, you do have to convert your integer into a std_logic_vector, however (which also needs you to specify a number of bits in the to_unsigned function).
http://www.edaplayground.com/x/exs

Extend bit pattern to generic vector size in VHDL

constant alternate_bits : std_logic_vector(C_BIT_SIZE-1 downto 0) := X;
What do I write in place of X to set it to an alternating pattern of bits, while keeping it generic and without getting upset if C_BIT_SIZE isn't even?
For example, if C_BIT_SIZE = 4 it should produce "1010" and if C_BIT_SIZE = 5 it should produce "01010". (And it should work for any value of C_BIT_SIZE >= 1.)
A function can be used:
-- Returns std_logic_vector(BIT_SIZE-1 downto 0) with bits on even indexes
-- as '0' and bits on odd indexes as '1', e.g. 5 bit vector as "01010".
function alternate_fun(BIT_SIZE : natural) return std_logic_vector is
variable res_v : std_logic_vector(BIT_SIZE - 1 downto 0);
begin
res_v := (others => '0');
for i in 1 to BIT_SIZE / 2 loop
res_v(2 * i - 1) := '1';
end loop;
return res_v;
end function;
I wrote a function that seems to do the trick but I'm interested in alternate tidier answers:
subtype data_vector is std_logic_vector(C_BIT_SIZE-1 downto 0);
function make_alternate_bits return data_vector is
variable bits : data_vector;
begin
for i in 0 to C_BIT_SIZE-1 loop
if (i mod 2) = 0 then
bits(i) := '0';
else
bits(i) := '1';
end if;
end loop;
return bits;
end function;
constant alternate_bits : data_vector := make_alternate_bits;

Resources