variable must be constrained error - vhdl

I am getting an error and I don't understand why.
my code :
library ieee;
use ieee.std_logic_1164.all;
use work.Func_Pack.all;
use ieee.std_logic_arith.all;
use IEEE.std_logic_unsigned.ALL;
--use ieee.numeric_std.all;
entity letters_arranger is
port (
clock, reset,start,rdy_to_get_new_letter :in std_logic; -- asuuming clock is 27 M Hz
select_input : in integer;
reg : out std_logic_vector(7 downto 0);
drive_letter : out std_logic
);
end letters_arranger ;
architecture behave of letters_arranger is
type state is (idle, set_str, send_str,endstring);
signal cur_state: state;
--signal str :string :=" "&CR;
signal str :string :=" "&CR;
signal counter :integer;
constant letters_max : integer := 47;
begin
pro:process(clock,reset)
variable data_count : integer range 0 to 10 :=0;
begin
if (reset='1') then
cur_state <= idle;
elsif rising_edge(clock) then
case cur_state is
when idle=>
drive_letter<='0';
if start = '1' then
cur_state <= set_str;
counter<=0;
elsif counter = letters_max then
cur_state <= endstring;
elsif rdy_to_get_new_letter ='1' then
cur_state <= send_str;
end if;
when set_str =>
str <= select_str(select_input);
counter<=1;-- check char pos indx start fr 0 or 1
when send_str =>
cur_state <= idle;
if counter<=str'length then
counter<=counter+1;
end if;
reg<=conv_std_logic_vector(character'pos(str(counter)),8);
drive_letter<='1';
when endstring =>
--need to do something
cur_state <= idle;
when others => null;
end case;
end if;
end process;
end behave;
and my funcpack (only the function select_str is relevant I believe ):
------------------------ Func_Pack.vhd program ------------------------------------
LIBRARY IEEE;
USE ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
PACKAGE Func_Pack IS
------------Type Decalration ---------------
SUBTYPE byte IS std_logic_vector(7 downto 0);
TYPE special_message IS array(0 to 4,0 to 100) OF byte;
--------------------------------------------
FUNCTION Parity_calc ( data : std_logic_vector(7 downto 0) )RETURN std_logic ;
FUNCTION To_7Seg ( data:integer range 0 to 9)RETURN std_logic_vector;
FUNCTION select_str ( indx:integer range 0 to 9) RETURN string;
END Func_Pack;
----------------------------------------------------------------------------------------------------------------------------
PACKAGE BODY Func_Pack IS
--parity_calc--
FUNCTION Parity_calc ( data : std_logic_vector(7 downto 0) )RETURN std_logic IS
VARIABLE temp : std_logic ;
BEGIN
temp := data(0) xor data(1) xor data(2) xor data(3) xor data(4) xor data(5) xor data(6) xor data(7);
return (temp);
end parity_calc;
----------------------------------------------------------------------------- ------------
------------------ To 7eg Convert function ---------------------------------------------
FUNCTION To_7Seg ( data:integer range 0 to 9)RETURN std_logic_vector IS
VARIABLE temp:std_logic_vector (6 downto 0):=(others=>'1');
BEGIN
CASE data IS
WHEN 0 => temp :="1000000"; -- 40h
WHEN 1 => temp :="1111001"; -- 79h
WHEN 2 => temp :="0100100"; -- 24h
WHEN 3 => temp :="0110000"; -- 30h
WHEN 4 => temp :="0011001"; -- 19h
WHEN 5 => temp :="0010010"; -- 12h
WHEN 6 => temp :="0000010"; -- 02h
WHEN 7 => temp :="1111000"; -- 78h
WHEN 8 => temp :="0000000"; -- 00h
WHEN 9 => temp :="0010000"; -- 10h
WHEN OTHERS => NULL;
END CASE;
RETURN (temp);
END To_7Seg;
FUNCTION select_str ( indx:integer range 0 to 9) RETURN string IS
VARIABLE temp:string;
BEGIN
CASE indx IS
WHEN 0 => temp :=" "&CR;
WHEN 1 => temp :="V18 "&CR;
WHEN 2 => temp :="w300 "&CR;
WHEN 3 => temp :="SPlease Choose 1 Branch line Out Of 3 Possible"&CR;
WHEN 4 => temp :="SYou chose Branch Number 1 "&CR;
WHEN 5 => temp :="SYou chose Branch Number 2 "&CR;
WHEN 6 => temp :="SYou chose Branch Number 3 "&CR;
WHEN OTHERS => temp:=" "&CR;
END CASE;
RETURN (temp);
END select_str;
-----------------------------------------------------------------------------------
--"V18"
--"W300"
--
--"SPlease Choose 1 Branch line Out Of 3 Possible" -- 46 .
--"SYou Choosed Branch Number 1"
--"SYou Choosed Branch Number 2"
--"SYou Choosed Branch Number 3" --29
--"SConnecttinngg" -- 14
--"SI Am Sorry I Couldn't Find the Branch , you tried to Reach" --59
--13 -- =D in hex == <cr> . must be sent in the end of each line
--
--type message_preset is record
-- speed: is array(0 to 2) of byte ;
-- volume: is array(0 to 3) of byte;
-- cr : is integer range 0 to 255;
--end record;
--signal message_set : message_preset := (,,);
------------------------------------------------------------------------- ---------
END Func_Pack;
when running the first code as top-level entity i get this error :
VHDL error at letters_arranger.vhd(21) variable must be constrained .
line 21 is this line
signal str :string :=" "&CR;

In VHDL (and globally in hardware description) you need to constrain all of your signals. Otherwise, the synthesizer can't allocate the needed resources.
That's why you should write the range of your string :
signal str :string(1 to 47) :=" "&CR;
(If I didn't fail in counting the spaces)

Currently all signals and variables must be explicitly sized. However, constants do not have this same restriction, so the clever work around is:
constant BL_STR :string :=" "&LF;
signal str :string(1 to BL_STR'length) := BL_STR ;
Note I changed your CR to LF. With VHDL-2008, LF is recognized as a newline for what ever operating system you are running on.

Related

vhdl equivalent for initial block in verilog

I am trying to convert some Verilog code to VHDL. I have difficulties to translate initial block in Verilog to VHDL properly.
As far as I know, the initial block corresponds to the process statement without a sensitivity list but we have to add a "wait" statement before the "end process".I tried it but it did not work. I tried some other methods too (using exit clause, conditional clause ( wait until), "for- generate" without process, etc) but none was successful.
Here is the Verilog code I want to convert, and it works properly
module MyRAM #(parameter DATA_WIDTH=24, parameter ADDR_WIDTH=10)
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, clk,
output reg [(DATA_WIDTH-1):0] q
);
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
initial
begin : INIT
integer i;
for(i = 1; i < ((2**ADDR_WIDTH)-1); i = i+1) begin
if (i == 132) ram[i] = 24'h550000;
else if (i == 133) ram[i] = 24'h005500;
else if (i == 134) ram[i] = 24'h000055;
else ram[i] = 24'h000000;
end
//*/
end
always # (negedge clk)
begin
// Write
if (we)
ram[write_addr] <= data;
q <= ram[read_addr];
end
endmodule
and this is the VHDL code I have written so far:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity MyRAM is
generic
(DATA_WIDTH: integer;
ADDR_WIDTH: integer);
port
(
data :in std_logic_vector ((DATA_WIDTH-1) downto 0);
read_addr :in std_logic_vector((ADDR_WIDTH-1) downto 0);
write_addr :in std_logic_vector(( DATA_WIDTH-1) downto 0);
we :in std_logic;
clk :in std_logic;
q :out std_logic_vector( 23 downto 0)
);
end MyRAM;
architecture behavioral of MyRAM is
constant case1:std_logic_vector(23 downto 0):=
(16=>'1',18=>'1',20=>'1',22=>'1',others=>'0');
constant case2:std_logic_vector(23 downto 0):=
(8=>'1',10=>'1',12=>'1',14=>'1',others=>'0');
constant case3:std_logic_vector(23 downto 0):=
(0=>'1',2=>'1',4=>'1',6=>'1',others=>'0');
type ram is array ( 0 to (2**ADDR_WIDTH-1)) of
std_logic_vector((DATA_WIDTH-1) downto 0);
shared variable origram:ram;
signal s_q: std_logic_vector(23 downto 0);
begin
process
begin
for ii in 1 to (2**ADDR_WIDTH-1) loop
if (ii = 132) then
origram(ii) := case1;
elsif (ii = 133) then
origram(ii) := case2;
elsif (ii = 134) then
origram(ii) := case3;
else
origram(ii) :=(others=>'0');
end if;
end loop;
wait;
end process;
process (clk)
begin
if falling_edge(clk) then
if (we ='1') then
origram(to_integer(unsigned(write_addr))) := data;
s_q <= origram(to_integer(unsigned(read_addr)));
end if;
end if;
end process;
q<=s_q;
end behavioral;
And this is the error message:
Error (10533): VHDL Wait Statement error at MyRAM.vhd(88): Wait Statement must contain condition clause with UNTIL keyword
I do not have much experience in these languages, so I would appreciate any kind of help
The answer is both yes and no. While yes, you can do pretty much what you can do in an initial block in a process, in your situation the answer is you are actually initialising a signal. For this you need to use a function, and set the initial value:
type ram is array ( 0 to (2**ADDR_WIDTH-1)) of std_logic_vector((DATA_WIDTH-1) downto 0);
function init_ram return ram is
variable r : ram;
begin
-- set the contents of the ram
end function init_ram;
shared variable origram:ram := init_ram;
Processes with wait at the end are only for simulation (which would mimic an initial block in verilog used for testbench stimulus)
Note: from VHDL 2002, using a shared variable like this is illegal as it should be a protected type (which is not synthesisable currently). The only reason you might want a shared variable (rather than a signal) to infer a ram is to get write-before-read behaviour in a RAM. It is very annoying most of the Xilinx Inference examples use a shared variable. Switching your code to VHDL2008 will throw the error mentioned above.
A process with a ram variable instead of a shared variable can provide an initial value as well:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity MyRAM is
generic (
DATA_WIDTH: integer;
ADDR_WIDTH: integer
);
port (
data: in std_logic_vector (DATA_WIDTH - 1 downto 0);
read_addr: in std_logic_vector (ADDR_WIDTH - 1 downto 0);
write_addr: in std_logic_vector (DATA_WIDTH - 1 downto 0);
we: in std_logic;
clk: in std_logic;
q: out std_logic_vector (DATA_WIDTH - 1 downto 0)
);
end entity MyRAM;
architecture behavioral of MyRAM is
constant case1: std_logic_vector(23 downto 0) :=
(16 => '1', 18 => '1', 20 => '1', 22 => '1', others => '0');
constant case2: std_logic_vector(23 downto 0) :=
( 8 => '1', 10 => '1', 12 => '1', 14 => '1', others => '0');
constant case3: std_logic_vector(23 downto 0) :=
( 0 => '1', 2 => '1', 4 => '1', 6 => '1', others => '0');
type ram is array ( 0 to 2 ** ADDR_WIDTH - 1) of
std_logic_vector(DATA_WIDTH - 1 downto 0);
begin
MY_RAM:
process (clk)
function init_origram return ram is
variable ramval: ram;
begin
for ii in ram'left to ram'right loop
if ii = 132 then -- note the presumption ram has at least 135 elements
ramval(ii) := case1;
elsif ii = 133 then
ramval(ii) := case2;
elsif ii = 134 then
ramval(ii) := case3;
else
ramval(ii) := (others => '0');
end if;
end loop;
return ramval;
end function;
variable origram: ram := init_origram;
begin
if falling_edge(clk) then
if we = '1' then -- write before read
origram(to_integer(unsigned(write_addr))) := data;
end if;
q <= origram(to_integer(unsigned(read_addr)));
end if;
end process;
end architecture behavioral;
This would be useful in IEEE Std 1076-2000, -2002 and -2008 compliant tool chains where shared variables are required to be protected types as well as earlier standard revisions.
IEEE Std 1076-2008
9.3.3 Aggregates
9.3.3.1 General:
element_association ::=
[ choices => ] expression
choices ::= choice { | choice }
You can also use the separator '|` to provide multiple values for choices:
constant case1: std_logic_vector(23 downto 0) :=
-- (16 => '1', 18 => '1', 20 => '1', 22 => '1', others => '0');
(16 | 18 | 20 | 22 => '1', others => '0');
or even provide a base specifier X bit string for a hexidecimal value here (15.8 Bit string literals).

Implementing a VHDL binary search on a std_logic_vector [vhdl]

I'm attempting to create synthesizable VHDL (function or procedure) for an ASIC (it must be part of the ASIC) that will look for the first '1' in a standard_logic_vector and output which vector position that '1' was in. For example, I have an 8-bit slv of "10001000" (a '1' in position 3 and 7). If I use this slv, the output should be 4 (the output is 1 based).
The actual VHDL will be searching a large slv, up to 512 bits in length. I tried implementing a binary search function but I get synthesis errors that states "Could not synthesize non-constant range values. [CDFG-231] [elaborate]
The non-constant range values are in file '...' on line 61" I indicated in the code below where it complains. I'm not sure how to implement a binary search algorithm without having non-constant range values. How would I modify this code so it's synthesizable?
I have attempted to search for binary search algorithms for HDL for potential code to look at and for my error, but I didn't find anything.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
entity bin_search is
generic (
constant NREGS : positive := 16 -- number of registers
);
port (
clk_i : in std_logic; -- clock
bin_i : in unsigned( NREGS-1 downto 0 ); -- input
en_i : in std_logic; -- input enable
addr_o : out natural range 0 to NREGS -- first binary location
);
end bin_search;
architecture rtl of bin_search is
function f_bin_search( input: unsigned; nob: positive ) return natural is
constant nbits : positive := 2**nob;
variable lower : natural range 0 to 1 := 0;
variable upper : natural range 0 to 1 := 0;
variable idx : natural range 0 to nob := 4;
variable cnt : natural range 0 to nbits := 0;
variable mid : positive range 1 to nbits := nbits/2; --
variable ll : natural range 0 to nbits := 0;
variable ul : positive range 1 to nbits := nbits; --
begin
if input = 0 then
cnt := 0;
return cnt;
else
loop1: while ( idx > 0 ) loop
if ( input( mid-1 downto ll ) > 0 ) then -- <===WHERE SYNTH COMPLAINS
lower := 1;
else
lower := 0;
end if;
if ( input( ul-1 downto mid ) > 0 ) then
upper := 1;
else
upper := 0;
end if;
if ( idx = 1 ) then
if ( lower = 1 ) then
cnt := mid;
else
cnt := ul;
end if;
elsif ( lower = 1 ) then
ul := mid;
mid := ( ( ll+ul )/2 );
elsif ( upper = 1 ) then
ll := mid;
mid := ( ll+ul )/2;
else
cnt := 0;
exit loop1;
end if;
idx := idx-1;
end loop loop1;
return cnt;
end if;
end f_bin_search;
begin
test_proc: process ( clk_i )
begin
if rising_edge( clk_i ) then
if en_i = '1' then
addr_o <= f_bin_search( bin_i, 4 );
end if;
end if;
end process test_proc;
end rtl;
Here's a simple test bench where the input is inc'd by '1'. The addr_o should be the location (1 based) of the input lsb with a '1'.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
entity bin_search_tb is
end bin_search_tb;
architecture behavior of bin_search_tb is
constant NREGS : positive := 16;
signal clk : std_logic;
signal input : unsigned( NREGS-1 downto 0 );
signal start : std_logic;
signal addr : natural range 0 to NREGS;
constant clk_per : time := 1 ns;
signal row : natural range 0 to 2**NREGS-1;
begin
bin_search_inst: entity work.bin_search( rtl )
generic map (
NREGS => NREGS
)
port map (
clk_i => clk, -- master clock
bin_i => input, -- captured events
en_i => start, -- start binary search
addr_o => addr -- addr where the first '1' appears
);
-- master clock process
clk_proc: process
begin
clk <= '0';
wait for clk_per / 2;
clk <= '1';
wait for clk_per / 2;
end process clk_proc;
--
stim1_proc: process
begin
input <= ( others => '0' );
start <= '0';
row <= 1;
wait until clk'event and clk = '1';
loop
wait until clk'event and clk = '1';
input <= to_unsigned( row, input'length );
start <= '1';
wait until clk'event and clk = '1';
start <= '0';
wait for 4*clk_per;
row <= row+1;
end loop;
end process stim1_proc;
end architecture behavior;
Thanks for your assistance!
-Jason
Edited code and added a testbench
Your design will most certainly depend on latency and other performance requirements, but, you could use some combination of or-reduction, sequencers (for mux selection of sliced vectors), shift register, and counters. I drew up a simple circuit that should find your lsb instance of "1" in ~30 clock cycles
The RTL translation that implements this design should be straight forward.
You say that you are thinking in hardware, but in fact you're not. Or you are misleading yourself.
input( mid-1 downto ll ) > 0
is not an OR-reduction, but a comparison operation. You must know > is the larger than comparison operator. The synthesis will therefor infer a comparator. But how many inputs must that comparator have, I ask? Well, there's your problem: it depends on the value of mid, which:
initially depends on the value of nbits, which depends on the value of nob which is a variable input for the function.
is changed within the loop. Thus it's value is not constant.
A hardware component cannot have a variable amount of wires.
But why do you want binary search? Why not keep-it-simple?
library ieee;
use ieee.std_logic_1164.all;
entity detect_one is
generic(
input_size : positive := 512);
port(
input : in std_logic_vector (input_size-1 downto 0);
output : out natural range 0 to input_size);
end entity;
architecture rtl of detect_one is
begin
main: process(input)
begin
output <= 0;
for i in input_size-1 downto 0 loop
if input(i)='1' then
output <= i+1;
end if;
end loop;
end process;
end architecture;
entity detect_one_tb is end entity;
library ieee;
architecture behavior of detect_one_tb is
constant input_size : positive := 512;
use ieee.std_logic_1164.all;
signal input : std_logic_vector (input_size-1 downto 0) := (others => '0');
signal output : integer;
begin
DUT : entity work.detect_one
generic map ( input_size => input_size )
port map(
input => input,
output => output);
test: process begin
wait for 1 ns;
assert (output = 0) report "initial test failure" severity warning;
for i in 0 to input_size-1 loop
input <= (others => '0');
input(i) <= '1';
wait for 1 ns;
assert (output = i+1) report "single ones test failure" severity warning;
end loop;
input <= (others => '1');
wait for 1 ns;
assert (output = 1) report "initial multiple ones test failure" severity warning;
for i in 0 to input_size-2 loop
input(i) <= '0';
wait for 1 ns;
assert (output = i+2) report "multiple ones test failure" severity warning;
end loop;
wait;
end process;
end architecture;

Why won't VHDL left shifter work?

I'm new to VHDL and I'm trying to write a left shifter that takes in a 32 bit value and a 5 bit value. The left shifter then tries to perform a logical left shift of the 32 bit value by moving out the number of bits specified by the 5 bit number on the left and bringing that many zeros on the right. I can't understand why the array notation isn't working. The result of 1 << 1 produces 20000000 instead of 00000002. Can someone explain where I'm going wrong? Here's the code:
SIGNAL lshiftOutput : STD_LOGIC_VECTOR( 31 downto 0 );
COMPONENT Lshift32
Port( a : in STD_LOGIC_VECTOR( 31 downto 0 );
b : in STD_LOGIC_VECTOR( 4 downto 0 );
lshiftOutput : out STD_LOGIC_VECTOR( 31 downto 0 ) );
END COMPONENT;
PROCESS( a, b, opcode, adderOutput, subtractOutput, xorOutput, lshiftOutput, rshiftOutput )
BEGIN
IF opcode = "0000" THEN
result <= x"00000000";
ELSIF opcode = "0001" THEN
result <= adderOutput;
ELSIF opcode = "0010" THEN
result <= subtractOutput;
ELSIF opcode = "0011" THEN
result <= NOT a;
ELSIF opcode = "0100" THEN
result <= a AND b;
ELSIF opcode = "0101" THEN
result <= a OR b;
ELSIF opcode = "0110" THEN
result <= xorOutput;
ELSIF opcode = "0111" THEN
result <= lshiftOutput;
ELSIF opcode = "1000" THEN
result <= rshiftOutput;
END IF;
END PROCESS;
LIBRARY ieee;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY Lshift32 IS
Port( a : in STD_LOGIC_VECTOR ( 31 downto 0 );
b : in STD_LOGIC_VECTOR ( 4 downto 0 );
lshiftOutput : out STD_LOGIC_VECTOR ( 31 downto 0 ) );
END Lshift32;
ARCHITECTURE Lshift32Architecture of Lshift32 IS
BEGIN
PROCESS( a, b )
VARIABLE shiftAmount : INTEGER := 0;
BEGIN
shiftAmount := to_integer( b(4 downto 0) );
-- Shift left
lshiftOutput <= a( 31-shiftAmount downto 0 ) & ( shiftAmount-1 downto 0 => '0' );
END PROCESS;
END Lshift32Architecture;
The test bench for this is:
-- Shift Left -------------------------------------------------------
WAIT FOR 9 ns;
op <= "0111";
-- 1 << 1
input_a <= x"00000001";
input_b <= x"00000001";
WAIT FOR 1 ns;
IF (output /= x"00000002") THEN
ASSERT false REPORT "1 << 1 has incorrect result" severity error;
END IF;
Brian asked that you supply a Minimal, Complete, and Verifiable example, your edited code doesn't do that. And the reason for asking is that it's possible to create an mcve around the portions of your code you originally supplied that does give the right answer:
library ieee; -- added
use ieee.std_logic_1164.all; -- added
use ieee.numeric_std_unsigned.all; -- added
entity lshift32 is
port( a : in std_logic_vector ( 31 downto 0 );
b : in std_logic_vector ( 4 downto 0 );
lshiftoutput : out std_logic_vector ( 31 downto 0 ) );
end entity lshift32;
architecture lshift32architecture of lshift32 is
begin
process( a, b )
variable shiftamount : integer := 0;
begin
shiftamount := to_integer( b(4 downto 0) );
-- shift left
lshiftoutput <= a( 31-shiftamount downto 0 ) & ( shiftamount-1 downto 0 => '0' );
end process;
end architecture lshift32architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity lshift32_tb is
end entity;
architecture foo of lshift32_tb is
signal a: std_logic_vector (31 downto 0) := (others => '0');
signal b: std_logic_vector (4 downto 0) := (others => '0');
signal lshiftoutput: std_logic_vector (31 downto 0);
begin
DUT:
entity work.lshift32
port map (
a => a,
b => b,
lshiftoutput => lshiftoutput
);
SIMULIS:
process
begin
wait for 10 ns;
a(0) <= '1'; -- 1
b(0) <= '1'; -- 1
wait for 10 ns;
wait;
end process;
ANALYSIS:
process (lshiftoutput)
variable shiftamount: integer;
begin
if now > 0 ns then
shiftamount := to_integer(b);
report "ShiftAmount = " & integer'image(shiftamount);
report "lshiftOutput = " & to_string(lshiftoutput);
end if;
end process;
end architecture;
And running the above testbench gives:
ghdl -a --std=08 lshift.vhdl
ghdl -e --std=08 lshift32_tb
ghdl -r lshift32_tb
lshift.vhdl:60:13:#10ns:(report note): ShiftAmount = 1
lshift.vhdl:61:13:#10ns:(report note): lshiftOutput = 00000000000000000000000000000010
And that your execution fails says there's either something wrong with your context clause (use clauses) or something wrong with your testbench.
Note that you are using both none standard package std_logic_unsigned and IEEE standard package numeric_std. You really shouldn't mix and match there can be unexpected consequences.
The package numeric_std_unsigned is available with a VHDL implementation compliant with the IEEE Std 1076-2008 standard. If using a previous version of the VHDL standard you can use package numeric_std and type convert b to unsigned as the expression passed to to_integer.
For the testbench supplied with this answer you'd also find that to_stringfor std_logic_vector is not supplied. Without seeing your entire testbench it could well be functional.
If you want to prove the answer supplied testbench works in a non -2008 revision environment:
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;
The function can be supplied as an architecture declarative item.

VHDL 8-bit multiplier, 3-bit input and 4-bit input, how to compensate for number of bits in output?

I have been working on a vhdl program that accepts 2 inputs, a 3-bit input and a 4-bit input. The 3-bit input represents "2 to the power of n", ie an input of 010(which is 2) would equal 2^2=4. An input of 110(which is 6) would yield 2^6 which is 64. This is to be multiplied by a 4-bit input from 0000 to 1111, and the answer stored as 8-bits. However, when I try to solve for this in VHDL, I keep getting the error "Expression error at midterm_q_one.vhd(34): expression has 12 elements, but must have 8 elements". I am new to VHDL, and searching online has yielded little result. I want a way for my output, in this case hex, to store the product of my 2 inputs as an 8 bit value but don't know how. Any help would be greatly appreciated and below is my code. Thanks!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity midterm_q_one is
port(en: in std_logic;
reset: in std_logic;
three_bit: in std_logic_vector(2 downto 0);
four_bit: in std_logic_vector(3 downto 0);
hex: out std_logic_vector(7 downto 0)
);
end midterm_q_one;
architecture arch of midterm_q_one is
signal temp : std_logic_vector(7 downto 0);
begin
process(en, reset, three_bit, four_bit)
begin
if(reset = '1') then
temp <= "00000000";--reset to decimal 0
elsif(en = '1') then
case three_bit is
when "000" => temp <= "00000001";--1
when "001" => temp <= "00000010";--2
when "010" => temp <= "00000100";--4
when "011" => temp <= "00001000";--8
when "100" => temp <= "00010000";--16
when "101" => temp <= "00100000";--32
when "110" => temp <= "01000000";--64
when "111" => temp <= "10000000";--128
end case;
end if;
hex <= temp * four_bit;
end process;
end arch;
Multiplication of the 8-bit temp with the 8-bit four_bit gives a 12-bit result, which is assigned to the 8-bit hex, thus the error message "expression has 12 elements, but must have 8 elements".
Suggestion: Get ridge of the non-standard (Synopsys) STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED, and start using the standard numeric_std package.
With the numeric_std you can resize the result using:
library ieee;
use ieee.numeric_std.all;
...
hex <= std_logic_vector(resize(unsigned(temp) * unsigned(four_bit), hex'length));
I could see two ways to get rid of the error.
The simplest is:
architecture simple of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
begin
if reset = '1' then
hex <= (others => '0');
elsif en = '1' then
hex <= SHL("0000" & four_bit, three_bit);
end if;
end process;
end architecture;
This still requires some knowledge of what 8 bit's you want, or whether you want the value to clamp to x"FF" or whether you want the 8 bit best product:
architecture best_product of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
variable intermed: std_logic_vector (11 downto 0);
begin
if reset = '1' then
intermed := (others => '0');
elsif en = '1' then
intermed := SHL("0000" & four_bit, three_bit);
end if;
hex <= intermed(11 downto 4);
end process;
end architecture;
Clamping:
architecture saturate_clamp of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
variable intermed: std_logic_vector (11 downto 0);
begin
if reset = '1' then
intermed := (others => '0');
elsif en = '1' then
intermed := SHL("0000" & four_bit, three_bit);
end if;
if intermed(11) = '1' or intermed(10) = '1' or
intermed(9) = '1' or intermed(8) = '1' then
hex <= x"FF";
else
hex <= intermed(7 downto 0);
end if;
end process;
end architecture;
What are the 8 bits supposed to represent mathematically?

Generic Binary-Gray, gray-binary converter, logic error

It shows me an error:
ERROR:Xst:787 - "E:/tumama/tytyty.vhd" line 54: Index value <4> is not in Range of array .
Its a "generic" code, my embedded signal A has the 5 bits of n
I only want to use 4 bits to convert in a case. So i have 4 bits in Y
The comments are for the concurrent code
but i dont get it
Thanks
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity FirstTermExamen is
Generic (n: natural := 4);
Port ( Num : in STD_LOGIC_VECTOR (n-1 downto 0);
Sel : in STD_LOGIC;
Y : out STD_LOGIC_VECTOR (n-1 downto 0)
);
end FirstTermExamen;
architecture Behavioral of FirstTermExamen is
signal A: STD_LOGIC_VECTOR (n downto 0);
begin
-- --Secuencial Description
-- Binary_Gray : process(A, Num, Sel)
-- begin
--
-- --Initial conditions
-- A(0) <= Num(0);
-- A(1) <= Num(0) xor Num(1);
--
-- for i in 1 to n-1 loop
-- if Sel = '1' then A(i+1) <= Num(i) xor Num(i+1);
-- else A(i+1) <= A(i) xor Num(i+1);
--
-- end if;
--
-- end loop;
--
-- for j in 0 to n loop
-- Y(j)<= A(j);
--
-- end loop;
--
--end process Binary_Gray;
--Concurrent Description
A(0) <= Num(0);
A(1) <= Num(0) xor Num(1);
Binary_Gray:
for i in 1 to n-1 generate
begin
A(i+1) <= Num(i) xor Num(i+1) when Sel = '1' else
A(i) xor Num(i+1);
end generate;
output:
for j in 0 to n generate
begin
Y(j)<= A(j);
end generate;
end Behavioral;
When your loop index i reaches the value n-1 then you are trying to access Num(n). However, Num is only defined for the range of (n-1 downto 0).
A Numeric example would be for n=4, as is your default case:
You generate for i values from 1 to 3, but access Num(i+1), therefore Num(4). But, as stated above, Num is only defined in the range 3 downto 0.

Resources