**主要介绍本人对周立公公司Fusion StartKit的FPGA的初次使用心得,由于是初次接触和使用,文中不乏部分的个人观点和纰漏的地方,如发现错误,望读者见谅,同时期盼您的参与和支持。
阅读本文前,读者最好对Actel FPGA有一点儿认识,浅尝辄止就足够了,同时,如果是FPGA的初学者,最好就先看一下有关Libero软件的使用,至于你想用什么语言,那就各人喜好,本人就偏爱Verilog。当然,如果你以前使用过其他的FPGA和软件的话,那你使用Fusion就能更加得心应手。读者中高手如云,本人在此班门弄斧,恳请指教。作者Yicheng
第一例
SRAM和串口的应用
1.实验设备
(1) 硬件:PC机,Fusion StartKit 开发板全套
(2) 软件:Libero (Quartus II )
2.应用的器件
(1)SRAM:IS61LV25616
(2)串口
3.实验内容
通过PC机,利用串口发送数据,保存到SRAM中,然后又把数据返回PC机,整个过程主要为了实现串口通信,阐明SRAM的读写方式和操作流程,加强对实验板上各器件之间的联合应用能力。
4.器件介绍
(1)IS61LV25616
IS61LV25616是ISSI公司的一款高速静态随机存取存储器,拥有264,144字,总共4,194,304位的存储空间。该芯片采用ISSI公司高性能的CMOS技术,结合先进的电路设计工艺,具有高性能、低功耗等优点的新型器件。快速存取,兼容TTL接口,三态输出等优势都使其倍受市场的青睐,应用日益广泛。
IS61LV25616有几种不同姆庾埃 没вσ虻刂埔耍 笃渌 茫 蘼勰愕难≡袢绾危 酒 墓δ芤 藕敛焕 獾亩际牵旱刂纷芟撸?/span>A0~A17),输入输出总线(I/O0~I/O15),片选(nCE),输出使能端(nOE),输入使能端(nWE),低字节选择端(nLB),高字节选择端(nUB),电源。
IS61LV25616不但接口简单,控制也比较方便。以下特意从其技术文档中截取了几个时序图来加以说明。
下图是读时序图,从图中可以看出,器件处于读状态时,nCE和nOE为低电平,也就是片选和读操作有效,然后在地址总线有效的情况下输入数据被写入相应的存储空间,整个过程当然不能忽略各信号线的转换时延。由于这是一款16位的存储器,当然少不了高低位选择端nLB,nUB,本例一概把数据写到低8位,那么nLB一直为低电平,至于nUB就不作要求。
读写的过程大同小异,在此不再累赘,下图就是写时序图。
(3) 串口
串口这个词对于广大电子爱好者来说当然是再熟悉不过了,接触过单片机的朋友都知道串口是怎么的一回事,然而这里要介绍的却是有点不同,否则我都不会在此浪费篇幅。
单片机的串口是包含于硬件中,我们只要通过指令控制相应的寄存器,就可以通信无阻,然而FPGA就没有这样的免费午餐。但我们可以通过串口的通信原理,利用硬件语言生成一个拥有串口通信功能的模块,本人为其取名,美其名曰"串口"。
生成的串口模块一定要注意时钟问题,特别是在程序的移植过程中,系统时钟会直接影响串口的通信波特率。同时,串口的波特率也可以在允许的范围内适当修改。
上图是在Q2中的使用例子,只要通过把50M的时钟改为48M的时钟环境,就可以方便地移植到Fusion上来了,当然Fusion套件的例子中也有相应的模块,但在此不敢妄自公开。
程序原码如下:
module UART(rxd,clock,out,end_flag);
input clock; //系统时钟
input rxd; //接收
output[7:0] out; //接收到的8位数据
output end_flag;
reg[7:0] out;
reg end_flag;
reg recclk;//16倍于9600的时钟
reg[8:0]divcnt;//分频系数
reg[9:0]data_buf; //接收数据缓冲
reg[3:0]cnt;
reg[3:0]bitpos; //串行数据当前位
reg[7:0]sbuf;
reg[1:0]state;
parameter st0=2'b00, //状态机定义
st1=2'b01,
st2=2'b11;
// st3=2'b10;
always@(posedge clock) //时钟分频325, 产生9600 16倍的频率
begin //时钟分频162, 产生19200 16倍的频率
if(divcnt<9'd162)
begin
divcnt=divcnt+1'b1;
recclk=1'b0;
end
else
begin
divcnt=1'b0;
recclk=1'b1;
end
end
always@(posedge recclk)//16倍于9600的时钟
begin
case(state)
st0:begin
// end_flag=1'b1;
end_flag=1'b0;
if(rxd==1'b1)
begin
cnt=4'h0;
state=st0;//进入空闲状态
end
else
begin
cnt=cnt+1'b1;
end
if(cnt==4'h2)
begin
state=st1;
cnt=4'h0;
bitpos=0;
end
end
st1:begin
if(cnt==4'hf)
begin
cnt=4'h0;
data_buf[bitpos]=rxd;
bitpos=bitpos+1'b1;
if(bitpos==4'd9)//9个数据
begin
bitpos=4'd0;
state=st2;
end
end
else
begin
cnt=cnt+1'b1;
end
end
st2:begin//进入数据传送状态
// end_flag=1'b0; //下降
end_flag=1'b01;//接收完产生一个上降沿
sbuf=data_buf[7:0];
out=sbuf;
state=st0;
end
default:state=st0;
endcase
end
endmodule
以上程序中重点部分都均以注析,究其原理比较通俗,因此蜻蜓点水,一带而过,不再深入剖析。 |