Dear Group, I know how annoying it is when one posts blocks of HDL, but I would really appreciate someone telling me why this code does not work -- or at least, a pointer to my stupidity!!! This HDL is supposed to generate standard -ve syncs plus an early 'newline' signal to a specialised SDRAM controller which writes a complete line of octets into alternate block-RAMs in my Spartan-3 device. It then attempts to display them by generating alternate read enables (based on the current vertical line). Tomorrow I am going to rewrite the code using discrete processes (one for each sync signal etc...). library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.numeric_std.all; entity VidCont is generic( DATA_WIDTH : natural := 16; -- video data width VADDR_WIDTH : natural := 10 -- Video FIFO (blockRAM) address width ); port( -- Interface clk : in std_logic; -- Master clock @25MHz rst : in std_logic; -- Reset -- Video blockRAM side VIAddr : out std_logic_vector(VADDR_WIDTH-1 downto 0); -- Video line buffer address VADIn : in std_logic_vector(DATA_WIDTH-1 downto 0); -- Data from 'A' block RAM VEnA : out std_logic; -- Enable 'A' FIFO VBDIn : in std_logic_vector(DATA_WIDTH-1 downto 0); -- Data from 'B' block RAM VEnB : out std_logic; -- Enable 'B' FIFO NewLine : out std_logic; -- Initiate line read burst -- TFT interface VRed : out std_logic_vector(5 downto 0); -- 6-bit red VGreen : out std_logic_vector(5 downto 0); -- 6-bit green VBlue : out std_logic_Vector(5 downto 0); -- 6-bit blue VDE : out std_logic; -- Data-enable VVSync : out std_logic; -- Vertical synch. VHSync : out std_logic; -- Horizontal synch. -- Debug signal... Debug : out std_logic ); end VidCont; architecture arch of VidCont is constant YES : std_logic := '1'; constant NO : std_logic := '0'; constant HI : std_logic := '1'; constant LO : std_logic := '0'; constant ONE : std_logic := '1'; constant ZERO : std_logic := '0'; -- TFT timing parameters... constant tHP : natural := 800; -- Horizontal sync. period constant tWH : natural := 96; -- Horizontal sync. width constant tVP : natural := 525; -- Vertical sync. period constant tWV : natural := 2; -- Vertical sync. width constant tHV : natural := 640; -- Active horizontal period constant tHBP : natural := tWH+40; -- End of H back porch (start of active area) constant tHFP : natural := tHBP+tHV; -- Start of H front porch (end of active area) constant tVV : natural := 480; -- Active vertical period constant tVBP : natural := tWV+33; -- End of V back porch (start of active area) constant tVFP : natural := tVBP+tVV; -- Start of V front porch (end of active area) -- Horizontal & vertical counters... signal hCount_x, hCount_r : natural range 0 to tHP+1; -- Horizontal column count signal vCount_x, vCount_r : natural range 0 to tVP+1; -- Address counters... signal hAddr_x, hAddr_r : std_logic_vector(VIAddr'range); -- Horizontal address -- Data enable flags... signal hDEm3_x, hDEm3_r : std_logic; -- Early (-3) horizontal data enable signal hDEm2_r : std_logic; -- Early (-2) latched horizontal data enable signal hDEm1_r : std_logic; -- Early (-1) latched horizontal data enable signal hDE_r : std_logic; -- Horizontal data enable signal vDEm2_x, vDEm2_r : std_logic; -- Early (-2) vertical data enable signal vDEm1_r : std_logic; -- Early (-1) vertical data enable signal vDE_r : std_logic; -- Vertical data enable signal nlBurst_x, nlBurst_r : std_logic; -- Newline burst strobe signal IVEnA_x, IVEnA_r : std_logic; -- Block RAM 'A' read enable signal IVEnB_x, IVEnB_r : std_logic; -- Block RAM 'B' read enable -- Syncs... signal IVSync_x, IVSync_r : std_logic; -- Vertical sync signal IHSync_x, IHSync_r : std_logic; -- Horizontal sync signal AltLine_x, AltLine_r : std_logic; -- Source flipper -- RGB data... signal RGB_x, RGB_r : std_logic_vector(VADIn'range); -- Demultiplexed and latched RGB data begin -- Attach signals to outputs... VIAddr <= hAddr_r; -- Horizontal address = block RAM address VDE <= hDE_r; -- Display enable... VRed(5 downto 1) <= RGB_r(15 downto 11); VRed(0) <= RGB_r(15); VGreen(5 downto 0) <= RGB_r(10 downto 5); VBlue(5 downto 1) <= RGB_r(4 downto 0); VBlue(0) <= RGB_r(4); VHSync <= IHSync_r; VVSync <= IVSync_r; VEnA <= IVEnA_r; VEnB <= IVEnB_r; NewLine <= nlBurst_r; Debug <= IHSync_r; -- Determine next state... RGB_x <= VBDIn when AltLine_r = '0' else VADIn; -- Video input mux IHSync_x <= LO when hCount_r = (tHP-1) else HI when hCount_r = (tWH-1) else IHSync_r; -- Hor. sync generation IVSync_x <= LO when vCount_r = (tVP-1) else HI when vCount_r = (tWV-1) else IVSync_r; -- Vert. sync generation hCount_x <= 0 when hCount_r = (tHP-1) else hCount_r + 1; -- Hor. counter vCount_x <= 0 when vCount_r = (tVP-1) else vCount_r + 1 when hCount_r = (tHP-1) else vCount_r; -- Vert. counter AltLine_x <= LO when vCount_r = (tVP-1) else not AltLine_r when hCount_r = (tHP-1) else AltLine_r; -- Alternate line generation hDEm3_x <= HI when (hCount_r = (tHBP-1)) and (vDEm2_r = HI) else LO when hCount_r = (tHFP-1) else hDEm3_r; -- Early horizontal DE vDEm2_x <= HI when vCount_r = (tVBP-1) else LO when vCount_r = (tVFP-1) else vDEm2_r; -- Early vertical DE nlBurst_x <= HI when (vDEm1_r = '1') and (hCount_r = (tWH-1)) else LO; -- BlockRAM fill strobe hAddr_x <= hAddr_r + 1 when hDEm2_r = '1' else (others => '0'); -- Keep advancing blockRAM address during active window, else reset IVEnA_x <= HI when AltLine_r = '1' else LO; IVEnB_x <= HI when AltLine_r = '0' else LO; update : process(rst, clk) begin if rst=YES then -- Asynchronous reset... hAddr_r <= (others => '0'); hDEm3_r <= '0'; hDEm2_r <= '0'; hDEm1_r <= '0'; hDE_r <= '0'; vDEm1_r <= '0'; vDEm2_r <= '0'; vDE_r <= '0'; nlBurst_r <= '0'; IVEnA_r <= '0'; IVEnB_r <= '0'; IVSync_r <= '1'; IHSync_r <= '1'; hCount_r <= 0; vCount_r <= 0; AltLine_r <= '0'; RGB_r <= (others => '0'); -- elsif rising_edge(clk) then elsif clk'event and clk='1' then -- Ripple pipline display enable bits... hDEm3_r <= hDEm3_x; hDEm2_r <= hDEm3_r; hDEm1_r <= hDEm2_r; hDE_r <= hDEm1_r; vDEm2_r <= vDEm2_x; vDEm1_r <= vDEm2_r; vDE_r <= vDEm1_r; nlBurst_r <= nlBurst_x; IVEnA_r <= IVEnA_x; IVEnB_r <= IVEnB_x; -- Syncs... IHSync_r <= IHSync_x; IVSync_r <= IVSync_x; -- Video data/address... hAddr_r <= hAddr_x; -- Update video RAM address RGB_r <= RGB_x; -- Latch video data -- Counters... hCount_r <= hCount_x; vCount_r <= vCount_x; AltLine_r <= AltLine_x; end if; end process update; end arch; Thanks for your patience. Regards, Peter
Going insane - Xilinx VGA controller...
Started by ●December 22, 2005
Reply by ●December 29, 20052005-12-29
Reply by ●December 30, 20052005-12-30
Hi Peter, It would appear from your VHDL code that you're sending sync signals out of your entity that are generated from combinational logic. I would suggest that this is BAD. Look at this line:- IHSync_x <= LO when hCount_r = (tHP-1) else HI when hCount_r = (tWH-1) else IHSync_r; -- Hor. sync generation The signal IHSync_x is the signal that gets propagated out of the design. The problem is that not all of the wires that make up signal hCount_r change at exactly the same time. There will be some skew on them. This means that IHSync_x could have glitches on it. Not good for a sync signal! Move the VHDL line inside the clocked update process. That way, IHSync_x will come straight from a FF and will be glitch free. HTH, Syms. p.s. I hope the wine is still flowing in Greece? Wish I was there myself, it's p-ing down here in Plymouth.
Reply by ●December 30, 20052005-12-30
peter.halford@alarmip.com wrote:>Dear All, > >Many thanks for all your suggestions... > >I have tried dividing my incoming 25MHz clock by 2 and voilla! >everything works, albeit 50% slower... > >So now I guess I will have to divide the incoming clock by 2, multiply >it and re-divide it. > >Any ideas why this could be happening? > >Doesn't completely fit the symptoms, but is it possible there are reflections on the clock input? What you are doing is not only dividing the clock, but providing a clean clock from WITHIN the FPGA. Of course, you also could have an extremely slow path in the design somewhere, but that would have to be a huge amount of combinatorial logic or maybe some very slow external path like a RAM, to make it work at 12.5 MHz but fail at 25. Jon
Reply by ●December 30, 20052005-12-30
Dear Symon, Today I rewrote the entire module using procedural code and now everything is working perfectly!!! It is odd how the code would work for a bit and then stop for another bit... Anyhow, this is how one learns to make things work... Many thanks to you and to all who offered help. Regards, Peter PS. It is p-ing down here in torrents!!! Corfu is the greenest island in Greece for a very good reason!!!