load VHDL sram from a file - vhdl

I was curious why the following code doesn't work to load an sram memory array in VHDL? What am I missing?
here's my input file: ram_image.hex
be
ef
ca
fe
34
23
Here's the code where i attempt to load my_ram using the impure function load_sram_hex.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
use std.textio.all;
entity sram is
end entity;
architecture beh of sram is
constant sram_dw :integer := 8;
constant sram_aw :integer := 4;
constant sram_depth :integer := 2**sram_aw - 1;
type sram_t is array (0 to sram_depth-1) of std_logic_vector(sram_dw downto 0);
impure function load_sram_hex(filename : in string) return sram_t is
file f :text is in filename;
variable b :line;
variable mem :sram_t;
variable good :boolean;
variable m :line;
begin
for i in sram_t'range loop
readline(f, b);
hread(b, mem(i), good);
write(m, string'("HERE=> ") );
hwrite(m, mem(i));
writeline(output, m);
if (not good) then
exit;
end if;
end loop;
return mem;
end function;
signal my_ram : sram_t := load_sram_hex("ram_image.hex");
begin
process
variable m :line;
begin
wait for 10 ns;
for i in sram_t'range loop
write(m, string'("ram["));
write(m, i);
write(m, string'("] = "));
hwrite(m, my_ram(i));
writeline(output, m);
end loop;
wait for 1000 ns;
report "just kidding! end of testbench" severity failure;
end process;
end architecture;
Here you can see the output of the vhdl simulation is just x's even tough i loaded the memory...
## run all
ram[0] = XXX
ram[1] = XXX
ram[2] = XXX
ram[3] = XXX
ram[4] = XXX
ram[5] = XXX
ram[6] = XXX
ram[7] = XXX
ram[8] = XXX
ram[9] = XXX
ram[10] = XXX
ram[11] = XXX
ram[12] = XXX
ram[13] = XXX
ram[14] = XXX
Failure: just kidding! end of testbench
Time: 1010 ns Iteration: 0 Process: /sram/line__52 File: sram.vhd

This worked in vivado simulator for me:
-- FILE: ram_image.hex
-- ab
-- 12
-- ef
-- 14
-- 34
-- 23
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
entity sram is
end entity;
architecture beh of sram is
constant sram_dw :integer := 8;
constant sram_aw :integer := 4;
constant sram_depth :integer := 2**sram_aw - 1;
type sram_t is array (0 to sram_depth-1) of std_logic_vector(sram_dw-1 downto 0);
shared variable my_ram :sram_t;
procedure hread_backport(
l :inout line;
value :out std_logic_vector
) is
variable offset :integer;
variable c :character;
variable good1 :boolean;
variable hex_val :std_logic_vector(3 downto 0);
begin
offset := 0;
value := (others => '0');
while (offset < value'high) loop
read(l, c, good1);
if (not good1) then exit; end if;
case c is
when '0' => hex_val := "0000";
when '1' => hex_val := "0001";
when '2' => hex_val := "0010";
when '3' => hex_val := "0011";
when '4' => hex_val := "0100";
when '5' => hex_val := "0101";
when '6' => hex_val := "0110";
when '7' => hex_val := "0111";
when '8' => hex_val := "1000";
when '9' => hex_val := "1001";
when 'A' | 'a' => hex_val := "1010";
when 'B' | 'b' => hex_val := "1011";
when 'C' | 'c' => hex_val := "1100";
when 'D' | 'd' => hex_val := "1101";
when 'E' | 'e' => hex_val := "1110";
when 'F' | 'f' => hex_val := "1111";
when others =>
hex_val := "XXXX";
assert false report "Found non-hex character'" & c & "'";
end case;
value( (value'high-offset) downto (value'high-offset-3) ) := hex_val;
offset := offset + 4;
end loop;
end procedure;
procedure sram_load_hex(filepath :string) is
file f :text;
variable b, m :line;
variable good :boolean;
begin
write(m, string'("opening file: ") & filepath );
writeline(output, m);
file_open(f, filepath, read_mode);
for i in sram_t'range loop
if (endfile(f)) then exit; end if;
readline(f, b);
hread_backport(b, my_ram(i));
end loop;
end procedure;
procedure sram_print_hex is
variable m :line;
begin
for i in sram_t'range loop
write(m, string'("read ram["));
write(m, i);
write(m, string'("] = "));
hwrite(m, my_ram(i));
writeline(output, m);
end loop;
end procedure;
begin
process
begin
sram_load_hex("C:/Users/racerx/Desktop/sandbox/sram/ram_image.hex");
wait;
end process;
process
begin
wait for 1000 ns;
sram_print_hex;
report "just kidding! end of testbench" severity failure;
end process;
end architecture;

Related

Unable to synthesize code. GHDL throws an array bounds error

I'm new to Stack Overflow and to VHDL too. I have completed the logic of an N-bit shifter and tested it using a testbench. But am unable to synthesize it.
While synthesizing I get an error saying "left and right bounds of a slice must be either constant or dynamic" (it is in line 37 and 45, also visible in the attached picture). Can somebody please tell what I need to fix (and perhaps how)?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.types.all;
use work.functions.all;
use work.casts.all;
entity logbarrel is
generic ( N : natural := 32
);
port ( a : in std_logic_vector(N-1 downto 0); -- input data word
func : in std_logic_vector( 2 downto 0); -- ctrl word (000=>>, 001=<<, 010=*>, 011=<*, 100=>>>)
shamt : in std_logic_vector(log2(N)-1 downto 0); -- shift amount
y : out std_logic_vector(N-1 downto 0) -- output data word
);
end;
architecture rtl1 of logbarrel is
begin
process(all)
constant stage : natural := log2(N); -- number of stages
variable rotr : arr_of_slv(stage-1 downto 0)(N-1 downto 0); -- rotated words
variable mask : arr_of_slv( N-1 downto 0)(N-1 downto 0); -- masks for all possible shifts
variable sh : std_logic_vector(shamt'range) := (others =>'0'); -- used as actual shift amount
begin
-- left or right shift
if to_int(func) = 1 OR to_int(func) = 3 then --checking for left, easier
sh := (others =>'0'); --left makes sh = 000
else
sh := (0 => '1', others =>'0'); --right makes sh = 001
end if;
-- 1st stage
if shamt(0) = '1' then -- shift if needed
rotr(stage-1) := a(N*(1-to_int(sh))+2*to_int(sh)-2 downto 0) & a(N-1 downto N*(1-to_int(sh))+2*to_int(sh)-2+1); --rotate
else
rotr(stage-1) := a; --no shift
end if;
-- i-th stage
for i in stage-2 downto 0 loop
if shamt(stage-i-1) = '1' then -- shift if needed
rotr(i) := rotr(i+1)(N*(1-to_int(sh))+(2*to_int(sh)-1)*2**(stage-i-1)-1 downto 0) & rotr(i+1)(N-1 downto N*(1-to_int(sh))+(2*to_int(sh)-1)*2**(stage-i-1)); --rotate
else
rotr(i) := rotr(i+1); --no shift at this level
end if;
end loop;
-- mask the rotated data if needed
for i in 0 to N-1 loop
case func is
when "000" | "100" => mask(i) := (N-1 downto N-1-i+1 => '0') & (N-i-1 downto 0 => '1'); -- right shift
when "001" => mask(i) := (N-1 downto i => '1') & (i-1 downto 0 => '0'); -- left shift
when "010" | "011" => mask(i) := (others => '1'); -- rotate
when others => mask(i) := (others => '0'); -- this case 101 should not occur
end case;
end loop;
-- output masking
y <= (N-1 downto N-to_int(shamt) => a(N-1)) & (rotr(0)(N-to_int(shamt)-1 downto 0) AND mask(to_int(shamt))(N-to_int(shamt)-1 downto 0)) when func = "100" else -- masking for arith. right shift
rotr(0) AND mask(to_int(shamt)); -- masking for all other cases
end process;
end;
Here's the original code skeleton, on which I had to change the lines only where TODO was written
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.types.all;
use work.functions.all;
use work.casts.all;
entity logbarrel is
generic ( N : natural := 32
);
port ( a : in std_logic_vector(N-1 downto 0); -- input data word
func : in std_logic_vector( 2 downto 0); -- ctrl word (000=>>, 001=<<, 010=*>, 011=<*, 100=>>>)
shamt : in std_logic_vector(log2(N)-1 downto 0); -- shift amount
y : out std_logic_vector(N-1 downto 0) -- output data word
);
end;
architecture rtl1 of logbarrel is
begin
process(all)
constant stage : natural := log2(N); -- number of stages
variable rotr : arr_of_slv(stage-1 downto 0)(N-1 downto 0); -- rotated words
variable mask : arr_of_slv( N-1 downto 0)(N-1 downto 0); -- masks for all possible shifts
variable sh : std_logic_vector(shamt'range) := (others =>'0'); -- used as actual shift amount
begin
-- left or right shift
if TODO then
sh := TODO
else
sh := TODO
end if;
-- 1st stage
if TODO then -- shift if needed
rotr(stage-1) := TODO
else
rotr(stage-1) := TODO
end if;
-- i-th stage
for i in TODO loop
if TODO then -- shift if needed
rotr(i) := TODO
else
rotr(i) := TODO
end if;
end loop;
-- mask the rotated data if needed
for i in 0 to N-1 loop
case func is
when TODO => mask(i) := TODO -- right shift
when TODO => mask(i) := TODO -- left shift
when TODO => mask(i) := TODO -- rotate
when others => mask(i) := TODO -- this case 101 should not occur
end case;
end loop;
-- output masking
y <= TODO when TODO else -- masking for arith. right shift
TODO -- masking for all other cases
end process;
end;
And here is the testbench used to test this as an instantiation. (It also initializes another such entity, I'll paste its code below, in case you want it).
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.casts.all;
use work.functions.all;
entity shifter_tb is
generic( N : natural := 32;
ainit: natural := 16#72345678#);
end;
architecture test of shifter_tb is
signal a, y1, y2 : std_logic_vector(N-1 downto 0):= to_slv(ainit,N);
signal func : std_logic_vector( 2 downto 0);
signal shamt : std_logic_vector(log2(N)-1 downto 0);
begin
stimuli: process
begin
-- for i in 0 to 2**a'length-1 loop
-- a <= to_slv(i, a'length);
for j in 0 to 4 loop --2**func'length-1 loop
func <= to_slv(j, func'length);
for k in 0 to 2**shamt'length-1 loop
shamt <= to_slv(k, shamt'length);
wait for 10 ns;
case func is
when "000" => assert (y1 = y2)
report strs(y1) & strs(y2) & " = " &
str(a) & " >> " & strs(to_int(shamt)) & str(func) ;
when "001" => assert (y1 = y2)
report strs(y1) & str(y2) & " = " &
str(a) & " << " & strs(to_int(shamt)) & str(func) ;
when "010" => assert (y1 = y2)
report strs(y1) & str(y2) & " = " &
str(a) & " *> " & strs(to_int(shamt)) & str(func) ;
when "011" => assert (y1 = y2)
report strs(y1) & str(y2) & " = " &
str(a) & " <* " & strs(to_int(shamt)) & str(func) ;
when others => assert (y1 = y2)
report strs(y1) & str(y2) & " = " &
str(a) & " >>> " & strs(to_int(shamt)) & str(func) ;
end case;
end loop;
end loop;
--end loop;
wait;
end process;
shifter1_inst: entity work.shifter
generic map (N => N)
port map (a, func, shamt, y1);
shifter2_inst: entity work.logbarrel
generic map (N => N)
port map (a, func, shamt, y2);
end;
The other entity called shifter (the golden model):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use work.types.all;
use work.functions.all;
use work.casts.all;
entity shifter is
generic ( N : natural := 32
);
port ( a : in std_logic_vector(N-1 downto 0);
func : in std_logic_vector( 2 downto 0);
shamt : in std_logic_vector(log2(N)-1 downto 0);
y : out std_logic_vector(N-1 downto 0)
);
end;
architecture rtl of shifter is
begin
process(all)
variable rotr, rotl, ashr, lshr, lshl : arr_of_slv(N-1 downto 0)(N-1 downto 0);
begin
lshr(0) := a; lshl(0) := a; ashr(0) := a; rotr(0) := a; rotl(0) := a;
for i in 1 to N-1 loop
lshr(i) := (i-1 downto 0 => '0') & a(N-1 downto i);
lshl(i) := a((N-1)-i downto 0) & (i-1 downto 0 => '0');
ashr(i) := (i-1 downto 0 => a(N-1)) & a(N-1 downto i);
rotr(i) := a( i-1 downto 0) & a(N-1 downto i);
rotl(i) := a((N-1)-i downto 0) & a(N-1 downto N-i);
end loop;
y <= lshr(to_int(shamt)) when func = "000" else
lshl(to_int(shamt)) when func = "001" else
rotr(to_int(shamt)) when func = "010" else
rotl(to_int(shamt)) when func = "011" else
ashr(to_int(shamt));
end process;
end;
And finally the header files (not sure what they're called in the VHDL world) that are being used in the testbench and the instantiated architectures:
types:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package types is
constant width : integer := 32;
subtype byte is natural range 7 downto 0;
subtype logic is std_logic;
subtype byteT is std_logic_vector(byte);
subtype word is std_logic_vector(width-1 downto 0);
subtype uword is unsigned(width-1 downto 0);
subtype sword is signed (width-1 downto 0);
type arr_of_slv is array (natural range <>) of std_logic_vector;
type matrix is array (natural range <>, natural range <>) of std_logic;
end;
package body types is
end;
functions:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.casts.all;
use work.types.all;
package functions is
function log2 (a : natural) return natural;
function replicate(s : std_logic; n: integer) return std_logic_vector;
function decode(arg : std_logic_vector) return std_logic_vector;
function mux(sel, x : std_logic_vector) return std_logic;
function mux(sel : std_logic_vector; x : arr_of_slv) return std_logic_vector;
-- function mux(sel : std_logic_vector; x : arr_of_slv (0 TO M-1)(N-1 downto 0)) return std_logic_vector is
function reduce(Inputs : std_logic_vector ) return std_logic_vector;
--function reduction( Inputs : arr_of_slv ) return std_logic_vector;
end;
package body functions is
function log2 (a: natural) return natural IS
variable val : natural := a;
variable log : natural := 0;
begin
for i in a downto 0 loop
val := val / 2;
if val > 0 then
log := log + 1;
end if;
end loop;
return log;
end;
function replicate(s: std_logic; n: integer) return std_logic_vector is
variable r : std_logic_vector(n-1 downto 0);
begin
for i in 0 to n-1 loop
r(i) := s;
end loop;
return r;
end;
function decode (arg : std_logic_vector) return std_logic_vector is
variable res : std_logic_vector((2**arg'length)-1 downto 0);
begin
res(to_int(arg)) := '1';
return res;
end;
function mux( sel, x : std_logic_vector ) return std_logic is
begin
return x(to_int(sel));
end;
function mux( sel : std_logic_vector; x: arr_of_slv) return std_logic_vector is
begin
-- assert Inputs'length <= 2 ** sel'length
-- report "Inputs size: " & integer'image(Inputs'length) & " is too big for the select";
return x(to_int(sel));
end;
-- function mux(sel : std_logic_vector; x : arr_of_slv (0 TO M-1)(N-1 downto 0)) return std_logic_vector is
-- variable y : std_logic_vector(x(0)'length-1 downto 0);
-- begin
-- y := x(to_int(sel));
-- return y;
-- end;
function reduce( Inputs : std_logic_vector ) return std_logic_vector is
constant N : integer := Inputs'length;
variable inp : std_logic_vector(N-1 downto 0);
begin
inp := Inputs;
if(N = 4) then
return inp(1 downto 0) xor inp(3 downto 2);
else
return reduce(inp((N-1) downto N/2)) xor reduce(inp(((N/2)-1) downto 0));
end if;
end;
-- function reduction( Inputs: arr_of_slv ) return std_logic_vector is
-- constant N : integer := Inputs'length;
-- variable inp : arr_of_slv(N-1 downto 0, 12-1 downto 0);
-- begin
-- --return x"1234"; --Inputs(0);
-- inp := Inputs;
-- if N = 1 then
-- return inp(0);
-- elsif N > 1 then
-- return reduction(inp(N-1 downto N/2)) xor reduction(inp(N/2-1 downto 0));
-- end if;
-- end;
end;
casts:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package casts is
function to_int(arg: std_logic_vector) return natural;
function to_sint(arg: std_logic_vector) return natural;
function to_int(arg: unsigned) return natural;
function to_int(arg: signed) return natural;
function to_slv(arg: integer; bits: integer) return std_logic_vector;
function to_slv(arg: unsigned) return std_logic_vector;
function to_slv(arg: signed) return std_logic_vector;
function to_slv(arg: std_ulogic_vector) return std_logic_vector;
function to_sslv(arg: integer; bits: natural) return std_logic_vector;
function str(s: std_ulogic_vector) return string;
function str(s: integer) return string;
function strs(s: std_ulogic_vector) return string;
function strs(s: integer) return string;
function strs(s: std_logic) return string;
function str(s: std_logic) return character;
end;
package body casts is
subtype logic is std_logic;
type logic_vector is array (natural range <>) of std_logic;
function to_int (arg: std_logic_vector) return natural IS
begin
return to_integer(unsigned(arg));
end;
function to_sint (arg: std_logic_vector) return natural IS
variable x : signed(arg'range);
begin
x := signed(arg);
return to_integer(x);
end;
function to_int (arg: unsigned) return natural IS
begin
return to_integer(arg);
end;
function to_int (arg: signed) return natural IS
begin
return to_integer(arg);
end;
function to_slv(arg: integer; bits: integer) return std_logic_vector is
begin
return std_logic_vector(to_unsigned(arg,bits));
end;
function to_sslv(arg: integer; bits: natural) return std_logic_vector is
begin
return std_logic_vector(to_signed(arg,bits));
end;
function to_slv(arg: unsigned) return std_logic_vector IS
begin
return std_logic_vector(arg);
end;
function to_slv(arg: std_ulogic_vector) return std_logic_vector IS
begin
return to_stdlogicvector(arg);
end;
function to_slv(arg: signed) return std_logic_vector IS
begin
return std_logic_vector(arg);
end;
function chr2sl (ch: in character) return std_logic is
begin
case ch is
when 'U' | 'u' => return 'U';
when 'X' | 'x' => return 'X';
when '0' => return '0';
when '1' => return '1';
when 'Z' | 'z' => return 'Z';
when 'W' | 'w' => return 'W';
when 'L' | 'l' => return 'L';
when 'H' | 'h' => return 'H';
when '-' => return '-';
when OTHERS => assert false
report "Illegal Character found" & ch
severity error;
return 'U';
end case;
end;
function str2sl (s: string) return std_logic_vector is
variable vector: std_logic_vector(s'LEFT - 1 DOWNTO 0);
begin
for i in s'RANGE loop
vector(i-1) := chr2sl(s(i));
end loop;
return vector;
end;
function to_char(s: std_ulogic) return character is
begin
case s is
when 'X' => return 'X';
when '0' => return '0';
when '1' => return '1';
when 'Z' => return 'Z';
when 'U' => return 'U';
when 'W' => return 'W';
when 'L' => return 'L';
when 'H' => return 'H';
when '-' => return '-';
end case;
end;
function str(s: std_ulogic_vector) return string is
variable ret:string(1 to s'length);
variable K : integer:= 1;
begin
for J in s'range loop
ret(K) := to_char(s(J));
K := K + 1;
end loop;
return ret;
end;
function strs(s: std_ulogic_vector) return string is
begin
return str(s) & ' ';
end;
function str(s: std_logic) return character is
begin
return to_char(s);
end;
function strs(s: std_logic) return string is
begin
return str(s) & ' ';
end;
function to_nstring(s: natural) return string is
variable ret, iret : string(1 to 16);
variable k, j : integer;
variable s1, s2, s3: natural := 0;
begin
s1 := s;
ret(1) := '0';
k := 1;
while (s1 > 0 and K < 16) loop
s2 := s1 / 10;
s3 := s1 - (s2 * 10);
if (s3 = 0) then
ret(k) := '0';
elsif (s3 = 1) then
ret(k) := '1';
elsif (s3 = 2) then
ret(k) := '2';
elsif (s3 = 3) then
ret(k) := '3';
elsif (s3 = 4) then
ret(k) := '4';
elsif (s3 = 5) then
ret(k) := '5';
elsif (s3 = 6) then
ret(k) := '6';
elsif (s3 = 7) then
ret(k) := '7';
elsif (s3 = 8) then
ret(k) := '8';
elsif (s3 = 9) then
ret(k) := '9';
end if;
k := k + 1;
s1 := s2;
end loop;
if (k > 1) then
k := k-1;
end if;
J := 1;
while (k > 0) loop
iret(j) := ret(k);
k := k-1;
j := j+1;
end loop;
return iret;
end;
function str(s: integer) return string is
begin
if (s < 0) then
return "-" & to_nstring(-s);
else
return to_nstring(s);
end if;
end;
function strs(s: integer) return string is
begin
return str(s) & ' ';
end;
end;

Error (10395): VHDL Conditional Signal Assignment error at (146): conditional waveforms must have same number of elements

Error (10395): VHDL Conditional Signal Assignment error at vga.vhd(146): conditional waveforms must have same number of elements.
in this line show me error
R<=intensity WHEN red_switch='0' AND dena='1' ELSE (OTHERS=>'1');
I really don't know what's wrong vhdl Altera code error but it didn't solve my problem. thanks in advance.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
LIBRARY lpm;
USE lpm.lpm_components.all;
----------------------------------------------------------
ENTITY vga IS
GENERIC (
Ha: INTEGER := 96; --Hpulse
Hb: INTEGER := 144; --Hpulse+HBP
Hc: INTEGER := 784; --Hpulse+HBP+Hactive
Hd: INTEGER := 800; --Hpulse+HBP+Hactive+HFP
Va: INTEGER := 2; --Vpulse
Vb: INTEGER := 35; --Vpulse+VBP
Vc: INTEGER := 515; --Vpulse+VBP+Vactive
Vd: INTEGER := 525); --Vpulse+VBP+Vactive+VFP
PORT (
clk: IN STD_LOGIC; --50MHz in our board
red_switch, green_switch, blue_switch: IN STD_LOGIC;
pixel_clk: BUFFER STD_LOGIC;
Hsync, Vsync: BUFFER STD_LOGIC;
R, G, B: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
nblanck, nsync : OUT STD_LOGIC);
END vga;
----------------------------------------------------------
ARCHITECTURE vga OF vga IS
SIGNAL Hactive, Vactive, dena: STD_LOGIC;
SIGNAL address: STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL intensity: STD_LOGIC_VECTOR(9 DOWNTO 0);
BEGIN
-------------------------------------------------------
--Part 1: CONTROL GENERATOR
-------------------------------------------------------
--Static signals for DACs:
nblanck <= '1'; --no direct blanking
nsync <= '0'; --no sync on green
--Create pixel clock (50MHz->25MHz):
PROCESS (clk)
BEGIN
IF (clk'EVENT AND clk='1') THEN
pixel_clk <= NOT pixel_clk;
END IF;
END PROCESS;
--Horizontal signals generation:
PROCESS (pixel_clk)
VARIABLE Hcount: INTEGER RANGE 0 TO Hd;
BEGIN
IF (pixel_clk'EVENT AND pixel_clk='1') THEN
Hcount := Hcount + 1;
IF (Hcount=Ha) THEN
Hsync <= '1';
ELSIF (Hcount=Hb) THEN
Hactive <= '1';
ELSIF (Hcount=Hc) THEN
Hactive <= '0';
ELSIF (Hcount=Hd) THEN
Hsync <= '0';
Hcount := 0;
END IF;
END IF;
END PROCESS;
--Vertical signals generation:
PROCESS (Hsync)
VARIABLE Vcount: INTEGER RANGE 0 TO Vd;
BEGIN
IF (Hsync'EVENT AND Hsync='0') THEN
Vcount := Vcount + 1;
IF (Vcount=Va) THEN
Vsync <= '1';
ELSIF (Vcount=Vb) THEN
Vactive <= '1';
ELSIF (Vcount=Vc) THEN
Vactive <= '0';
ELSIF (Vcount=Vd) THEN
Vsync <= '0';
Vcount := 0;
END IF;
END IF;
END PROCESS;
---Display enable generation:
dena <= Hactive AND Vactive;
-------------------------------------------------------
--Part 2: IMAGE GENERATOR
-------------------------------------------------------
PROCESS (Hsync, Vsync, Vactive, dena, red_switch,
green_switch, blue_switch)
VARIABLE line_counter: INTEGER RANGE 0 TO Vc;
BEGIN
IF (Vsync='0') THEN
line_counter := 0;
ELSIF (Hsync'EVENT AND Hsync='1') THEN
IF (Vactive='1') THEN
line_counter := line_counter + 1;
END IF;
END IF;
IF (dena='1') THEN
IF (line_counter=1) THEN
R <= (OTHERS => '1');
G <= (OTHERS => '0');
B <= (OTHERS => '0');
ELSIF (line_counter>1 AND line_counter<=3) THEN
R <= (OTHERS => '0');
G <= (OTHERS => '1');
B <= (OTHERS => '0');
ELSIF (line_counter>3 AND line_counter<=6) THEN
R <= (OTHERS => '0');
G <= (OTHERS => '0');
B <= (OTHERS => '1');
ELSE
R <= (OTHERS => red_switch);
G <= (OTHERS => green_switch);
B <= (OTHERS => blue_switch);
END IF;
ELSE
R <= (OTHERS => '0');
G <= (OTHERS => '0');
B <= (OTHERS => '0');
END IF;
END PROCESS;
--END vga;
-------------------------------------------
--ROM instantiation:
myrom: lpm_rom
GENERIC MAP (
lpm_widthad => 9, --address width
lpm_outdata => "UNREGISTERED",
lpm_address_control => "REGISTERED",
lpm_file => "pic_6.mif", --data file
lpm_width => 10) --data width
PORT MAP (
inclock=>NOT pixel_clk, address=>address, q=>intensity);
--Create address (row number):
PROCESS (Vsync, Hsync)
VARIABLE line_counter: INTEGER RANGE 0 TO Vd;
BEGIN
IF (Vsync='0') THEN
line_counter := 0;
ELSIF (Hsync'EVENT AND Hsync='1') THEN
IF (Vactive='1') THEN
line_counter := line_counter + 1;
END IF;
END IF;
address <= conv_std_logic_vector(line_counter, 9);
END PROCESS;
-- --Assign color values to R/G/B:
R<=intensity WHEN red_switch='0' AND dena='1' ELSE (OTHERS=>'1');
G<=intensity WHEN green_switch='0' AND dena='1' ELSE (OTHERS=>'1');
B<=intensity WHEN blue_switch='0' AND dena='1' ELSE (OTHERS=>'1');
END vga;
Signal R is 8 bits wide:
R, G, B: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
while signal intensity is 10 bits wide:
SIGNAL intensity: STD_LOGIC_VECTOR(9 DOWNTO 0);
This is not allowed in VHDL. Both must be the same width; you must either explicitly truncate intensity or extend R.

How to shift std_logic_vector?

I want shift std_logic_vector.
But this code is has an error:
architecture led_main of testing is
signal clk_cnt : std_logic_vector(64 DOWNTO 0) := (others => '0');
signal led_buf : std_logic_vector( 3 downto 0 ) := "0001";
begin
process(clk)
begin
if rising_edge(clk) then
clk_cnt <= clk_cnt + 1;
if clk_cnt >= 24999999 then
led_buf <= led_buf(0) & led_buf(3 downto 1);
end if;
end if;
end process;
ground <= '0';
end led_main;
I think "0001", "0010", "0100" ...
Your shifter is OK. Actually, it's a rotator.
But your counter is to big (65 bits) and it doesn't roll over or reset to zero in a proper time. Your current design waits for 25M cycles and then shifts in every cycle from 25M to 2**64.
More over, you are using a non standard IEEE package to perform arithmetic operations (addition) on std_logic_vector. Please use type unsigned from package numeric_std.
The needed number of bits for your counter can be obtained by a log2 function like this:
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;
Source: https://github.com/VLSI-EDA/PoC/blob/master/src/common/utils.vhdl
Full code rewrite:
use IEEE.numeric_std.all;
architecture led_main of testing is
constant CNT_MAX : positive := 25000000;
signal clk_cnt : unsigned(log2ceil(CNT_MAX) - 1 downto 0) := (others => '0');
signal led_buf : std_logic_vector( 3 downto 0 ) := "0001";
begin
process(clk)
begin
if rising_edge(clk) then
clk_cnt <= clk_cnt + 1;
if clk_cnt = (CNT_MAX - 1) then
clk_cnt <= (others => '0');
led_buf <= led_buf(0) & led_buf(3 downto 1);
end if;
end if;
end process;
end led_main;
```

variable must be constrained error

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.

My function does not return a value, and I do not understand why? VHDL

Part of code in VHDL. Workspace ISE.
My function does not return a value, and I do not understand why
Note that appears to me in ISE is "function 'con_integer14' does not always return a value."
The Function is:
function con_integer14 (vNumberSTD : std_logic_vector(14 downto 0)) return integer is
variable vCounter : integer range 0 to 16 := 0;
variable vNumberINT : integer range 0 to 16384 := 0;
begin
if (vCounter = 0) then
if ((vNumberSTD(vCounter)) = '1') then
vNumberINT := (vNumberINT+(2**vCounter));
elsif ((vNumberSTD(vCounter)) = '0') then
vNumberINT := vNumberINT;
end if;
vCounter := (vCounter+1);
elsif ((vCounter >= 1)or(vCounter < 14)) then
if ((vNumberSTD(vCounter)) = '1') then
vNumberINT := (vNumberINT+(2**vCounter));
elsif ((vNumberSTD(vCounter)) = '0') then
vNumberINT := vNumberINT;
end if;
vCounter := (vCounter+1);
elsif (vCounter = 14) then
if ((vNumberSTD(vCounter)) = '1') then
vNumberINT := (vNumberINT+(2**vCounter));
elsif ((vNumberSTD(vCounter)) = '0') then
vNumberINT := vNumberINT;
end if;
vCounter := (vCounter+1);
elsif (vCounter = 15) then
return vNumberINT;
vCounter := 0;
elsif (vCounter > 15) then
vNumberINT := 0;
vCounter := 0;
end if;
end function con_integer14;
Please help me, thank you :)
I'd go a step further and tell you your function never returns a value. I took the liberty of removing the superfluous parentheses and then took a look at the function's structure.
You're going to execute the first if statement and fail to return a value - there is no return statement in reach.
Add a test bench:
library ieee;
use ieee.std_logic_1164.all;
use work.foo.all;
entity fum is
end entity;
architecture fie of fum is
signal vNumberINT: integer range 0 to 16384;
signal vNumberSTD: std_logic_vector(14 downto 0) := "011001110111100";
begin
CALL:
process
begin
wait for 1 ns;
vNumberINT <= con_integer14(VNumberSTD);
wait for 1 ns;
wait;
end process;
end architecture;
Analyze it, elaborate it and run it:
ghdl -a something.vhdl
david_koontz#Macbook: ghdl -e fum
david_koontz#Macbook: ghdl -r fum
./fum:error: missing return in
function at something.vhdl:10
./fum:error: simulation failed
ghdl: compilation error
And we get it to tell us there's a missing return for the first if statement, that a call to it won't return a value.
To make a conversion routine that converts your std_logic_vector to integer you should use a loop statement with an iteration scheme based on the index range of the input vNumberSTD.
When the loop statement is done 'calculating' vNumberINT return VNumberINT.
Note that if you don't do anything specific about meta values for elements of vNumberSTD they will be treated as '0'.
And with some modifications:
library ieee;
use ieee.std_logic_1164.all;
package foo is
function con_integer14 (vNumberSTD: std_logic_vector(14 downto 0)) return integer;
function conv_slv_int (input: std_logic_vector) return natural;
end package;
package body foo is
function con_integer14 (vNumberSTD : std_logic_vector(14 downto 0)) return integer is
-- variable vCounter: integer range 0 to 16 := 0;
-- variable vNumberINT: integer range 0 to 16384 := 0;
variable vNumberINT: integer range 0 to 32767 := 0;
begin
-- if vCounter = 0 then
-- if vNumberSTD(vCounter) = '1' then
-- vNumberINT := vNumberINT + 2 ** vCounter;
-- elsif vNumberSTD(vCounter) = '0' then
-- vNumberINT := vNumberINT;
-- end if;
-- vCounter := vCounter + 1;
-- elsif vCounter >= 1 or vCounter < 14 then
-- if vNumberSTD(vCounter) = '1' then
-- vNumberINT := vNumberINT + 2 ** vCounter;
-- elsif vNumberSTD(vCounter) = '0' then
-- vNumberINT := vNumberINT;
-- end if;
-- vCounter := vCounter + 1;
-- elsif vCounter = 14 then
-- if vNumberSTD(vCounter) = '1' then
-- vNumberINT := vNumberINT + 2 ** vCounter;
-- elsif vNumberSTD(vCounter) = '0' then
-- vNumberINT := vNumberINT;
-- end if;
-- vCounter := vCounter + 1;
-- elsif vCounter = 15 then
-- return vNumberINT;
-- vCounter := 0;
-- elsif vCounter > 15 then
-- vNumberINT := 0;
-- vCounter := 0;
-- end if;
for i in vNumberSTD'range loop
report "vNumberSTD(" & integer'image(i) & ") = " & std_ulogic'image(vNumberSTD(i));
if vNumberSTD(i) = '1' then
vNumberINT := vNumberINT + 2 ** i;
report "vNumberINT = " & integer'image(vNumberINT);
end if;
end loop;
return vNumberINT;
end function con_integer14;
function conv_slv_int (input: std_logic_vector) return natural is
alias inp: std_logic_vector (input'LENGTH - 1 downto 0) is input;
variable int_equiv: natural range 0 to 2 ** input'LENGTH - 1 := 0;
begin
if Is_X(input) then -- announce meta values - interpreted as '0's
report "conv_slv_int input contains meta value";
end if;
for i in inp'RANGE loop
if To_bit(inp(i)) = '1' then -- convert 'H' to '1', 'L' to '0'
int_equiv := int_equiv + 2 ** i;
end if;
end loop;
return int_equiv;
end function;
end package body;
library ieee;
use ieee.std_logic_1164.all;
use work.foo.all;
entity fum is
end entity;
architecture fie of fum is
signal vNumberINT: integer range 0 to 32767;
signal vNumberSTD: std_logic_vector(14 downto 0) := "HX1001110111100";
begin
CALL:
process
begin
wait for 1 ns;
vNumberINT <= con_integer14(VNumberSTD);
wait for 1 ns;
report "vNumberINT = " &integer'image(vNumberINT);
report "conv_slv_int returns " & integer'image(conv_slv_int(vNumberSTD));
wait;
end process;
end architecture;
Notice I corrected the range of vNumberINT, it can be based on the argument to function con_integer14.
You can remove the report statements in the function. I used them to illustrate the function loop.
I added a second function showing conversion of any length std_logic_vector that will fit in a natural range. It will generate an error when called (function local variables elaborated) if the length of the input won't fit in an integer.
The second function also detects meta value inputs and converts 'H' to '1' and 'L' to '0' for each element of the input.
The use of the alias inp for he input allows us to always deal with the input as natural range, caring about length instead of left and right bounds.
When running the new test bench:
something.vhdl:45:13:#1ns:(report note): vNumberSTD(14) = 'H'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(13) = 'X'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(12) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4096
something.vhdl:45:13:#1ns:(report note): vNumberSTD(11) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(10) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(9) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4608
something.vhdl:45:13:#1ns:(report note): vNumberSTD(8) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4864
something.vhdl:45:13:#1ns:(report note): vNumberSTD(7) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4992
something.vhdl:45:13:#1ns:(report note): vNumberSTD(6) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(5) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5024
something.vhdl:45:13:#1ns:(report note): vNumberSTD(4) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5040
something.vhdl:45:13:#1ns:(report note): vNumberSTD(3) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5048
something.vhdl:45:13:#1ns:(report note): vNumberSTD(2) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5052
something.vhdl:45:13:#1ns:(report note): vNumberSTD(1) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(0) = '0'
something.vhdl:87:9:#2ns:(report note): vNumberINT = 5052
something.vhdl:59:17:#2ns:(report note): conv_slv_int input contains meta value
something.vhdl:88:9:#2ns:(report note): conv_slv_int returns 21436
We see that you can pass std_logic_vector to both that only conv_slt_int will interpret correctly.
Save yourself some time and use the built-in functions. If you just use numeric_std, then you can do the following:
library IEEE ;
use IEEE.numeric_std.all ;
...
signal Y_int : integer ;
signal A_slv15 : std_logic_vector(14 downto 0) ;
...
Y_int <= to_integer( unsigned( A_slv15) ) ;
If you also include numeric_std_unsigned (warning this is VHDL-2008 and may not yet be supported by your tools - try it and report a bug if it does not work) -
library IEEE ;
use IEEE.numeric_std.all ;
use IEEE.numeric_std_unsigned.all ;
...
signal Y_int : integer ;
signal A_slv15 : std_logic_vector(14 downto 0) ;
...
Y_int <= to_integer( A_slv15) ;
Like what has already been mentioned, you did not cover all possible conditions. It's always good to have a default assignment, either by having an "else" clause, or have a default before the if-elsif statement:
function con_integer14 (...) return integer is
begin
vNumberINT := -1;
if (vCounter = 0) then ...
elsif ...
elsif ... then return vNumberINT;
end if;
return vNumberINT;
end function con_integer14;
or alternatively,
function con_integer14 (...) return integer is
begin
if (vCounter = 0) then ...
elsif ...
elsif ... then return vNumberINT;
else
return vNumberINT;
end if;
end function con_integer14;
I personally prefer the first option, because some tools still complain that not all paths are covered for the second option, though in fact all paths were covered. Anyway, this is just a matter of style.
It seems to me that you are only returning a value when vCounter=15:
elsif (vCounter = 15) then return vNumberINT; ...
and this condition is not always met by your testbench (perhaps never met as analysed by David).
-daniel

Resources