Constant initialisation from a user-made function synthesis takes forever but easily created in simulation - vhdl

I have created a function "my_func" in a package which when inputted with x produced a matrix of integers of shape [log2(x), x]. I wish to place this slice into ROM memory for synthesis.
For the sake of synthesis I attatch a counter to the ROM and read out one register per clk cycle. I have been able to simulate this and get the expected answers. The synthesis of the code never finishes, even when the generic controling the function is very small as shown in the code.
I am confused as to why Vivado can very quickly simulate the desired design but takes forever to synthesise. I get no errors from vivado saying that the design is unsynthesisable.
Has anyone else experienced this problem, and what are the steps I can take to avoid the problem in the future?
Please see my synthesis code below and a snippet of the function code below
For the record for this question Synthesis = Elaborate Design (RTL)
library IEEE;
library WORK;
use WORK.mylib.all;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.math_real.all;
entity try is
generic(
x : integer := 8
);
port(
clk : in std_logic;
ouput: out integer;
);
end entity try;
architecture v1 of try is
constant sig : my_matrix_of_integers(0 to integer(log2(real(x)))-1, 0 to x-1) := my_func(x);
signal counter : unsigned(integer(log2(real(x)))-1 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
output <= sig(0, to_integer(counter));
counter <= counter + 1;
end if;
end process;
end architecture v1;
Here is a snippet of my function code
function my_func (x: integer) return mat_t is
variable y: integer := integer(log2(real(x)));
variable cluster : integer;
variable index : integer;
variable mat : my_matrix_of_integers(0 to y-1, 0 to x-1);
begin
for s in 0 to y-1 loop
index := x/(2**(s+1));
cluster := x/index;
for c in 0 to cluster - 1 loop
for i in 0 to index -1 loop
if c mod 2 = 0 then
mat(s, (c*index) + i) := 0;
else
mat(s, (c*index) + i) := i*(2**(s));
end if;
end loop;
end loop;
end loop;
return mat;
end function my_func;
and type ...
type my_matrix_of_integers is array(integer range <>, integer range <>) of integer;

Related

How to code a module that determines horizontal and vertical coordinates of the monitor in vhdl

I am coding a game with vhdl for a school project, I need to write a module to
determine the horizontal and vertical positions of the screen, I wrote one but it does not work correctyly. I think the problem is in the boundary numbers but I do not know how to correct it can you help?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Sync_To_Row_And_Column is
port(
vga_clk : in std_logic;
global_reset : in std_logic;
hdisp : in std_logic;
vdisp : in std_logic;
hpos : out integer;
vpos : out integer
);
end Sync_To_Row_And_Column;
architecture Behavioral of Sync_To_Row_And_Column is
begin
process(vga_clk,hdisp,vdisp,global_reset)
variable hpos_temp : integer range 1 to 640 := 1 ;
variable vpos_temp : integer range 1 to 480 := 1 ;
variable counter : integer := 0;
begin
if(global_reset = '1') then
hpos_temp := 1;
vpos_temp := 1;
counter := 0;
elsif (vga_clk'event and vga_clk='1') then
if (vdisp ='1' and hdisp = '1') then
counter := counter + 1;
if(counter >= 639)then
vpos_temp := vpos_temp + 1;
counter := 0;
end if;
hpos_temp := hpos_temp + 1;
end if;
end if;
hpos <= hpos_temp;
vpos <= vpos_temp;
end process;
end Behavioral;

Generic Multiplexer warning

I created a generic multiplexer( on number of inputs and bits per input) in VHDL. I tested it and it works correctly but I get a width mismatch warning:
Width mismatch. < output > has a width of 8 bits but assigned expression is 64-bit wide.
This is the code of my generic MUX. Can anyone explain me why I get this warning? WHat's wrong with my code? My professor wants me to implement this without the use of process. Thanks
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.package_log.all;
use IEEE.NUMERIC_STD.ALL;
entity mux_generic is
generic(N : natural :=8;
M : natural := 8);
-- N: number of inputs
-- M: bit per input/output
Port ( input : in STD_LOGIC_VECTOR (N*M-1 downto 0);
sel: in STD_LOGIC_VECTOR (log2ceil(N)-1 downto 0);
output : out STD_LOGIC_VECTOR (M-1 downto 0));
end mux_generic;
architecture DataFlow of mux_generic is
begin
output <= input(M*(to_integer(unsigned(sel))+1) - 1 downto M*(to_integer(unsigned(sel))));
end DataFlow;
The function log2ceil is defined in this way:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package package_log is
function log2ceil( n : natural) return natural;
end package_log;
package body package_log is
function log2ceil (N : natural) return natural is
variable i, j : natural;
begin
i := 0;
j := 1;
while (j < N) loop
i := i+1;
j := 2*j;
end loop;
return i;
end function log2ceil;
end package_log;
Please update to the lastest ISE version 14.7, if you haven't done so far. Then enable the new parser for your Spartan-3E FPGA:
Right click on Synthesize -> Process Properties.
Change property display level to "Advanced".
For property "Other XST Command Line Options" enter -use_new_parser yes.
Now the warning goes away. A new warning appears, just noting, that the new parser is not the default one. But, I didn't experienced a problem with this yet.
By the way, your multiplexer description is not yet efficient. Take at look at my other post, for different implementations and their effects on resource usage and timing analysis.

Simulation blinking LED using VHDL with Quartus II and ModelSim

I'm new to VHDL, Quartus II and ModelSim. Now I'm doing a lab where we are constructing a blinking LED. How should simulation be handled when the construction deals with relatively long time periods. The frequency of the blinking LED is 1 Hz and the clock on the dev board I'm using (Terasic DE2-115) is 50 MHz. In the code I'm counting the clock pulses and turn on the LED accordingly. However, when I want to verify my code with ModelSim, I get in to troubles dealing with times as long as seconds. So I solved it just by changing the period in the code to a couple of clock cycles to see that the waves behave as expected. For final compilation, I just change the count value that corresponds to 1 second.
But there should be a better way. I don't really want to touch the VHDL code after simulation. Should I use two rtl's, one for synthesis and one for simulation when dealing with time periods approaching 1 ms and higher?
The VHDL code
library ieee;
use ieee.std_logic_1164.all;
entity lab4 is
port( CLOCK_50 : in std_logic; -- DE2-115 internal clock
KEY : in std_logic_vector(0 downto 0); -- Push-buttons, active 0
-- KEY(0) as reset
LEDG : out std_logic_vector(7 downto 0)); -- Green LEDs
end entity lab4;
architecture lab4_rtl of lab4 is
signal RESET_N : std_logic;
begin
-- Parallel VHDL
constant CLK_FRQ : integer := 50000000;
RESET_N <= KEY(0); -- Here we connect reset to a push-button
-- synch process with asynch reset, i.e. reset as soon as reset is active
p1 : process(CLOCK_50, RESET_N)
variable counter : integer := 0;
variable led_num : integer := 0;
begin
-- reset part
if RESET_N = '0' then --KEY is active 0
counter := 0; --reset counter
LEDG(0) <= '0'; --turn OFF leds
-- synch part, updates depending on clock
elsif rising_edge(CLOCK_50) then
counter := counter + 1;
if counter < 50000000 then;
LEDG(0) <= '1';
elsif counter >= 50000000 AND counter < 100000000 then
LEDG(0) <= '0';
else
counter := 0;
end if;
end if;
end process p1;
end architecture lab4_rtl;
You have declared a named constant, then ignored it...
constant CLK_FRQ : integer := 50000000;
First you can rewrite the counter in terms of CLK_FRQ and CLK_FRQ * 2 instead of magic numbers.
Then you can set different values for CLK_FRQ in sim and synth. There are various ways to do it but my preference is for a function.
function Clock_Frequency return natural is
begin
-- synthesis translate_off
return 50;
-- synthesis translate_on
return 50000000;
end Clock_Frequency;
It uses the "magic" pragmas translate_off (and _on) which may vary between synthesis tools but are accepted by most. These direct synthesis to ignore bits of the source : in this case, the first Return which is only seen by the simulator.
Now you can call this function to initialise the constant
constant CLK_FRQ : integer := Clock_Frequency;
Job done.
I would not change the clock frequency, because this doesn't change the count of events which have to be simulated by the simulator (this is also the time consuming factor). I think it's better to change the number of cycles which must pass until you change the LED output.
You can define a VHDL function which returns TRUE if you are in a simulation environment:
function SIMULATION return boolean is
variable ret : boolean;
begin
ret := false;
--synthesis translate_off
if Is_X('X') then ret := true; end if;
--synthesis translate_on
return ret;
end function;
In addition to this, you can define a if-then-else function to simplify your code:
function ite(cond : BOOLEAN; value1 : INTEGER; value2 : INTEGER) return INTEGER is
begin
if cond then
return value1;
else
return value2;
end if;
end function;
And now it's possible to select the counter's max value in one line like this:
constant COUNTER_MAX : INTEGER := ite(SIMULATION, 500, 50000);
Reviewing your code from above, there are some errors:
the LED is blinking at 0.5 Hz not 1 Hz (regarding your if
the duty-cycle is not 50.00000 %, because your counter is set to zero one cycle to late.
I think it's not intended that LED is synthesized as an addition Flip-Flop.

Conversion from numeric_std unsigned to std_logic_vector in vhdl

I have a question related to conversion from numeric_std to std_logic_vector. I am using moving average filter code that I saw online and filtering my ADC values to stable the values.
The filter package code is:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package filterpack is
subtype number is unsigned(27 downto 0);
type numbers is array(natural range <>) of number;
function slv_to_num(signal slv: in std_logic_vector) return number;
procedure MAF_filter(
signal x: in number;
signal h: inout numbers;
signal y: out number
);
end filterpack;
package body filterpack is
function slv_to_num(signal slv: in std_logic_vector) return number is
variable x: number := (others => '0');
begin
for i in slv'range loop
if slv(i) = '1' then
x(i+4) := '1';
end if;
end loop;
return x;
end function slv_to_num;
procedure MAF_filter(
signal x: in number;
signal h: inout numbers;
signal y: out number
) is
begin
h(0) <= x + h(1); -- h[n] = x[n] + h[n-1]
y <= h(0) - h(h'high); -- y[n] = h[n] - h[n-M]
end MAF_filter;
end package body filterpack;
In my top level file, I call the MAF_filter procedure.
Asign_x: x <= slv_to_num(adc_dat);
Filter: MAF_filter(x,h,y);
The adc_dat is defined as:
adc_dat : out std_logic_vector (23 downto 0);
I want to convert the output of the MAF_Filter to std_logic_vector (23 downto 0). Can anyone tell how can I convert filter output 'y' to 'std_logic_vector'?
Many Thanks!
What do you want to do with the 4 extra bits? Your type number has 28 bits, but your signal adc_dat has only 24.
If it's ok to discard them, you could use:
adc_dat <= std_logic_vector(y(adc_dat'range));
Also, is there a reason not to write your function slv_to_num as shown below?
function slv_to_num(signal slv: in std_logic_vector) return number is
begin
return number(slv & "0000");
end function slv_to_num;
The conversion has to solve 2 problems : the type difference you noted, and the fact that the two words are different sizes.
The type difference is easy : std_logic_vector (y) will give you the correct type. Because the two types are related types, this is just a cast.
The size difference ... only you have the knowledge to do that.
adc_dat <= std_logic_vector(y(23 downto 0)) will give you the LSBs of Y - i.e. the value of Y itself, but can overflow. Or as Rick says, adc_dat <= std_logic_vector(y(adc_dat'range)); which is usually better, but I wanted to expose the details.
adc_dat <= std_logic_vector(y(27 downto 4)) cannot overflow, but actually gives you y/16.

VHDL: Converting from floating point to fixed point explanation?

In the Designer's Guide to VHDL in Chapter 6.2 there is an entity and architecture body for a converter from floating point to fixed point representation. I'm confused by it
library ieee; use ieee.std_logic_1164 all;
entity to_fp is
port(vec: in std_u_logic_vector(15 downto 0);
r: out real);
end entity to_fp;
architecture behavioral of to_fp is
begin
behavior : process (vec) is
variable temp: bit_vector(vec'range);
variable negative: boolean;
variable int_result: integer;
begin
temp := to_bitvector(vec);
negative := temp(temp'left) = '1';
if negative then
temp := not temp;
end if;
int_result := 0;
for index in vec'range loop
int_result := int_result*2 + bit'pos(temp(index));
end loop;
if negative then
int_result := (-int_result) -1;
end if;
r <= real(int_result) / 2.0**15;
end process behavior;
end architecture behavioral;
I understand most of it. I just don't understand the for loop. How does this give us the integer representation of the bit vector? Please explain in as much detail as possible, Thanks :) .
for index in vec'range loop
This loops over the range of vec. In this case this (15 downto 0).
bit'pos(temp(index));
bit is an enumaration type (type BIT is ('0', '1'); in std.standard). The pos attribute returns the position number (as an integer type) of the given value. So bit'pos(...) converts a bit to an integer.
So what the loop does is convert a bit_vector to an integer.
I recommend using to_integer(unsigned(vec)) for this purpose, though. Remember to use ieee.numeric_std.all;.
The last line converts (casts) the integer to a real.

Resources