Question

Hi, i'm coding the main program structure for my LCM, called DE2_LCM2(in vhdl).

Within the main structure, there is a clock divider calls PLL2 (in verilog) and a I2S_LCM_Config (in verilog). My PLL2.v and I2S_LCM.v are given by vendor, except for my DE2_LCM.vhd, myself coded. Compile successful, but stimulation failed.

FYI:

Horizontal scan:

1 Horizontal Line, there are 1171 counts or cycles of DCLK. The LCM_HSYNC goes low during falling edge of DCLK for 1 cycle. For the first 152 cycle, the data on LCM_DATA bus are invalid, start valid from cycle 153 to 1112, and invalid from cycle 1112 to 1171.

Vertical scan (Non-interlace):

After the last cycle of a horizontal line, the vertical counter shall be incremented by one. This LCM got 262 vertical lines in total, but only line 15 to (15+240)=255 is displayed.

LCM_PLL.v:

This file helps to convert system clock 50MHz to 18.42MHz. the DCLK or LCM_DCLK will be used for horizontal and vertical counter.

Below is my DE2_LCM.vhd codes, can't find what is going wrong on my code. Some more my teacher is on leave.

library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity DE2_LCM2 is port(CLOCK_50 : in std_logic;
                   KEY0 : in std_logic;
                   SW : in std_logic_vector(1 downto 0);
                   LCM_DATA : out std_logic_vector(7 downto 0);
                   LCM_DCLK, LCM_HSYNC, LCM_VSYNC,LCM_SCLK,LCM_SDAT,LCM_SCEN,LCM_GRST,LCM_SHDB : out std_logic
                    );
end DE2_LCM2;

architecture rtl of DE2_LCM2 is
  constant H_SYNC_CYC: integer:=1;
  constant H_SYNC_BACK: integer:=152;
  constant H_SYNC_ACT: integer:=960;
  constant H_SYNC_FRONT: integer:=59;
  constant H_SYNC_TOTAL: integer:=1171;

  constant V_SYNC_CYC: integer:=1;
  constant V_SYNC_BACK: integer:=14;
  constant V_SYNC_ACT: integer:=240;
  constant V_SYNC_FRONT: integer:=8;
  constant V_SYNC_TOTAL: integer:=262;

  signal H_Cont: std_logic_vector(10 downto 0);
  signal V_Cont: std_logic_vector(10 downto 0);
  signal MOD_CNT: std_logic_vector(1 downto 0);
  signal Tmp_DATA1: std_logic_vector(11 downto 0);
  signal CLK_18: std_logic;
  signal mSEL: std_logic_vector(1 downto 0);
  signal iRST_N: std_logic;
  signal I2S_SDAT: std_logic;

component LCM_PLL2 port(inclk0: in std_logic;
                      c0: out std_logic);
end component;

component I2S_LCM_Config is port(iCLK: in std_logic;
                             iRST_N: in std_logic;
                             I2S_SCLK: out std_logic;
                             I2S_SDAT: inout std_logic;
                             I2S_SCEN: out std_logic);
end component;

begin
  LCM_GRST<=KEY0;
  LCM_DCLK<=not(CLK_18);
  LCM_SHDB<='1';
  iRST_N<=KEY0;
  LCM_SDAT<=I2S_SDAT; --add on

  process(SW,MOD_CNT )
    begin
      if(SW="00")then 
        if(MOD_CNT="00")then
          LCM_DATA<="01111111";
        else LCM_DATA<="00000000";
        end if;
      elsif(SW="01")then
        if(MOD_CNT="01")then
          LCM_DATA<="01111111";
            else LCM_DATA<="00000000";
        end if;
      elsif(SW="10")then
        if(MOD_CNT="10")then
          LCM_DATA<="01111111";
        else LCM_DATA<="00000000";
        end if;
      else LCM_DATA<="00000000";
      end if;
  end process;

u0:LCM_PLL2 port map(inclk0=>CLOCK_50,
                c0=>CLK_18);
u1:I2S_LCM_Config port map(iCLK=>CLOCK_50,
                       iRST_N=>KEY0,
                       I2S_SCLK=>LCM_SCLK,
                       I2S_SDAT=>I2S_SDAT,
                       I2S_SCEN=>LCM_SCEN);

process(CLK_18,iRST_N)
  begin
    if(rising_edge(CLK_18))then
      if iRST_N = '0'then
      MOD_CNT <= "11";
      H_Cont <= "00000000000";
      LCM_HSYNC <= '0';
      V_Cont <= "00000000000";
      LCM_VSYNC <= '0';
      else
        if((H_Cont >= H_SYNC_BACK) and (H_Cont<(H_SYNC_TOTAL-H_SYNC_FRONT)))then
          if(MOD_CNT < "10") then 
          MOD_CNT <= MOD_CNT + '1';
          else
          MOD_CNT <= "00";
          end if;
        else MOD_CNT <= "11";
        end if;

        if(H_Cont < (H_SYNC_TOTAL-1)) then
        H_Cont <= H_Cont + '1';
        else H_cont <= "00000000000";
        end if;

        if(H_Cont < H_SYNC_CYC)then
        LCM_HSYNC <= '0';
        else LCM_HSYNC <= '1';
        end if;

        if(V_Cont <(V_SYNC_TOTAL-1)) then
          V_Cont <= V_Cont+'1';
        else V_Cont <= "00000000000";
        end if;

        if(V_Cont < V_SYNC_CYC) then
        LCM_VSYNC <= '0';
        else LCM_VSYNC <= '1';
        end if;
      end if; 
    end if;
end process;                                                      
end rtl;

Should be my coding style that is not suitable for hardware programming. Do let me know if PLL2.v and I2S_LCM_Config.v are needed for your testing. I'll send u through email.

Thanks in advance:)

Was it helpful?

Solution

Without checking your PLL or I2C, the vertical counter appears to be counting clocks and not lines:

LCM_TB showing vertical counter counting CLK_18

There needs to be an additional qualifier to only increment V_cont when H_Cont is the maximum count (1170).

Something along the lines of:

            if H_Cont = std_logic_vector (to_unsigned (H_SYNC_TOTAL-1,11)) then

                if V_Cont < std_logic_vector(to_unsigned (V_SYNC_TOTAL-1, 11)) then
                    V_Cont <= std_logic_vector(unsigned(V_Cont) + 1);
                else 
                    V_Cont <= (others => '0');
                end if;
            end if;

(Ya, I used package numeric_std, sue me. Reformatted the heck out of your code to make it readable too).

And that gives you something that looks more reasonable (but hasn't really been checked, after all it's your design):

vertical counter incrementing properly

And the next Vertical event:

enter image description here

I also don't see any reason you couldn't use range constrained integers for H_Cont and V_Cont.

addendum

Because the answer caused confusion:

sorry, to be frank, i do understand what r u trying to achieve but i dont understand your codes. – user317130 13 hours ago

I figured I'd redo the solution using the Synopsys version of std_logic packages. It makes the changes simpler and easier to see.

First, I created a CLOCK process that generated CLK_18 locally. This could have been in the test bench and simply driving CLK_18 with CLK_50, I didn't want any name confusion. I also commented out the I2C and PLL as being not supplied/uninvolved:

signal CLK_18: std_logic := '0';  -- default value to allow not in CLOCK process to run

Removing the unsupplied components:

-- component LCM_PLL2 port(inclk0: in std_logic;
--                       c0: out std_logic);
-- end component;
--
-- component I2S_LCM_Config is port(iCLK: in std_logic;
--                              iRST_N: in std_logic;
--                              I2S_SCLK: out std_logic;
--                              I2S_SDAT: inout std_logic;
--                              I2S_SCEN: out std_logic);
-- end component;

And:

--
-- u0:LCM_PLL2 port map(inclk0=>CLOCK_50,
--                 c0=>CLK_18);
-- u1:I2S_LCM_Config port map(iCLK=>CLOCK_50,
--                        iRST_N=>KEY0,
--                        I2S_SCLK=>LCM_SCLK,
--                        I2S_SDAT=>I2S_SDAT,
--                        I2S_SCEN=>LCM_SCEN);

And yes that leaves some signals undriven. We'll drive CLK_18 locally:

-- Dummy up CLK_18:
CLOCK:
    process
    begin 
        wait for 27.15 ns;
        CLK_18 <= not CLK_18;
        if Now > 80 ms then
            wait;
        end if;
    end process;
-- Here instead of the test bench, could have jumpered CLOCK_50 to CLK_18

80 ms was rather excessive (a simulation will run until no events occur, everything is driven off the clock). Took a substantial length of time to simulate and the waveform dump was big (32 MB). It can be pared in half at least.

The change in operating the vertical counter is a bit more obvious using Synopsys standard logic libraries:

    if H_Cont = H_SYNC_TOTAL - 1 then

        if(V_Cont <(V_SYNC_TOTAL-1)) then
          V_Cont <= V_Cont+'1';
        else V_Cont <= "00000000000";
        end if;
    end if;

It consists of only operating the V_Cont counter in the last count of H_Cont so the counter only operates once per scan line.

The added test bench:

library ieee;
use ieee.std_logic_1164.all;

entity LCM_TB is
end entity;

architecture foo of LCM_TB is
    signal CLOCK_50:   std_logic := 'H';
    signal KEY0:       std_logic := '0';
    signal SW:         std_logic_vector(1 downto 0) := "11";
    signal LCM_DATA:   std_logic_vector(7 downto 0);
    signal LCM_DCLK, 
           LCM_HSYNC, 
           LCM_VSYNC,
           LCM_SCLK,
           LCM_SDAT,
           LCM_SCEN,
           LCM_GRST,
           LCM_SHDB: std_logic;
begin

-- CLOCK process found in DUT

DUT:
    entity work.de2_lcm2
        port map (
            CLOCK_50 => CLOCK_50,
            KEY0 => KEY0,
            SW => SW,
            LCM_DATA => LCM_DATA,
            LCM_DCLK => LCM_DCLK,
            LCM_HSYNC => LCM_HSYNC, 
            LCM_VSYNC => LCM_VSYNC,
            LCM_SCLK => LCM_SCLK,
            LCM_SDAT => LCM_SDAT,
            LCM_SCEN => LCM_SCEN,
            LCM_GRST => LCM_GRST,
            LCM_SHDB => LCM_SHDB
        );

STIMULUS:  -- Just a reset
    process
    begin
        wait for 100 ns;
        KEY0 <= '1';
        wait;
    end process;

end architecture;

The build process:

ghdl -a --ieee=synopsys -fexplicit de2_lcm2.vhdl
ghdl -e --ieee=synopsys -fexplicit lcm_tb
ghdl -r lcm_tb --wave=lcm_tb.ghw

And because this is a Mac open *.ghw, or after establishing a save file open *.gtkw. (OS X claims suffixes like Windows, the open command tells it to...).

And all this gives the same answer as the version using package numeric_std:

lcm_tb using Synopsys standard logic packages

From the horizontal scroll bar in GTKWave you can see the simulation was twice as long as needed.

And instead of using std_logic_vector values you could have used unsigned with IEEE standard compliant package numeric_std with some slight modifications or converted H_Cont and V_Cont to range constrained integers (which will synthesize just fine), not forgetting to convert "00000000000" to 0 and ... + '1' to + 1 where appropriate.

I would have gotten back quicker but am in timezone GMT-12 (It's tomorrow here).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top