How to code a module that determines horizontal and vertical coordinates of the monitor in vhdl - 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;

Related

Do I need increment pwm_count variable?

I'm learning VHDL language right now and I have some problems of understanding a part of the code in my course. I don't understand in process freq_counter this statement -> if(pwm_count < max_pwm_count), because we don't know the value of max_pwm_count and also I don't see any incrementation of variable pwm_count.
Thank you, guys!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity PWM is
generic (
freq : integer := 50; --50Hz
INPUT_CLK : integer := 50000000; --50MHz
BITH_DEPTH : integer := 8
);
Port (
ENABLE : in std_logic;
CLK : in std_logic;
PWM_OUT : out std_logic;
DUTY_CYCLE : in std_logic_vector(BITH_DEPTH-1 downto 0)
);
end PWM;
architecture behavioral of PWM is
constant max_freq_count : integer:= INPUT_CLK/freq;
constant pwm_step : integer := max_freq_count/2**BITH_DEPTH;
signal PWM_value : std_logic := '0';
signal freq_count : integer range from 0 to max_freq_count := 0;
signal pwm_count : integer range from 0 to 2**BITH_DEPTH := 0;
signal max_pwm_count : integer range from 0 to 2**BITH_DEPTH := 0;
signal pwm_step_count : integer range from 0 to max_freq_count := 0;
begin
max_pwm_count <= TO_INTEGER(unsigned(DUTY_CYCLE));
PWM_OUT <= PWM_value;
freq_counter: process(CLK)
begin
if rising_edge(CLK) then
if(ENABLE='0') then
if(freq_count < max_freq_count) then
freq_count <= freq_count + 1;
if(pwm_count < max_pwm_count) then
PWM_value<='1';
if(pwm_step_count<pwm_step) then
pwm_step_count<=pwm_step_count+1;
else
pwm_step_count<=0;
pwm_count<=0;
end if;
else
pwm_value<='0';
end if;
else
freq_count <= 0;
pwm_count <= 0;
end if;
else
PWM_value <= '0';
end if;
end if;
end process freq_counter;
end PWM;
We DO know the value of max_pwm_count : it is initialised to 0 and never re-assigned. Therefore the IF can never be true and ... so on.
As far as incrementing PWM_Count is concerned, your understanding seems to be better than the author's, which puts you in a reasonable position for the necessary re-write.
I recommend first writing a testbench so you can observe its behaviour, and get it correct in simulation.

ADC to RAM signal reconstruction (after send it to VGA)

I should reconstruct a wave from the ADC into the RAM and later send it to the VGA.
I wrote this module, but when I synthesize, vivado produces an error:[Synth 8-3380] loop condition does not converge after 2000 iterations.
The error refers to the while loop, but i don't understand the reason. Unfortunately, if I can't synthezise the module i don't understand if it works well.
This is the module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use ieee.std_logic_arith.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 leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Data_Elab is
Generic (
C: integer := 640; -- Colonne 640
R: integer := 480 -- Righe 480
);
Port (
--clk: in std_logic;
DRP_Data: in std_logic_vector(15 downto 0);
DRP_Ready: in std_logic;
RAM_addr: out std_logic_vector(17 downto 0);
RAM_Data: out std_logic;
RAM_en: out std_logic
);
end Data_Elab;
architecture Behavioral of Data_Elab is
signal data_reg: integer range 0 to 2**16;
--signal flag: std_logic;
begin
process(DRP_Ready, DRP_Data)
begin
if(DRP_Ready'event and DRP_Ready = '1') then
data_reg <= to_integer(unsigned(DRP_Data));
end if;
end process;
process(data_reg)
variable Cont_W: integer range 0 to C-1 := 0; -- contatore per spostamento tra colonne
variable Cont_i: integer range 0 to C := 1; -- contatore colonne
variable Cont_x: integer range 0 to R := 1; -- contaore per spostamento tra righe
variable Cont_R: integer range 0 to R := 0; -- contatore righe
begin
if(Cont_i <= C) then
if( data_reg <= (2**16/R)*Cont_x ) then
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '1'; -- pixel corrispondente alla forma d'onda (bianchi)
Cont_W := Cont_W+1;
Cont_i := Cont_i+1;
--Cont_R := Cont_R+1;
--Cont_x := 1;
while Cont_R < R loop
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '0'; -- pixel neri
Cont_R := Cont_R+1;
Cont_x:= Cont_x+1;
end loop;
Cont_R := 0;
else
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '0'; -- pixel neri
Cont_R := Cont_R+1;
Cont_x:= Cont_x+1;
end if;
else
RAM_en<= '0';
Cont_W := 0;
Cont_i := 1;
Cont_x := 1;
Cont_R := 0;
end if;
end process;
end Behavioral;
The module tries to write the full image from 640*480 pixel in the RAM block, in this way i can read later the values stored in the RAM and send them tothe VGA module.
Thank you.
I guess the synthesizer is not smart enough to know how many times the while loop would run, because it changes in every loop. I would recommend using a for loop instead.
for Cont_R in 0 to R-1 loop
RAM_addr <= std_logic_vector(to_unsigned( (C*(R-Cont_x))+Cont_W, RAM_addr'length));
RAM_en<= '1';
RAM_Data <= '0'; -- pixel neri
Cont_x:= Cont_x+1;
end loop;

Vhdl, is there a way, to use modulo on larger than 64 bits unsigned?

I've got two 115bits unsigned vectors. I have to do some mod calculations on them, but Quartus shows those errors.
Error: In lpm_divide megafunction, LPM_WIDTHN must be less than or equals to 64
Error: In lpm_divide megafunction, LPM_WIDTHD must be less than or equal to 64
Error: Can't elaborate inferred hierarchy "lpm_divide:Mod0"
I fully understand, that numbers are too large to perform mod. Is there a way/library/any idea how to solve this problem? I would love to avoid using any "substracting loop", and be as simple as possible. VHDL is not my world, and after academic project I will abandon it with pleasure :P
Application has to calculate modulo inversion. As far as I am not master from VHDL, I've tried doing it using fast powering + mod alghoritm. Application can sucks, it just has to work :d
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
library altera;
use altera.altera_primitives_components.all;
entity inwersja is
port(
a: in unsigned(114 downto 0);
clk: in std_logic;
start: in std_logic;
reset: in std_logic;
c: out unsigned(114 downto 0);
ready: out std_logic);
end inwersja;
architecture i1 of inwersja is
begin
process(clk)
variable tempOutput : unsigned(114 downto 0) := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
variable temp : unsigned (114 downto 0):= a;
variable modul: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101011";
variable power: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101001";
variable counter: integer := 0;
begin
if reset='1' then
tempOutput := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
ready <= '0';
elsif clk'event and clk='1' then
if start='0' then
ready<='0';
else
if (counter < 115) then
if (power(counter) /= '0') then
tempOutput := (tempOutput * temp) mod modul;
end if;
temp := (temp * temp) mod modul;
counter := counter + 1;
elsif (counter = 115) then
ready <= '1';
end if;
end if;
end if;
c <= tempOutput;
end process;
end i1;

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;

Unsigned VHDL conversion not working

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.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 fourToSixteenDecoder is
port ( a : in std_logic_vector(0 to 3);
EN : in STD_LOGIC;
Y : out std_logic_vector(0 to 15));
end fourToSixteenDecoder;
architecture Behavioral of fourToSixteenDecoder is
begin
process(a, EN)
variable inputs : integer := conv_integer(unsigned(a));
variable Y_c : std_logic_vector(0 to 15);
begin
Y_c := X"0000";
if (EN = '1') then
Y_c(inputs) := '1';
elsif (EN = '0') then
Y_c := X"0000";
end if;
Y <= Y_c;
end process;
end Behavioral;
Trying to make a 4-16 Decoder, however, I am trying to use conversion between integer and SLV to do bit indexing assignment, but the conversion does not work.
ERROR:HDLCompiler:806 - "..." Line 40: Syntax error near "b".
Also tried
to_integer(unsigned())
integer(unsigned())
integer(to_unsigned())
to_integer(to_unsigned())
use IEEE.ARITH and IEEE.STD_LOGIC.UNSIGNED
No solution.
The conversion routine is call to_integer in package numeric_std, and for an unsigned produces a natural range integer.
With variable inputs : integer := to_integer(unsigned(a)); inputs would be initialized to the initial value of a converted to an integer (likely 0 if a is uninitialized (all 'U's).
There is no other assignment to inputs and inputs wouldn't change with a value changes.
Replace the variable inputs declaration with
variable inputs: integer range 0 to 15;
which restricts the range of inputs to the index range of Y_c.
Add
inputs := to_integer(unsigned(a));
as a first sequential statement to the process.
The two assignments:
Y_c := X"0000";
are redundant. The elsif can be eliminated:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fourToSixteenDecoder is
port (
a: in std_logic_vector(0 to 3);
EN: in std_logic;
Y: out std_logic_vector(0 to 15)
);
end entity fourToSixteenDecoder;
architecture Behavioral of fourToSixteenDecoder is
begin
process(a, EN)
-- variable inputs : integer := conv_integer(unsigned(a));
variable inputs: integer range 0 to 15;
variable Y_c: std_logic_vector(0 to 15);
begin
inputs := to_integer(unsigned(a)); -- ADDED
Y_c := X"0000";
if EN = '1' then
Y_c(inputs) := '1';
-- elsif (EN = '0') then
-- Y_c := X"0000";
end if;
Y <= Y_c;
end process;
end architecture Behavioral;
This analyzes, elaborates and simulates. Notice the parentheses around the if statement conditions aren't needed.
A testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_4to16 is
end entity;
architecture fum of tb_4to16 is
signal a: std_logic_vector (0 to 3) := (others => '0');
signal EN: std_logic;
signal Y: std_logic_vector(0 to 15);
begin
DUT:
entity work.fourtosixteendecoder
port map (
a => a,
EN => EN,
Y => Y
);
STIMULI:
process
begin
for i in 0 to 15 loop
EN <= '0';
a <= std_logic_vector(to_unsigned(i,4));
wait for 10 ns;
EN <='1';
wait for 10 ns;
end loop;
EN <= '0';
wait for 10 ns;
wait;
end process;
end architecture;
The results:

Resources