VHDL - Quartus II modsim - vhdl

I'm starting to write a VGA controller for a DE0 board. I have a model which compiles and loads onto the DE0 board. Also it displays the test message. The problem I am having is I cannot simulate my controller using Quartus II modsim. When I run the simulation I cannot start the VGA file. The little plus icon is missing from the file. A picture and the models file I am using are below:
vga model
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY VGA is
PORT (clk : IN std_logic; -- demo had 2 bit vector
rst : IN std_logic:='1';
vga_hs, vga_vs : OUT std_logic;
vga_r, vga_g, vga_b : OUT std_logic_vector(3 DOWNTO 0));
END ENTITY VGA;
ARCHITECTURE A1 OF VGA IS
SIGNAL clk25 : std_logic; -- clk25 signal
BEGIN
SYNC1 : ENTITY work.sync(A1)
PORT MAP (clk25, vga_hs, vga_vs, vga_r, vga_g, vga_b);
CLK_25 : ENTITY work.CLK25(behav)
PORT MAP (clk, rst, clk25);
END ARCHITECTURE A1;
Sync model
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY SYNC IS
GENERIC (
h_res : integer:= 640 ; -- horizontal screen resolution
h_fp : integer:= 16 ; -- horizontal front porch
h_bp : integer:= 48 ; -- horizontal back porch
h_sync : integer:= 96 ; -- horizontal sync pulse duration
h_sync_pol : std_logic:='0'; -- horizontal sync pulse state
v_res : integer:= 480 ; -- vertical screen resolution
v_fp : integer:= 10 ; -- vertical front porch
v_bp : integer:= 33 ; -- vertical back porch
v_sync : integer:= 2; -- vertical sync pulse duration
v_sync_pol : std_logic:='0' -- vertical sync pulse state
);
PORT(
clk : IN std_logic;
h_sync_pulse, v_sync_pulse : OUT std_logic;
r, g, b : OUT std_logic_vector(3 DOWNTO 0)
);
END ENTITY SYNC;
ARCHITECTURE A1 OF SYNC IS
CONSTANT h_size : integer := (h_res + h_fp + h_bp + h_sync); -- total horizontal vector
CONSTANT v_size : integer := (v_res + v_fp + v_bp + v_sync); -- total vertical vector
SIGNAL h_pos : integer RANGE 0 TO h_size := 0; -- total horizontal vector
SIGNAL v_pos : integer RANGE 0 TO h_size := 0; -- total vertical vector
BEGIN
TIMING :PROCESS(clk, h_pos, v_pos) IS
BEGIN
IF rising_edge(clk) THEN
IF (h_pos <= 480 or v_pos <= 285) THEN -- middle of the screen is pic res/2 + (FP + sync + BP)
r <= (OTHERS => '1');
g <= (OTHERS => '1');
b <= (OTHERS => '1');
ELSE
r <= (OTHERS => '0');
g <= (OTHERS => '0');
b <= (OTHERS => '0');
END IF;
IF (h_pos <= 480 or v_pos <= 285) THEN -- middle of the screen is pic res/2 + (FP + sync + BP)
r <= (OTHERS => '1');
g <= (OTHERS => '1');
b <= (OTHERS => '1');
ELSE
r <= (OTHERS => '0');
g <= (OTHERS => '0');
b <= (OTHERS => '0');
END IF;
IF (h_pos < h_size) THEN
h_pos <= h_pos + 1;
ELSE
h_pos <= 0;
IF (v_pos < v_size) THEN
v_pos <= v_pos + 1;
ELSE
v_pos <= 0; --< edit was v_pos <= v_pos
END IF;
END IF;
IF (h_pos > h_fp and h_pos < h_fp + h_sync ) THEN -- H_POS between end of FP and the end of H_SYNC
h_sync_pulse <= h_sync_pol; -- H_SYNC needs to stay high during display
ELSE
h_sync_pulse <= '1';
END IF;
IF (v_pos > v_fp and v_pos < v_fp + v_sync ) THEN --V_POS between end of FP and the end of V_SYNC
v_sync_pulse <= v_sync_pol; -- V_SYNC needs to stay high during display
ELSE
v_sync_pulse <= '1';
END IF;
IF ((h_pos > 0 and h_pos < h_fp + h_bp + h_sync) or (v_pos > 0 and v_pos < v_fp + v_bp + v_sync )) THEN --During all of SYNC i.e FP + SYNC + BP colour signals stay low
r <= (OTHERS => '0');
g <= (OTHERS => '0');
b <= (OTHERS => '0');
END IF;
END IF;
END PROCESS TIMING;
END ARCHITECTURE A1;
The design units after compilation do not show the architectures for either the vga.vhd or the sync.vhd files

Related

Trying to display on 640x480 vga display with fpga

I am literally writing this in desperation. i've tried some many times to make it work and it just doesn't.
im using Altera DE2 board - Cyclone II EP2C35F672C6 & been trying to display simple image on 640x480 vga screen.
im using a vga controller design i made for a different board- Altera DE1 which worked really good.
the difference on this DE2 board is a different DAC component which has 10bit rgb data instead of 4bit like in the DE1 board, and it has extra needed ouputs - VGA_SYNC, VGA_BLANK, VGA_CLK.
So i made the needed changes & found an example where it says to set VGA_BLANK to '1' constant and VGA_SYNC to '0'. VGA_CLK is connected to the 25.175 Mhz pixel clk which is the pll clk output.
i've tried so many variations & tried to use another example where they set vga_blank to '1' when in visable aread & '0' when not and it still didnt work. i just get a black screen saying no video input when i run the design.
below is the implementation of my timing generator, data_generator & vga_top_level
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.vga_consts.all;
entity vga_toplevel is
port
(
-- in --
clk, rst : in std_logic;
-- out --
vga_clk, vga_blank, vga_sync : out std_logic;
r_data, g_data, b_data : out std_logic_vector(9 downto 0);
h_sync, v_sync : out std_logic
);
end entity;
architecture structural of vga_toplevel is
component pll
port
(
areset : IN STD_LOGIC := '0';
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
locked : OUT STD_LOGIC
);
end component;
component timing_generator
port
(
clk, rst : in std_logic;
h_cnt : out integer range 0 to h_frame-1;
v_cnt : out integer range 0 to v_frame-1;
vga_blank, vga_sync : out std_logic;
h_sync, v_sync : out std_logic
);
end component;
component data_generator
generic
(
vis_x : integer := visable_x;
vis_y : integer := visable_y
);
port
(
clk, rst : in std_logic;
h_cnt : in integer range 0 to h_frame-1;
v_cnt : in integer range 0 to v_frame-1;
-- RGB values
r_data, g_data, b_data : out std_logic_vector(9 downto 0)
);
end component;
signal h_cnt, v_cnt : integer range 0 to h_frame-1;
signal pll_clk, rst_out, locked : std_logic;
-------------------------------------------------------------------
begin
rst_out <= not locked; -- uncomment for PLL use
vga_clk <= pll_clk;
-- rst_out <= rst; -- comment for PLL use
-- pll_clk <= clk; -- comment for PLL use
PLL1: pll
port map
(
inclk0 => clk,
areset => rst,
c0 => pll_clk,
locked => locked
);
T_GEN: timing_generator
port map
(
-- in --
clk => pll_clk,
rst => rst_out,
-- out --
vga_blank => vga_blank,
vga_sync => vga_sync,
v_cnt => v_cnt,
h_cnt => h_cnt,
v_sync => v_sync,
h_sync => h_sync
);
D_GEN: data_generator
port map
(
-- in --
clk => pll_clk,
rst => rst_out,
v_cnt => v_cnt,
h_cnt => h_cnt,
r_data => r_data,
g_data => g_data,
b_data => b_data
);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.vga_consts.all;
entity timing_generator is
port
(
clk, rst : in std_logic;
h_cnt : out integer range 0 to h_frame-1;
v_cnt : out integer range 0 to v_frame-1;
vga_blank : out std_logic;
vga_sync : out std_logic;
h_sync, v_sync : out std_logic
);
end entity;
architecture behave of timing_generator is
signal h_cnt_inner : integer range 0 to h_frame-1;
signal v_cnt_inner : integer range 0 to v_frame-1;
begin
vga_blank <= '1';
vga_sync <= '0';
h_cnt <= h_cnt_inner;
v_cnt <= v_cnt_inner;
-- counter for pixels --
process (clk, rst)
begin
if rst = '1' then
h_cnt_inner <= 0;
elsif rising_edge(clk) then
if h_cnt_inner = h_frame-1 then
h_cnt_inner <= 0;
else
h_cnt_inner <= h_cnt_inner + 1;
end if;
end if;
end process;
-- counter for lines --
process (clk, rst)
begin
if rst = '1' then
v_cnt_inner <= 0;
elsif rising_edge(clk) then
if v_cnt_inner = v_frame-1 then
v_cnt_inner <= 0;
elsif h_cnt_inner = 654 then
v_cnt_inner <= v_cnt_inner + 1;
end if;
end if;
end process;
-- h_sync generator --
process (clk, rst)
begin
if rst = '1' then
h_sync <= '1';
elsif rising_edge(clk) then
if h_cnt_inner = h_sync_d(0)-1 then
h_sync <= '0';
elsif h_cnt_inner = h_sync_d(1) then
h_sync <= '1';
end if;
end if;
end process;
-- v_sync generator --
process(clk, rst)
begin
if rst = '1' then
v_sync <= '1';
elsif rising_edge(clk) then
if v_cnt_inner = v_sync_d(0) then
v_sync <= '0';
elsif v_cnt_inner = v_sync_d(1) + 1 then
v_sync <= '1';
end if;
end if;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.vga_consts.all;
entity data_generator is
generic (
vis_x : integer := visable_x;
vis_y : integer := visable_y
);
port
(
clk, rst : in std_logic;
h_cnt : in integer range 0 to h_frame-1;
v_cnt : in integer range 0 to v_frame-1;
-- RGB values for each pixel
r_data, g_data, b_data : out std_logic_vector(9 downto 0)
);
end entity;
architecture behave of data_generator is
begin
-- process to handle only 1 color - blue screen
process(clk, rst)
begin
if rst = '1' then
r_data <= (others => '0');
g_data <= (others => '0');
b_data <= (others => '0');
elsif rising_edge(clk) then
if (h_cnt >= h_vis_d(0)) and (h_cnt < h_vis_d(1)) and (v_cnt >= v_vis_d(0)) and (v_cnt < v_vis_d(1)) then
-- if in visiable area
r_data <= (others => '1');
g_data <= (others => '1');
b_data <= (others => '1');
else
r_data <= (others => '0');
g_data <= (others => '0');
b_data <= (others => '0');
end if;
end if;
end process;
end architecture;

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.

PWM controlled LED using VHDL

I've written the following VHDL code and test-bench to control the brightness of LEDs. Then tried with Altera ModelSim to simulate the code. However, I'm facing some technical difficulties. It would be really nice if someone will compile the code and share me the simulated result with me. Thanks in advance.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity main_testbench is
end main_testbench;
architecture behavior of main_testbench is
component led_controller is
Port ( clk, reset: in std_logic; -- system clock is assumed 10KHz
in_word: in std_logic_vector(7 downto 0); -- LS 4 bits - frequency & MS 4 bits - duty-cycle
LEDs: out std_logic_vector(3 downto 0));
end component;
signal clk, reset: std_logic := '0';
signal in_word: std_logic_vector(7 downto 0) := "00010001"; -- 0.2 Hz, 10% duty cycle
signal LEDs: std_logic_vector(3 downto 0) := "0000";
type in_word_commands is array (0 to 15) of std_logic_vector(7 downto 0);
signal in_words: in_word_commands := ("00010001", "00010010", "00010100", "00011000", -- 10% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"00100001", "00100010", "00100100", "00101000", -- 30% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"01000001", "01000010", "01000100", "01001000", -- 60% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
"10000001", "10000010", "10000100", "10001000"); -- 85% duty cycle with 0.2Hz, 0.5Hz, 1Hz, 2Hz
signal command_num : integer := 0;
begin
dut: led_controller port map (clk, reset, in_word, LEDs);
clk <= not clk after 50 us; -- 0.1ms/2 = 50us
command_num <= command_num + 1 after 5000 ms; -- 5000ms = 5s
in_word <= in_words(command_num);
end behavior;
controller:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
entity led_controller is
Port ( clk, reset: in std_logic;
in_word: in std_logic_vector(7 downto 0);
LEDs: out std_logic_vector(3 downto 0));
end led_controller;
architecture behavior of led_controller is
--------------------- signals ---------------------
type freq is array (0 to 3) of integer range 0 to 50000;
signal frq: freq := (25000, 10000, 5000, 2500);
signal led_freq_count: integer range 0 to 50000 := frq(0);
type d is array (0 to 3) of integer range 0 to 100;
signal duty: d := (10, 30, 60, 85);
signal duty_cycle: integer range 0 to 100 := duty(0);
signal LED_switch, new_command: std_logic := '0';
begin
--------- clock process / sync reset configuration ---------------
process (clk)
variable duty_counter: integer range 0 to 100 := 100;
variable freq_counter: integer range 0 to 50000 := led_freq_count;
begin
if rising_edge(clk) then
------- if reset was high or new in_word were arrived --------
if reset = '1' or new_command = '1' then
LEDs <= "0000";
duty_counter := 100;
freq_counter := led_freq_count;
new_command <= '0';
else
------- blinking process --------
if freq_counter = 0 then
freq_counter := led_freq_count;
LED_switch <= not LED_switch;
end if;
freq_counter := freq_counter - 1;
if duty_counter = 0 then
duty_counter := 100;
end if;
duty_counter := duty_counter - 1;
------ output assignment -------
if LED_switch = '1' and duty_counter < duty_cycle then
LEDs <= "1111";
else
LEDs <= "0000";
end if;
end if;
end if;
end process;
--------- input process---------------
process (in_word)
begin
case in_word(3 downto 0) is
when "0001" => led_freq_count <= frq(0);
when "0010" => led_freq_count <= frq(1);
when "0100" => led_freq_count <= frq(2);
when "1000" => led_freq_count <= frq(3);
when others => led_freq_count <= frq(0);
end case;
case in_word(7 downto 4) is
when "0001" => duty_cycle <= duty(0);
when "0010" => duty_cycle <= duty(1);
when "0100" => duty_cycle <= duty(2);
when "1000" => duty_cycle <= duty(3);
when others => duty_cycle <= duty(0);
end case;
new_command <= '1';
end process;
end behavior;
if freq_counter = 0 then
freq_counter := led_freq_count;
LED_switch <= not LED_switch;
else
freq_counter := freq_counter - 1;
end if;
if duty_counter = 0 then
duty_counter := 100;
else
duty_counter := duty_counter - 1;
end if;

VHDL VGA interface

I've been modelling a VGA interface on the DE0 board. I have the following model for a 640x480 display which refreshes at 60Hz:
Main model:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY VGA is
PORT (clk : IN std_logic; -- demo had 2 bit vector
vga_hs, vga_vs : OUT std_logic;
vga_r, vga_g, vga_b : OUT std_logic_vector(3 DOWNTO 0));
END ENTITY VGA;
ARCHITECTURE A1 OF VGA IS
SIGNAL rst, clk25 : std_logic; -- rst only resets pixel clock
BEGIN
SYNC1 : ENTITY work.sync(A1)
PORT MAP (clk25, vga_hs, vga_vs, vga_r, vga_g, vga_b);
CLK_25 : ENTITY work.PLL(rtl)
PORT MAP (clk, rst, clk25);
END ARCHITECTURE A1;
Sync model:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY SYNC IS
PORT(
clk : IN std_logic;
h_sync, v_sync : OUT std_logic;
r, g, b : OUT std_logic_vector(3 DOWNTO 0)
);
END ENTITY SYNC;
ARCHITECTURE A1 OF SYNC IS
SIGNAL h_pos: integer RANGE 0 TO 800:=0;
SIGNAL v_pos : integer RANGE 0 TO 520:=0;
BEGIN
TIMING :PROCESS(clk) IS
BEGIN
IF rising_edge(clk) THEN
IF (h_pos = 480 or v_pos = 280) THEN -- middle of the screen is pic res/2 + (FP + sync + BP)
r <= (OTHERS => '1');
g <= (OTHERS => '1');
b <= (OTHERS => '1');
ELSE
r <= (OTHERS => '0');
g <= (OTHERS => '0');
b <= (OTHERS => '0');
END IF;
IF (h_pos < 800) THEN
h_pos <= h_pos + 1;
ELSE
h_pos <= 1;
IF (v_pos < 520) THEN
v_pos <= v_pos + 1;
ELSE
v_pos <= 1;
END IF;
END IF;
IF (h_pos > 16 and h_pos < 112 ) THEN -- H_POS between end of FP and the end of H_SYNC
h_sync <= '0'; -- H_SYNC needs to stay low during display
ELSE
h_sync <= '1';
END IF;
IF (v_pos > 8 and v_pos < 10 ) THEN --V_POS between end of FP and the end of V_SYNC
v_sync <= '0'; -- V_SYNC needs to stay low during display
ELSE
v_sync <= '1';
END IF;
IF ((h_pos > 0 and h_pos < 160) or (v_pos > 0 and v_pos < 40 )) THEN--During all of SYNC i.e FP + SYNC + BP colour signals stay low
r <= (OTHERS => '0');
g <= (OTHERS => '0');
b <= (OTHERS => '0');
END IF;
END IF;
END PROCESS TIMING;
END ARCHITECTURE A1;
----------Amendments made to model 09/02 13:42----------
The other direct instantiation is for PLL generated from Quartus II it seems to work fine.. thank you Mr Zilmer :). The model compiles fine. I load it into the DE0. Then connect this to a monitor and get nothing on the display. It should display a cross in the centre of the screen. The display I am using is a Samsung with 1920x1080. Would this stop my model from displaying anything? Or have I made a obvious mistake in my model. I have changed some of the standard timing values to fit a 60Hz refresh with 25Mz clk.
Thanks
D
Your VHDL code for entity sync doesn't analyze. You are missing an end if and your initial values for h_sync and v_sync violate the subtype constraint:
signal h_pos: integer range 1 to 800 := 0;
signal v_pos: integer range 1 to 520 := 0;
Where 0 is outside the bounds of 1 to 800 or 1 to 520.
This raises the question of whether or not you have another architecture for entity sync, or whether sync is simply unbound. Either of which might give you an incorrect indication (and the error isn't demonstrated in your question).
We can use a testbench to demonstrate what sync does in simulation with a 25 MHz clock:
library ieee;
use ieee.std_logic_1164.all;
--use ieee.numeric_std.all;
entity sync is
port (
clk: in std_logic;
h_sync, v_sync: out std_logic;
r, g, b: out std_logic_vector(3 downto 0)
);
end entity sync;
architecture a1 of sync is
signal h_pos: integer range 1 to 800 := 1; -- was := 0;
signal v_pos: integer range 1 to 520 := 1; -- was := 0;
begin
timing:
process (clk) is
begin
if rising_edge(clk) then
if h_pos = 480 or v_pos = 280 then -- middle of the screen
r <= (others => '1');
g <= (others => '1');
b <= (others => '1');
else
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
if h_pos < 800 then
h_pos <= h_pos + 1;
else
h_pos <= 1;
if v_pos < 520 then
v_pos <= v_pos + 1;
else
v_pos <= 1;
end if;
if h_pos > 16 and h_pos < 112 then
h_sync <= '0'; -- h_sync low during display
else
h_sync <= '1';
end if;
if v_pos > 8 and v_pos < 10 then
v_sync <= '0'; -- v_sync low during display
else
v_sync <= '1';
end if;
if (h_pos > 1 and h_pos < 160) or
(v_pos > 1 and v_pos < 40 ) then -- black during blanking
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
end if;
end if; -- added misssing end if
end process timing;
end architecture a1;
library ieee;
use ieee.std_logic_1164.all;
entity sync_tb is
end entity;
architecture foo of sync_tb is
signal clk: std_logic := '0';
signal h_sync: std_logic;
signal v_sync: std_logic;
signal r, g, b: std_logic_vector (3 downto 0);
begin
DUT:
entity work.sync
port map (
clk => clk,
h_sync => h_sync,
v_sync => v_sync,
r => r,
g => g,
b => b
);
CLOCK:
process
begin
wait for 20 ns; -- clock period 25 MHz = 40 ns;
clk <= not clk;
if now > 20 ms then -- one frame time plus a bit
wait;
end if;
end process;
end architecture;
And now we get to troubleshoot:
The first thing we notice is h_sync is wrong. Also note that v_sync appears to be around 16.667 ms (1/60th of a second).
We can add the h_pos and v_pos counters so we can look at h_sync, we do know the h_pos counter is running to get a v_sync we can see in the right neighborhood of 60 Hz.
So I picked the wrong place to add the end if. Correcting that also separates operating the counters from operating on their outputs (h_sync, v_sync and r,g,b).
timing:
process (clk) is
begin
if rising_edge(clk) then
if h_pos = 480 or v_pos = 280 then -- middle of the screen
r <= (others => '1');
g <= (others => '1');
b <= (others => '1');
else
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
if h_pos < 800 then
h_pos <= h_pos + 1;
else
h_pos <= 1;
if v_pos < 520 then
v_pos <= v_pos + 1;
else
v_pos <= 1;
end if;
end if; -- separate the counters for what they produce
-- HSYNC
if h_pos > 16 and h_pos < 112 then
h_sync <= '0'; -- h_sync low during display
else
h_sync <= '1';
end if;
-- VSYNC
if v_pos > 8 and v_pos < 10 then
v_sync <= '0'; -- v_sync low during display
else
v_sync <= '1';
end if;
-- BLANKING
if (h_pos > 1 and h_pos < 160) or
(v_pos > 1 and v_pos < 40 ) then
r <= (others => '0');
g <= (others => '0');
b <= (others => '0');
end if;
end if;
end process timing;
We have h_sync now:
Notice we can see the vertical blanking interval now too.
Zooming in we can see there a horizontal white line at v_pos 280:
Along with a vertical line at h_pos 480 (+1):
And this looks like it just might work.
The only design change I might be tempted to make would be to start the visible portion of the line at h_pos = 0 and the the visible portion of the frame at v_pos = 0. This would allow something else to address pixels for writing in a frame buffer without adding additional pixel counters or having to do offset arithmetic. (Pixel addressing usually starts at 0 for x and y axis).

UART Receiver Testbench

I am new to VHDL, and I trying to verify UART receiver how is it works.
I synthesized the code below (quoted form the book) and its fine but if needs more let me know :).
The frequency for my board is 100 Mhz and the data I want receive is 8 bits, baud rate is 115200, how the clock and tick should be in the testbench or what is the right testbench here?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity uart_rx is
generic(
data_bits: integer := 8; -- # d a t a b i t s
stop_bit_ticks: integer := 16 -- # t i c k s f o r s t o p b i t s
);
Port ( rx : in STD_LOGIC;
clk : in STD_LOGIC;
reset: in STD_LOGIC;
tick : in STD_LOGIC;
rx_done : out STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end uart_rx;
architecture arch of uart_rx is
type state_type is (idle, start, data, stop);
SIGNAL state_reg, state_next: state_type;
SIGNAL s_reg, s_next: UNSIGNED(3 downto 0);
SIGNAL n_reg, n_next: UNSIGNED(2 downto 0);
SIGNAL b_reg, b_next: STD_LOGIC_VECTOR(7 downto 0);
begin
-- FSMD s t a t e & d a t a r e g i s t e r s
process(clk, reset) -- FSMD state and data regs.
begin
if (reset = '1') then
state_reg <= idle;
s_reg <= (others => '0');
n_reg <= (others => '0');
b_reg <= (others => '0');
--rx_done <= '0';
-- rx <= '1';
elsif (clk'event and clk='1') then
state_reg <= state_next;
s_reg <= s_next;
n_reg <= n_next;
b_reg <= b_next;
end if;
end process;
-- n e x t - s t a t e l o g i c & d a t a p a t h f u n c t i o n a l u n i t s / r o u t i n g
process (state_reg, s_reg, n_reg, b_reg, tick, rx)
begin
state_next <= state_reg;
s_next <= s_reg;
n_next <= n_reg;
b_next <= b_reg;
rx_done <= '0';
case state_reg is
when idle =>
if (rx = '0') then
state_next <= start;
s_next <= (others => '0');
end if;
when start =>
if (tick = '1') then
if (s_reg = 7) then
state_next <= data;
s_next <= (others => '0');
n_next <= (others => '0');
else
s_next <= s_reg + 1;
end if;
end if;
when data =>
if (tick = '1') then
if (s_reg = 15) then
s_next <= (others => '0');
b_next <= rx & b_reg(7 downto 1);
if (n_reg = (data_bits - 1)) then
state_next <= stop;
else
n_next <= n_reg + 1;
end if;
else
s_next <= s_reg + 1;
end if;
end if;
when stop =>
if (tick = '1') then
if (s_reg = (stop_bit_ticks - 1)) then
state_next <= idle;
rx_done <= '1';
else
s_next <= s_reg + 1;
end if;
end if;
end case;
end process;
data_out <= b_reg;
end arch;
Typically, UART receivers run at 8 times the bit rate. If your bit rate is 115200, this means a sample rate of 921600. If you are running at 100Mzh, you will need to create a clock divider to get you from 100 MHz to the desired sample rate. To go from 921600 to 100 MHz the following will work:
100 MHz = 100,000,000 Hz
921600 samples/sec = 921,600 Hz
divider = 100,000,000/921,600 = 108.51.
Thus, you will need a counter that will count up to 109 (we round up as we have to sample at an integer of the clock rate) on rising_edge(clock), then raise an enable signal that tells your component its time to sample the line and reset the counter. The example above assumed 8 samples/bit which is typical to my knowledge. Thus, if you set the period of your main clock in the simulation to be 1ns and set up the counter circuit I described above, you should get the test bench you are looking for.
EDIT: warning about uneven clock division
Almost forgot to mention this. Since your clock rate does not divide evenly into the bit rate for the UART, some extra care must be taken when coding up this circuit. Your sample rate will move later and later in the transmission with the scheme I have proposed. You will probably have to add a simple offset to change your counter to 108 on the even bits to keep you more aligned with the incoming data bits.
See here for some more info: https://electronics.stackexchange.com/questions/42236/uart-receiver-clock-speed

Resources