在主结构中,有一个时钟分频器调用 PLL2(在verilog中)和一个 I2S_LCM_Config(在verilog中)。 我的PLL2.v和I2S_LCM.v由供应商提供,除了我的DE2_LCM.vhd,我自己编码。编译成功,但刺激失败。
供参考:
横向扫描:
1水平线,有1171个DCLK计数或周期。 LCM_HSYNC在DCLK的下降沿期间变为低电平,持续1个周期。对于前152个周期,LCM_DATA总线上的数据无效,从周期153到1112开始有效,从周期1112到1171无效。
垂直扫描(非隔行扫描):
在水平线的最后一个循环之后,垂直计数器应增加1。该LCM总共有262条垂直线,但只显示第15行到第(15 + 240)= 255行。
LCM_PLL.v:
此文件有助于将系统时钟50MHz转换为18.42MHz。 DCLK或LCM_DCLK将用于水平和垂直计数器。
以下是我的DE2_LCM.vhd代码,无法找到我的代码出错的地方。我的老师还有一些休假。
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;
应该是我的编码风格,不适合硬件编程。如果您的测试需要 PLL2.v 和 I2S_LCM_Config.v ,请告诉我们。我会通过电子邮件发送给您。
提前致谢:)
答案 0 :(得分:0)
在不检查PLL或I2C的情况下,垂直计数器似乎是计数时钟而不是行:
当H_Cont是最大计数(1170)时,需要额外的限定符才能增加V_cont。
有些事情:
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,我使用了包numeric_std,起诉我。重新格式化你的代码以使其可读)。
这会给你一些看起来更合理的东西(但实际上并没有经过检查,毕竟这是你的设计):
下一个垂直事件:
我也没有看到任何理由不能为H_Cont和V_Cont使用范围约束整数。
<强>附录强>
因为答案引起了混淆:
抱歉,坦率地说,我明白你想要实现的目标,但是我 不明白你的代码。 - user317130 13小时前
我想我会使用Synopsys版本的std_logic软件包重做解决方案。它使更改更简单,更容易看到。
首先,我创建了一个在本地生成CLK_18的CLOCK进程。这可能是在测试台上,只是用CLK_50驱动CLK_18,我不想让任何名字混淆。我还将I2C和PLL注释为未提供/未提供:
signal CLK_18: std_logic := '0'; -- default value to allow not in CLOCK process to run
删除未提供的组件:
-- 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;
和
--
-- 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);
是的,这留下一些信号未被发现。我们将在本地驱动CLK_18:
-- 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毫秒相当过分(模拟将一直运行,直到没有事件发生,一切都被驱动掉时间)。花了相当长的时间来模拟并且波形转储很大(32 MB)。它至少可以减少一半。
使用Synopsys标准逻辑库,操作垂直计数器的变化更为明显:
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;
它只包括在H_Cont的最后一次计数中操作V_Cont计数器,因此计数器每个扫描行只运行一次。
增加的测试平台:
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;
构建过程:
ghdl -a --ieee = synopsys -fexplicit de2_lcm2.vhdl
ghdl -e --ieee = synopsys -fexplicit lcm_tb
ghdl -r lcm_tb --wave = lcm_tb.ghw
因为这是Mac open *.ghw
,或者在建立保存文件open *.gtkw
之后。
(OS X声称像Windows这样的后缀,open命令告诉它......)。
所有这些都给出了与使用包numeric_std的版本相同的答案:
从GTKWave的水平滚动条中,您可以看到模拟时间是所需时间的两倍。
而不是使用std_logic_vector值,你可以使用unsigned与IEEE标准兼容的包numeric_std进行一些轻微的修改,或者将H_Cont和V_Cont转换为范围约束的整数(它将合成得很好),不要忘记转换"00000000000"
适当时为0和... + '1'
至+ 1
。
我会更快地回来,但我在时区GMT-12(明天就在这里)。