首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于FPGA的VRAM控制器设计

基于FPGA的VRAM控制器设计

摘要:本文简要介绍了FPGA在雷达系统中的应用,重点阐述了显示子系统中GDC(图形控制器)与VRAM(视频存储器)的接口,以及用FPGA实现VRAM控制器的方法。
一、引言
在信息技术高速发展的现代社会中,数字化的浪潮正席卷各个行业。数字系统的设计方法和设计手段已经有了根本性的变化。在数字系统中,以往的中小规模的数字集成电路已逐渐被超大规模集成电路和可编程逻辑器件所取代。现场可编程门阵列(FPGA)的出现是超大规模集成电路(VLSI)技术和计算机辅助设计(CAD)技术发展的结果。FPGA器件集成度高,体积小,可以通过用户编程来改变其内部逻辑单元之间的连接,以实现不同的功能,满足各种应用的要求。使用FPGA器件可以大大缩短系统的研制周期,降低开发风险和成本,并且系统的可靠性高,升级方便快捷,在无需改动系统硬件环境的前提下,完成性能的改进或功能的改变,实现产品的更新换代。

本文简要介绍了FPGA在雷达系统中的应用,重点阐述了显示子系统中GDC(图形控制器)与VRAM(视频存储器)的接口,以及用FPGA实现VRAM控制器的方法。在雷达信号处理板上,这只是很小的一部分,但却是FPGA的一个非常典型应用。
二、FPGA在雷达信号处理板的应用
信号处理部分是雷达系统的核心,雷达的操作界面以及雷达回波的处理算法的实现都是在信号处理单元完成的。信号处理单元是非常复杂的,主要包括雷达回波的处理和交互式操作界面的处理这两大部分。雷达回波的处理部分又可分为:信号的编码、采样、高速缓存、距离和方位平均,坐标变换等模块,是通过对FPGA编程来实现的。交互式操作界面的处理主要是通过嵌入式处理器来实现的,它根据操作者的输入来控制雷达回波的处理部分来完成量程切换、距离和方位测量、报警区的设定和报警条件的检测、以及目标轨迹的标绘等功能,还提供了与其它设备的通信接口,如GPS、罗径、测深仪、计程仪等等,使雷达显示器成为一个导航信息的综合显示器。在这一部分中,FPGA主要完成与辅助电路和外部设备的通信接口,如SPI接口、罗径接口、跟踪球接口等。

回波的处理和交互式操作界面的处理都需要与视频缓冲区接口,以便通过视频缓冲区将回波和各种辅助测量的图形送到显示器上。在我们的方案中,图形、文字的显示是由处理器向GDC写入各种命令和参数,再有GDC产生对视频缓冲区的读改写操作的地址和数据,通过VRAM的接口控制器最终完成对视频缓冲区的访问;同时又要完成刷新和传送操作。
三、VRAM概述
VRAM是视频存储器的简称。在显示系统中,VRAM是用来存储最终要显示到屏幕上的图形数据。以CRT为显示器件的显示系统中,在显示时,视频数据是在行场同步信号的控制下,逐点串行输出到CRT单元,这是一个对存储器进行串行访问的过程。而图形的绘制,是在处理器的控制下,由GDC按照其指令,对存储器内的存储单元进行读改写操作,从而将图形数据存储到存储器内,这是一个对存储器的随机访问过程。为了避免这两种访问过程的冲突,就出现了这样一种存储器,称为视频存储器,简称VRAM。它是一个双口RAM,一个并行访问数据口,一个串行访问数据口,但是只有一套地址口;其内部除了有通常的存储阵列外,还有一个SAM(串行访问存储器),其数据位宽度与存储阵列的位宽度一样,地址宽度与列地址的宽度一样。这样,除了在把即将串行输出的一行存储单元的内容锁存到SAM和对动态存储器进行刷新的时候,都可以进行图形的绘制,即对并行口的访问;通常在一行的有效显示期到来前,使VRAM工作于传送状态,完成VRAM内某一行数据锁入SAM中。这就使系统更容易实现,也提高了图形绘制的效率。在我们的设计中,选用了OKI的MSM5416262芯片作为视频存储器。它的三种工作状态如图1,2,3所示:




四、GDC概述
GDC是图形控制器的简称,在带有显示系统的设计中,一般都会用到它,它是图形显示系统的核心,我们选择了NEC公司的UPD72020芯片作为图形控制器。通常GDC是不能单独形成一个显示系统的,必须和处理器系统、视频存储器共同完成图形的绘制和显示功能。GDC根据处理器写入的初始化命令产生相应的行场同步信号,根据绘图命令产生对VRAM进行访问的控制时序,并提供可以进行VRAM刷新的时序,将一个扫描行所要输出的数据锁存到VRAM内的SAM中的时序。但是,GDC没有与VRAM的直接接口,因此需要在GDC与VRAM之间加入一层接口电路,这就是我们所要做的VRAM控制器。GDC的3种工作状态如图4,5所示:


①GDC的AD0-AD15、A16、A17输出画图地址,在周期的第一个时钟(E1)输出地址,在RAS下降沿锁存。②在E2到E3的一个时钟周期,GDC输出DBIN信号,从VRAM图形缓冲区读出16bit数据。③在E3的一个时钟周期对读出的数据加以修改。④在E4的一个时钟周期,GDC将修改的数据输出,在DBIN延时产生的VRAM的图形缓冲区的写信号(WE)的上升沿,写入VRAM中。

在GDC的BLANK信号由‘1’变为‘0’后的两个GDC时钟周期,即GDC的DT信号为‘0’时为GDC要求的数据传送周期。在GDC的HSYNC信号为‘1’其间是刷新周期。
五、VRAM控制器的实现
由GDC和VRAM构成的显示存储系统的典型结构如图6所示:


GDC对VRAM的控制过程包括:读改写周期、传送周期、刷新周期,这与VRAM的工作状态是一一的对应。从上图中可以看出,除了GDC的数据线可以直接与VRAM的并行口连接外,GDC其它的信号不能直接与VRAM相连。
地址线:GDC输出的地址线和数据线是复用的,并且没有分出行地址和列地址,而VRAM的存储单元是按照行地址和列地址确定的阵列方式排布的;因此,首先要将GDC的AD0~AD15和A16、A17上的地址,在地址有效期锁存,然后按照VRAM的时序要求分为行地址和列地址输出到VRAM的地址线上。
控制信号:GDC的HSYNC、DT、2CCLK信号定义了GDC对VRAM的3种操作。接口电路应当根据这三种信号的组合,判定GDC的当前操作,然后再按照VRAM的时序要求,产生相应的控制信号输出到VRAM。这就需要定义一个能够完整描述GDC工作状态的状态机,针对状态机的各个状态,定义VRAM控制信号的状态,我们将状态划分s0,rfs1,rfs2,rfs3,dt1,dt2,dt3,dt4, dt5, rmw1,rmw2,rmw3, rmw4, rmw5;其中,s0为初始状态,rfs1~3为刷新周期,dt1~5为传送周期,rmw1~5为读改写周期。
状态的转换需要由时钟来同步,因此,在描述状态机之前,要确定它的时钟。虽然状态机本身与所选的时钟之间没有必然的联系,但是由于要做的是GDC和VRAM的接口,就必须正确选择时钟,以使状态机能同时满足GDC和VRAM的时序要求,同时还可以使设计简化。由GDC的时序可以看出,GDC的各种工作状态都是由2CCLK同步的,它的频率是6.346MHz,考虑VRAM的写信号的时间要求,我们选择25.744MHz的时钟作为状态机的时钟。这样就完成了VRAM控制器的描述。
另外,在应用FPGA的设计中,设计手段的选择也是至关重要的。原理图输入的设计方法容易入手,逻辑单元间的连接明确,但是其实现的逻辑功能难于理解,模块的维护和升级很费时也很困难,当设计软件升级时,原有的设计就有可能不再被支持了,造成资源的浪费。用VHDL硬件描述语言进行设计,虽然需要花时间了解该语言的规范,但是用它描述的设计,其功能明确易懂、并且其代码可以重用;由于VHDL语言的规范性,使得新版本的编译器可以兼容原有的设计,因此可以实现资源共享、降低成本和风险。为此,我们的设计是用VHDL硬件描述语言实现的。程序详见附录A。
结束语
以上简要介绍了采用FPGA技术设计的VRAM控制器。这种设计方式可以将以前需要多块集成芯片的电路设计到一片大规模可编程逻辑器件中,大大减少了电路板的尺寸,增强了系统的可靠性和设计的灵活性。而且用VHDL产生VRAM时序的方法简单、易读,并且易于修改。在代码中只须修改一些时序参数就能产生任意时序的波形,具有很好的可重用性。在实际设计中的FPGA芯片,我们选用Xilinx公司的spartanⅡ的XC2S200芯片。辽宁无线电二厂自行开发的信号处理板,其硬件功能设计都是由FPGA完成,已经获得了成功。

参考文献
《可编程ASIC设计及应用》电子科技大学出版社孟宪元 李广军 编著
《Xilinx ISE 5.X使用详解》人民邮电出版社王诚 薛小刚 钟信潮 编著
《用VHDL设计电子线路》清华大学出版社 边计年 薛宏熙 译

附录A:VHDL硬件语言描述
VRAM控制器的VHDL语言描述如下:
entity CHRVRAM is
Port ( GDC_ADDRESS : in std_logic_vector(17 downto 0);
GDC_RAS,GDC_DBIN,GDC_DT,GDC_HSYNC : in std_logic;
GDC_2CLK,CLK : in std_logic;
CHR_ADD : out std_logic_vector(8 downto 0);
CHR_RAS,CHR_CAS,CHR_TRG,CHR_WE,CHR_DSFut std_logic );
end CHRVRAM;
architecture Behavioral of CHRVRAM is
signal chr_trgtemp: std_logic;
signal dbin_dlya: std_logic_vector(3 downto 0);
signal dbin_dlyb: std_logic;
signal gdc_a: std_logic_vector(17 downto 0);
signal chr_addrc ,chr_adden: std_logic;
type state_type is (s0,rfs1,rfs2,rfs3,dt1,dt2,dt3,dt4,dt5,
rmw1,rmw2,rmw3, rmw4, rmw5);
signal state:state_type:=s0;
begin
gdcaddres_latch: process(CLK, GDC_RAS)
begin
if GDC_RAS'event and GDC_RAS ='0' then
gdc_a <= GDC_ADDRESS;
end if;
end process;
cvram_cycle: process(GDC_RAS,CLK)
begin
if GDC_RAS='1' then
CHR_RAS <= '1';
CHR_CAS <= '1';
chr_addrc <= '1';
chr_adden <= '0';
state<= S0;
elsif CLK'event and CLK ='1' then
case state is
when S0 => if GDC_RAS = '0' then
if GDC_HSYNC = '1'then
state <= rfs1;
elsif GDC_DT = '0' then
chr_adden <='1';
state<= dt1;
else
chr_adden <='1';
state<= rmw1;
end if;
end if;
when rfs1 => state <=rfs2;
CHR_CAS<='0';
when rfs2 => state <=rfs3;
CHR_RAS<='0';
when rfs3 => null;
when dt1 => state <=dt2;
CHR_RAS<='0';
when dt2 => state <=dt3;
chr_addrc <='0';
when dt3 => state <= dt4;
CHR_CAS <= '0';
when dt4 => state <= dt5;
chr_adden <= '0';
when dt5 => null;
when rmw1 => state <= rmw2;
CHR_RAS<= '0';
when rmw2 => state <= rmw3;
chr_addrc <= '0';
when rmw3=> state <= rmw4;
CHR_CAS<= '0';
when rmw4 => state <= rmw5;
chr_adden <= '0';
when rmw5=> null;
when others=> null;
end case;
end if;
end process;
CHR_ADD <= (others => 'Z') when chr_adden = '0' else
gdc_a(17 downto 9) when chr_addrc = '1' else
gdc_a(8 downto 0);
chr_trgtemp <= '0' when state = dt1 or state = dt2 else
'1';
CHR_TRG <= chr_trgtemp and GDC_DBIN;
CHR_DSF <= '0' when state = dt1 or state = dt2 else
'0' when state = rmw1 or state = rmw2 else
'0' when state = rmw3 or state = rmw4 else
'1' ;
dbindelay: process(GDC_2CLK)
begin
if GDC_2CLK'event and GDC_2CLK = '1' then
dbin_dlya(0) <= GDC_DBIN;
dbin_dlya(1) <= dbin_dlya(0);
end if;
end process;
dbindelay1: process(GDC_2CLK)
begin
if GDC_2CLK'event and GDC_2CLK = '0' then
dbin_dlyb <= dbin_dlya(1);
dbin_dlya(2) <= dbin_dlya(0);
end if;
end process;
dbindelay2: process(CLK)
begin
if CLK'event and CLK = '1' then
dbin_dlya(3) <= dbin_dlya(2);
end if;
end process;
we_delay: process(CLK)
begin
if CLK'event and CLK = '0' then
CHR_WE <= dbin_dlya(3) or dbin_dlyb;
end if;
end process;
end Behavioral;

作者:王敏,李波
记录学习中的点点滴滴,让每一天过的更加有意义!
返回列表