Cant display a static image through VGA using handel-c and VHDL - vhdl
Hi I am having problem to display a static image using handel-c create a test pattern through the DE2-115 VGA.
For some reason I can't output the image to the monitor.
This is my tpad.hcc code:
#include "tpad.hch"
macro proc lcd_driver( lcd ) {
unsigned 24 colour;
unsigned 1 de;
interface bus_out() tpad_RGB( unsigned 24 clr = colour )
//Post pin for RGB color
//with {data = {"V27","U28","U27","R28","R27","V26",
//"T22","T21","R23","R22","R21","P21",
//"J26","L28","V25","V22","U22","V28"},
with {data = {"D12","D11","C12","A11","B11","C11","A10","B10", //BLUE
"C9","F10","B8","C8","H12","F8","G11","G8", //GREEN
"H10","H8","J12","G10","F12","D10","E11","E12"}, //RED
standard = "LVCMOS33"};
interface bus_out() tpad_control( unsigned 3 ctrl = (!__clock) # 1 #de)
with {data = {"C13","F11","A12", "G13","C10"},
standard = "LVCMOS33"};
//VHDL driver
//entity vga_controller is
//port (
// pixel_clk : IN STD_LOGIC; --pixel clock at frequency of VGA mode being used
// reset_n : IN STD_LOGIC; --active low asycnchronous reset
// h_sync : OUT STD_LOGIC; --horiztonal sync pulse
// v_sync : OUT STD_LOGIC; --vertical sync pulse
// disp_ena : OUT STD_LOGIC; --display enable ('1' = display time, '0' = blanking time)
// column : OUT INTEGER; --horizontal pixel coordinate
// row : OUT INTEGER; --vertical pixel coordinate
// n_blank : OUT STD_LOGIC; --direct blacking output to DAC
// n_sync : OUT STD_LOGIC --sync-on-green output to DAC
// );
//END vga_controller;
interface vga_controller( unsigned 11 row, unsigned 11 column, unsigned 1 disp_ena,
unsigned 1 h_sync, unsigned 1 v_sync, unsigned 1 n_sync,
unsigned 1 n_blank)
tpad_lcd( unsigned 1 pixel_clk = __clock, unsigned 1 reset_n = 0)
with {busformat = "B[I]"};
do par {
colour = lcd.r # lcd.g # lcd.b; // Synchronise LCD output signals
//de = !lcd.nb;
de = 1;
lcd.x = tpad_lcd.row;
lcd.y = tpad_lcd.column;
lcd.hs = tpad_lcd.h_sync;
lcd.vs = tpad_lcd.v_sync;
lcd.ns = tpad_lcd.n_sync;
lcd.nb = tpad_lcd.n_blank;
lcd.de = 1;
} while (1);
}
my tpad.hch:
typedef struct {
signal unsigned 11 x, y; // Position on display
signal unsigned 8 r, g, b; // Colour to display
signal unsigned 1 hs, vs, ns, nb, de; // syncronisation signals
} lcd_data;
macro proc lcd_driver( lcd );
This is my demo.hcc:
#include "tpad.hch"
set family = AlteraCycloneIII; /* Really a Cyclone IV */
set part = "EP4CE115F29C7";
interface bus_in (unsigned 1 pin) clock_pin () with {data = {"Y2"}};
interface altpll (unsigned 5 clk with {clockport = 1})
pll (unsigned 2 inclk = 0 # clock_pin.pin)
with {
busformat = "B[N:0]",
properties = {
{"bandwidth_type", "AUTO"},
{"clk0_divide_by", "5"},
{"clk0_duty_cycle", "50"},
{"clk0_multiply_by", "4"},
{"clk0_phase_shift", "0"},
{"compensate_clock", "CLK0"},
{"inclk0_input_frequency", "20000"},
{"intended_device_family", "Cyclone IV E"},
{"lpm_hint", "CBX_MODULE_PREFIX=pll"},
{"lpm_type", "altpll"},
{"operation_mode", "NORMAL"},
{"pll_type", "AUTO"},
{"port_clk0", "PORT_USED"},
{"width_clock", "5"}},
bind = 1};
set clock = internal pll.clk[0];
void main( void ) {
lcd_data lcd;
par {
lcd_driver( lcd );
do par {
lcd.r = lcd.x[7:0]; // Generate a simple test pattern
lcd.g = lcd.y[7:0];
lcd.b = (lcd.x + lcd.y)[9:2];
} while (1);
}
}
This is my VHDL code:
--------------------------------------------------------------------------------
--
-- FileName: vga_controller.vhd
-- Dependencies: none
-- Design Software: Quartus II 64-bit Version 12.1 Build 177 SJ Full Version
--
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
--
-- Version History
-- Version 1.0 05/10/2013 Scott Larson
-- Initial Public Release
--
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY vga_controller IS
GENERIC(
h_pulse : INTEGER := 128; --horiztonal sync pulse width in pixels
h_bp : INTEGER := 88; --horiztonal back porch width in pixels
h_pixels : INTEGER := 800; --horiztonal display width in pixels
h_fp : INTEGER := 40; --horiztonal front porch width in pixels
h_pol : STD_LOGIC := '1'; --horizontal sync pulse polarity (1 = positive, 0 = negative)
v_pulse : INTEGER := 4; --vertical sync pulse width in rows
v_bp : INTEGER := 23; --vertical back porch width in rows
v_pixels : INTEGER := 600; --vertical display width in rows
v_fp : INTEGER := 1; --vertical front porch width in rows
v_pol : STD_LOGIC := '1'); --vertical sync pulse polarity (1 = positive, 0 = negative)
PORT(
pixel_clk : IN STD_LOGIC; --pixel clock at frequency of VGA mode being used
reset_n : IN STD_LOGIC; --active low asycnchronous reset
h_sync : OUT STD_LOGIC; --horiztonal sync pulse
v_sync : OUT STD_LOGIC; --vertical sync pulse
disp_ena : OUT STD_LOGIC; --display enable ('1' = display time, '0' = blanking time)
column : OUT STD_LOGIC_vector (10 downto 0); --horizontal pixel coordinate
row : OUT STD_LOGIC_vector (10 downto 0); --vertical pixel coordinate
n_blank : OUT STD_LOGIC; --direct blacking output to DAC
n_sync : OUT STD_LOGIC); --sync-on-green output to DAC
END vga_controller;
ARCHITECTURE behavior OF vga_controller IS
CONSTANT h_period : INTEGER := h_pulse + h_bp + h_pixels + h_fp; --total number of pixel clocks in a row
CONSTANT v_period : INTEGER := v_pulse + v_bp + v_pixels + v_fp; --total number of rows in column
BEGIN
n_blank <= '1'; --no direct blanking
n_sync <= '0'; --no sync on green
PROCESS(pixel_clk, reset_n)
VARIABLE h_count : INTEGER RANGE 0 TO h_period - 1 := 0; --horizontal counter (counts the columns)
VARIABLE v_count : INTEGER RANGE 0 TO v_period - 1 := 0; --vertical counter (counts the rows)
--VARIABLE h_count : unsigned (7 downto 0) := "00000000";
--VARIABLE v_count : unsigned (7 downto 0) := "00000000";
BEGIN
IF(reset_n = '0') THEN --reset asserted
h_count := 0; --reset horizontal counter
v_count := 0; --reset vertical counter
h_sync <= NOT h_pol; --deassert horizontal sync
v_sync <= NOT v_pol; --deassert vertical sync
disp_ena <= '0'; --disable display
column <= "00000000000"; --reset column pixel coordinate
row <= "00000000000"; --reset row pixel coordinate
ELSIF(pixel_clk'EVENT AND pixel_clk = '1') THEN
--counters
IF(h_count < h_period - 1) THEN --horizontal counter (pixels)
h_count := h_count + 1;
ELSE
h_count := 0;
IF(v_count < v_period - 1) THEN --veritcal counter (rows)
v_count := v_count + 1;
ELSE
v_count := 0;
END IF;
END IF;
--horizontal sync signal
IF(h_count < h_pixels + h_fp OR h_count > h_pixels + h_fp + h_pulse) THEN
h_sync <= NOT h_pol; --deassert horiztonal sync pulse
ELSE
h_sync <= h_pol; --assert horiztonal sync pulse
END IF;
--vertical sync signal
IF(v_count < v_pixels + v_fp OR v_count > v_pixels + v_fp + v_pulse) THEN
v_sync <= NOT v_pol; --deassert vertical sync pulse
ELSE
v_sync <= v_pol; --assert vertical sync pulse
END IF;
--set pixel coordinates
IF(h_count < h_pixels) THEN --horiztonal display time
--column <= h_count; --set horiztonal pixel coordinate
column <= std_logic_vector(to_unsigned(h_count, column'length)); --set horiztonal pixel coordinate
END IF;
IF(v_count < v_pixels) THEN --vertical display time
--row <= v_count; --set vertical pixel coordinate
row <= std_logic_vector(to_unsigned(v_count, column'length)); --set vertical pixel coordinate
END IF;
--set display enable output
IF(h_count < h_pixels AND v_count < v_pixels) THEN --display time
disp_ena <= '1'; --enable display
ELSE --blanking time
disp_ena <= '0'; --disable display
END IF;
END IF;
END PROCESS;
END behavior;
Related
VHDL code to read the inputs of a parallel AD converter
I was wondering if someone could help me to find the error I am making when reading the analog input introduced to the AD7822 converter by a potentiometer capable of varying its voltage in a range of 0 to 5V. As far as I understand what I have to do is to generate a 20ns wide pulse for the CONVST bit every 10MHz at most (starting from a clock operating at a maximum frequency of 50 MHz), then wait for the DR to be set to 0 and the value of the digital inputs could be taken. Timeline for working with AD7822 in automatic mode library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity db_read is generic ( div : natural := 5 ); port ( -- Input ports clk_in : in std_logic; rd : in std_logic; db_input : in std_logic_vector (7 downto 0) := (others => '0'); -- Output ports convst : out std_logic := '1'; db_output : out std_logic_vector (7 downto 0) := (others => '0') ); end db_read; -- Library Clause(s) (optional) -- Use Clause(s) (optional) architecture arch1 of db_read is begin ---------------------------------------------------------------------- -- Send CONVST each div/50MHz ms. ---------------------------------------------------------------------- process(clk_in) variable cont_convst : integer range 0 to div := 0; begin if (rising_edge(clk_in)) then cont_convst := cont_convst + 1; if (cont_convst = 1) then convst <= '0'; else convst <= '1'; end if; if (cont_convst = div) then cont_convst := 0; end if; end if; end process; ---------------------------------------------------------------------- -- Read digital inputs when ready ---------------------------------------------------------------------- process(clk_in) variable cont_rd : integer := 0; begin if (rising_edge(clk_in)) then -- Detect if RD takes '0' value if (rd = '0') then cont_rd := cont_rd + 1; end if; if (cont_rd = 1) then db_output <= db_input; end if; if (rd = '1') then cont_rd := 0; end if; end if; end process; end arch1; When I simulate it on a board what I see is that I always have all the outputs at high state regardless of the voltage that I introduce to the input of the converter.
VHDL wrapper for 1-wire core for DS18B20 temperature sensor
currently I am trying to write a VHDL wrapper for this Opencore Verilog module (1-wire master) so that I can send/receive from this temperature sensor (DS18B20). However I am struggling to understand the usage. Namely the read/write enable vs. the cyc bit in the control/status register of the 1-wire master module. The code I have so far sets the cyc bit to 1 and the read/write enable to one simultaneously but does not cycle them during each bit. Is this correct or am I misunderstanding it? I'm new to VHDL/ reading a datasheet so I have been struggling over this for a few days. Any help would be appreciated. I found this site that I have been using as a reference but it does not deal with the Verilog module that I am using. I am also looking for tips on my code style, and VHDL tips in general. My current code: LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; --may need to remove if signed not used ENTITY one_wire_temp_probe_control IS GENERIC ( one_us_divider_g : integer range 0 to 50 := 50 -- clock divider for one micro second ); PORT ( i_clk_50mhz : IN STD_LOGIC; i_read_enable : IN std_logic; io_temp_probe : INOUT STD_LOGIC; --how do i register an inout o_temperature : OUT signed(6 DOWNTO 0); o_temp_ready : OUT std_logic ); END one_wire_temp_probe_control; ARCHITECTURE rtl of one_wire_temp_probe_control IS ----temp commands---- CONSTANT skip_rom_c : std_logic_vector(7 DOWNTO 0) := x"CC"; --command to skip ROM identity of temperature sensor CONSTANT convert_temp_c : std_logic_vector(7 DOWNTO 0) := x"44"; --command to start temperature conversion CONSTANT read_scratchpad_c : std_logic_vector(7 DOWNTO 0) := x"BE"; --command to read the scratchpad i.e. get temperature data CONSTANT command_bits_c : integer RANGE 0 TO 8 := 8; --number of bits in the above commands (note: range used to limit number of bits to minimum needed) CONSTANT data_bits_c : integer RANGE 0 to 12 := 12; --number of bits in received data ----1-wire commands---- CONSTANT send_reset_pulse : std_logic_vector(7 DOWNTO 0) := "00001010"; --command to send reset pulse CONSTANT write_command_structure_c : std_logic_vector(6 DOWNTO 0) := "0000000"; --structure of the command that must be passed to the 1-wire controller (----EDIT----) ----timing constants---- CONSTANT delay_65us_c : integer := one_us_divider_g * 65; --65 micro-second delay CONSTANT delay_960us_c : integer := one_us_divider_g * 960; --960 micro-second delay CONSTANT delay_750ms : integer := one_us_divider_g * 1000 * 750; --760 milli-second delay ----state machine---- TYPE state_type IS (idle, presence_pulse, wait_presence_pulse, skip_rom, temp_conversion, wait_for_conversion, read_scratchpad, data_read, convert_data, wait_65us); SIGNAL state : state_type := idle; SIGNAL previous_state : state_type := idle; ----1-wire---- SIGNAL read_enable_s, write_enable_s, reset_s, owr_e_s : std_logic := '0'; SIGNAL write_data_s, read_data_s : std_logic_vector(7 DOWNTO 0):= (OTHERS => '0'); --8 bit mode chosen in sockit_owm SIGNAL address_s : std_logic_vector(1 DOWNTO 0) := "00"; SIGNAL timer_s : integer := 0; ----commands--- SIGNAL bit_counter_command_s : integer RANGE 0 TO command_bits_c := 0; --counter for bits in commands (note: not -1 due to using 9th bit as state change) SIGNAL bit_counter_data_s : integer RANGE 0 TO data_bits_c := 0; --counter for bits in data recieved ----temperature---- SIGNAL temperature_raw_data : std_logic_vector(11 DOWNTO 0) := (OTHERS => '0'); ----one wire control---- COMPONENT sockit_owm IS PORT ( ----control interface---- clk : IN std_logic; rst : IN std_logic; bus_ren : IN std_logic; bus_wen : IN std_logic; bus_adr : IN std_logic_vector(7 DOWNTO 0); bus_wdt : IN std_logic_vector(7 DOWNTO 0); bus_rdt : OUT std_logic_vector(7 DOWNTO 0); bus_irq : OUT std_logic; ----1-wire interface---- owr_p : OUT std_logic; --verilog code is a one bit wide vector owr_e : OUT std_logic; owr_i : IN std_logic ); END COMPONENT; BEGIN address_s <= "00"; --for the temp probe control we're not interested in other address spaces PROCESS(i_clk_50mhz) BEGIN --state change IF rising_edge(i_clk_50mhz) THEN CASE state is WHEN idle => o_temp_ready <= '0'; IF (i_read_enable = '1') THEN state <= presence_pulse; ELSE state <= idle; END IF; WHEN presence_pulse => ----send reset/presence pulse---- write_enable_s <= '1'; write_data_s <= send_reset_pulse; timer_s <= delay_960us_c; state <= wait_presence_pulse; WHEN wait_presence_pulse => ----wait for 960 micro seconds---- read_enable_s <= '1'; IF (timer_s = 0) THEN IF (read_data_s(0) = '0') THEN state <= skip_rom; ELSIF (read_data_s(0) = '1') THEN --precence not detected ELSE state <= wait_presence_pulse; END IF; ELSE timer_s <= timer_s - 1; state <= wait_presence_pulse; END IF; WHEN skip_rom => ----send skip rom command---- previous_state <= skip_rom; write_enable_s <= '1'; IF (bit_counter_command_s = command_bits_c) THEN bit_counter_command_s <= 0; state <= temp_conversion; ELSE write_data_s <= write_command_structure_c & skip_rom_c(bit_counter_command_s); ---command structure concatonated with 1 bit from command bit_counter_command_s <= bit_counter_command_s + 1; timer_s <= delay_65us_c; state <= wait_65us; END IF; WHEN temp_conversion => ----send temp conversion command to probe---- previous_state <= temp_conversion; IF (bit_counter_command_s = bit_counter_command_s) THEN bit_counter_command_s <= 0; timer_s <= delay_750ms; state <= wait_for_conversion; ELSE write_data_s <= write_command_structure_c & convert_temp_c(bit_counter_command_s); ---command structure concatonated with 1 bit from command bit_counter_command_s <= bit_counter_command_s + 1; timer_s <= delay_65us_c; state <= wait_65us; END IF; WHEN wait_for_conversion => ----wait for temperature conversion to finish---- IF (timer_s = 0) then state <= read_scratchpad; ELSE timer_s <= timer_s - 1; END IF; WHEN read_scratchpad => ----send read scratchpad command---- previous_state <= read_scratchpad; IF (bit_counter_command_s = command_bits_c) THEN state <= data_read; bit_counter_command_s <= 0; ELSE write_data_s <= write_command_structure_c & read_scratchpad_c(bit_counter_command_s); ---command structure concatonated with 1 bit from command bit_counter_command_s <= bit_counter_command_s + 1; timer_s <= delay_65us_c; state <= wait_65us; END IF; WHEN data_read => ----read incoming data---- previous_state <= data_read; read_enable_s <= '1'; IF (bit_counter_data_s = data_bits_c) THEN bit_counter_data_s <= 0; --may need to invert this state <= convert_data; ELSE temperature_raw_data(bit_counter_data_s) <= read_data_s(0); bit_counter_data_s <= bit_counter_data_s + 1; timer_s <= delay_65us_c; state <= wait_65us; END IF; WHEN convert_data => ----convert raw data into temperature---- o_temp_ready <= '1'; WHEN wait_65us => ----wait for read/write cycle to finish---- IF (timer_s = 0) THEN state <= previous_state; ELSE timer_s <= timer_s - 1; state <= wait_65us; END IF; END CASE; END IF; END PROCESS; ----one wire component instantiation---- one_wire_control : sockit_owm PORT MAP( ----control interface---- clk => i_clk_50mhz, rst => reset_s, bus_ren => read_enable_s, bus_wen => write_enable_s, bus_adr => address_s, bus_wdt => write_data_s, bus_rdt => read_data_s, bus_irq => OPEN, ----1-wire interface---- owr_p => OPEN, owr_e => owr_e_s, owr_i => io_temp_probe ); io_temp_probe <= owr_e_s ? '0' : 'Z'; --I also need help converting this line to VHDL END rtl; Thank you in advance. Best Tom
I am also looking for tips on my code style, and VHDL tips in general. OK. First thing: don't make the lines so long. So don't put comments at the end of a line. Put them a line before. use IEEE.NUMERIC_STD.ALL; --may need to remove if signed not used then remove, as I don't see any signed one_us_divider_g : integer range 0 to 50 := 50 -- clock divider for one micro second So... what happens is one_us_divider_g is set to 0? Seems an illegal value. Using it for simulation? io_temp_probe : INOUT STD_LOGIC; --how do i register an inout One option is to use a tristate IOBUFFER. This is a special FPGA edge element which splits the input and output to separate signals. You can tristate the ouput by setting a control port. Alternatively you could just do it the way you do in your code (this is also explained in for instance the Xilinx synthesis user guide). Which leads me to another question in your code. io_temp_probe <= owr_e_s ? '0' : 'Z'; --I also need help converting this line to VHDL io_temp_probe <= '0' when owr_e_s = '1' else 'Z'; CONSTANT command_bits_c : integer RANGE 0 TO 8 := 8; No need for an integer range if it is a constant. CONSTANT send_reset_pulse : ... CONSTANT delay_750ms : ... Missing the "_c" you put behind all your constants. But I would not add this "s", "_c" or "_g" anyhow. A lot of work for little gain. COMPONENT sockit_owm IS PORT ( [...] ); END COMPONENT; Component declarations are not required anymore since some time now. You can remove it and change your instantiation: one_wire_control : entity work.sockit_owm PORT MAP( [...] WHEN idle => [...] ELSE state <= idle; END IF; not required. If you don't change state, it stays at idle. WHEN wait_presence_pulse => IF (timer_s = 0) THEN IF (read_data_s(0) = '0') THEN [...] ELSIF (read_data_s(0) = '1') THEN [...] ELSE state <= wait_presence_pulse; END IF; read_data_s(0) '0' and '1' are covered. Do you expect any other value? That can only happen in simulation, not in implementation. So the code in the last else-statement is unreachable then. [...] timer_s <= delay_65us_c; state <= wait_65us; [...] WHEN wait_65us => IF (timer_s = 0) THEN [...] ELSE timer_s <= timer_s - 1; END IF; Let's say a delay is 65 us lasts 10 clock cycles. Setting the divider to 1, delay_65us_c=10. So at t=0, timer_s is set to 10. at t=1 -state is wait_65us now- timer_s is set to 9. And so on: at t=10, timer_s is set to 0... but state is still wait_65us. So at t=11, timer_s is detected 0, and state is changed to the previous one. Which it will enter at t=12. So, instead of a 10 clock cycle delay, you get a 12 clock cycle delay. Is this a problem? If yes, you should reconsider your code. SIGNAL read_enable_s, write_enable_s, reset_s, owr_e_s : std_logic := '0'; [... not used anywhere else... ] one_wire_control : sockit_owm PORT MAP( [...] rst => reset_s, Are you sure this is correct? A lot of components need to be properly reset before they operate correctly.
If you're working with Quartus, you can mix VHDL code with Verilog and even schematic elements. In the link below, I use a verilog driver for the same chip (DS18B20). See here for details: https://physnoct.wordpress.com/2016/12/14/altera-quartus-combining-verilog-and-vhdl/
How do you make vhdl counter that can count in tenths of a millisecond?
I am working on an IR Decoder in VHDL and I know that the widths of an IR 1 bit is 1.2 ms, an IR 0 bit is 0.6 ms, and the start bit is 2.5 ms. I am trying to make a counter that takes in the 50MHz clock and converts to tenths of a millisecond. How can I do this? entity counter is Port ( EN : in STD_LOGIC; RESET : in STD_LOGIC; CLK : in STD_LOGIC; COUNT : out STD_LOGIC_VECTOR (4 downto 0)); end counter; architecture Behavioral of counter is constant max_count : integer := (2); begin startCounter: process(EN, RESET, CLK) variable cnt : integer := 0; variable div_cnt : integer := 0; begin if (RESET = '1') then cnt := 0; div_cnt := 0; elsif (EN = '1' and rising_edge(CLK)) then if (cnt = max_count) then cnt := 0; div_cnt:= div_cnt + 1; else cnt := cnt + 1; end if; end if; COUNT <= conv_std_logic_vector(cnt, 5); -- COUNT <= temp_count(16 downto 13); end process startCounter; end Behavioral;
Since you have a 50 MHz clock and want to generate a 0.1 msec pulse, you can use the ieee library, math_real, to compute the number of 50 MHz clocks to create a 0.1 msec pulse. Here's a code fragment. library ieee; use ieee.math_real.all; -- omitting for clarity... -- generate one clk cycle pulse with period of 0.1 msec gen_0p1mspulse_p : process(Clk) constant CLK_PERIOD : real := 1/50e6; constant PULSE_PERIOD : real := 0.1e-3; constant MAX_CNT : integer := INTEGER(PULSE_PERIOD/CLK_PERIOD); variable cnt : integer range 0 to MAX_CNT-1 := 0; begin if rising_edge(Clk) then if reset = '1' then cnt := 0; pulse_0p1msec <= '0'; else pulse_0p1msec <= '0'; -- default value if cnt < MAX_CNT-1 then cnt := cnt + 1; else cnt := 0; pulse_0p1msec <= '1'; end if; end if; end if; end process; -- logic using 0.1 msec pulse your_logic_p : process(Clk) begin if rising_edge(Clk) then if reset = '1' then your_cnt := 0; else if pulse_0p1msec = '1' then -- insert your logic here end if; end if; end if; end process; I like to split up my VHDL processes so that they're short. I also prefer to use synchronous resets and enables since they synthesize to less hardware for Xilinx FPGAs as well as running at a higher clock rates. Hope that addresses your issue.
VGA VHDL Screen Moves when I refresh
I'm trying to make a grid on the screen using this VHDL. I can make two lines now, but when I refresh the screen, the lines move. I'm not sure where the error is, can someone help or offer any pointers? library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_unsigned.all; --use IEEE.std_logic_arith.all; --VVVVVVV use IEEE.NUMERIC_STD.all; --^^^^^^^ entity SCRN is port( clk : in STD_LOGIC; vga : OUT STD_LOGIC_VECTOR (7 downto 0); Hsync : OUT STD_LOGIC; Vsync : OUT STD_LOGIC ); end SCRN; architecture Behavioral of SCRN is type PLC_HOLD is array (1 to 800, 1 to 525) of STD_LOGIC_VECTOR(7 downto 0); signal scrn : PLC_HOLD; signal s_clk : std_logic_vector (1 downto 0) := (others => '0'); signal xx_vga : std_logic_vector (7 downto 0); signal xx_h : std_logic; signal xx_v : std_logic; signal X : std_logic_vector (9 downto 0) := (others => '1'); signal Y : std_logic_vector (9 downto 0) := (others => '1'); -- signal test : ieee.numeric_std.unsigned -- test now works with mod begin NW_CLK: process (clk) is begin if rising_edge (clk) then s_clk <= (s_clk + "01"); end if; end process NW_CLK; --###############################-- scrn_loc : process (s_clk(1)) is begin if RISING_EDGE (s_clk(1)) then X <= X + "0000000001"; if (X = "1100100000") then --if x = 800 X <= "0000000001"; Y <= (Y + "0000000001"); elsif (Y = 525) then -- if y = 525 X <= "0000000001"; Y <= "0000000001"; end if; end if; end process; --###############################-- draw : process (X,Y) is -- h and v sync process begin if (X > 640) then -- and (X <= 752) then -- low for sync pulse at 656 to 752 -- 96 pixel xx_h <= '0'; else xx_h <= '1'; end if; if (Y> 490) and (Y <= 492) then -- low for sync puls at 490 to 492 xx_v <= '0'; else xx_v <= '1'; end if; -- (CONV_INTEGER((X)) mod 10) -- CONV_INTEGER(Y) mod 10 -- if X = 1 then -- xx_vga <= "00111000"; ---- elsif Y = 1 or Y = 480 then ---- xx_vga <= "11101011"; -- else -- xx_vga <= "11100000"; -- end if; end process; --###############################-- scrn(CONV_INTEGER(X),CONV_INTEGER(Y)) <= "00111000" when X = 1 else "11100101" when Y = 2 else "00000111" when X = 640 else "11001101"; Hsync <= xx_h; Vsync <= xx_v; vga <= scrn(CONV_INTEGER(X),CONV_INTEGER(Y)); end Behavioral;
Hmmm... What happens if you move the line where you assign to scrn(CONV_INTEGER(X),CONV_INTEGER(Y)) <= "00111000" when X = 1 else ... to somewhere inside your process? Also there is no need to use binary literals in your code (e.g., if (X = "1100100000")). Just use integer literals, or decimal bit-string literals. Better yet, define all your numeric values as integers or naturals. As a bonus, your code will be cleaner because you won't need all those conversion functions.
You are creating a clock from a clock, which is a bad idea. It seems you are trying to divide by 4? Instead create an enable pulse: NW_CLK: process (clk) is variable divider : integer range 0 to 3; begin if rising_edge (clk) then if divider = 3 then divider := 0; screen_process_enable <= '1'; else divider := divider + 1; screen_process_enable <= '0'; end if end if; end process NW_CLK; Then in the screen process: scrn_loc : process (clk) is begin if RISING_EDGE (clk) and screen_process_enable = '1' then etc... Not related to your question, but I'll comment on it here anyway: You seem to be trying to hold the entire screen in memory - that's quite a lot of storage you are asking for in a real chip (it'll be fine in simulation). For producing a grid you can just do it on the fly, by assigning to the VGA output depending on the values of your x and y counters. Because you have both the assignment to scrn and vga outside of a process, the synthesiser is probably clever enough to figure out that you never make use of the memory storage you've asked for and has optimised it away. If at some future point you come to use scrn as a true framebuffer, you may run up against performance or resource limitations, depending on your device.
Check chapter 15 (VHDL Design of VGA Video Interfaces) of "Circuit Design and Simulation with VHDL", which shows detailed VGA theory followed by a number of experiments using VHDL and VGA monitors.
VHDL - Quartus II modsim
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