FPGA设计提高班培训实验指导手册_V1.0

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

FPGA应用设计高级实验指导
目录
FPGA应用设计高级实验指导 (1)
目录 (1)
实验一 VGA接口控制器 (3)
一实验目的: (3)
二实验内容: (3)
三实验原理说明: (3)
1、显示器接口 (3)
2、显示器基本知识 (5)
3、显示器工作时序SuperVGA timing (6)
4、系统结构示意图 (9)
5、硬件设计方法 (9)
四实验要求: (9)
实验二SRAM控制器 (12)
一实验目的: (12)
二实验内容: (12)
三实验原理说明: (12)
1、SRAM硬件结构 (12)
2、SRAM控制时序 (13)
3、SRAM控制器实现方法 (14)
4、用SRAM实现FIFO的功能(选作) (16)
四补充: (16)
1、 SRAM仿真模型: (16)
2、开发板SRAM管脚映射 (17)
实验三SRAM应用――图象缓冲、变换 (19)
一实验目的: (19)
二实验内容: (19)
三实验原理说明: (19)
1、输入数据结构――数字视频格式 (19)
2、实验任务 (20)
四硬件系统设计方法: (20)
1、分析系统硬件是否满足要求 (20)
2、规划系统功能框图 (21)
3、规定各部分模块的接口 (21)
4、分别设计各个小模块 (22)
四仿真方法 (25)
1、如何使用modelsim读文本文件 (25)
2、如何使用modelsim写文本文件 (26)
3、如何调用sram仿真模型 (27)
实验三整型DCT的硬件实现 (28)
一实验目的: (28)
二实验内容: (28)
三实验原理: (28)
四硬件系统设计方法: (30)
实验一 VGA接口控制器
一实验目的:
1、熟悉quartusII锁相环的使用
2、熟悉VGA显示时序的工作原理
3、通过设计VGA显示时序,熟悉较复杂时序逻辑的硬件设计
二实验内容:
在硬件上实现VGA显示输出
三实验原理说明:
显示器因为其输出信息量大,输出形式多样等特点已经成为现在大多数设计的常用输出设备。

在FPGA 的设计中可以使用很少的资源,就产生VGA各种控制信号。

1、显示器接口
首先有必要对显示器(VGA)的硬件接口作介绍:
开发板包括VGA显示功能与接口,电路原理图见图1-1所示。

可以用普通的VGA电缆连接到电脑的液晶或电子管显示器上
图 1-1: VGA 电路原理图与接口定义
控制信号有: Red (R), Green (G), Blue (B), Horizontal Sync (水平扫描HS), Vertical Sync (垂直扫描 VS), 表1-1为VGA信号连接FPGA的管脚映射图
表 1-1: VGA信号连接FPGA的管脚映射图
Signal FPGA Pin
Red (R) 160
Green (G) 159
Blue (B) 158
Horizontal Sync (HS) 156
Vertical Sync (VS) 141
每一个色线都有3位的色彩分别为红,绿,蓝。

串接270的电阻使色彩信号线阻抗匹配,可以正常的显示出预想的颜色。

HS和VS信号是 TTL 电平.R, G, B 信号不同的组合可以显示出8种颜色,如表2-2所示。

表 2-2: 3-Bit Display Color Codes
2、显示器基本知识
(1)像素与分辨率
显示器的显示方式有两种: A/N(Alphabet/Number:字符/数字)显示方式和APA (All Point Addressable:全点寻址)显示方式,即文本显示方式和图形显示方式。

A/N 方式已淘汰不用,目前微机都采用APA 图形方式。

显示器上输出的一切信息,包括数值、文字、表格、图象、动画等等,都是由光点(即像素)构成的。

组成屏幕显示画面的最小单位是像素,像素之间的最小距离为点距(Pitch)。

点距越小像素密度越大,画面越清晰。

显示器的点距有0.31mm、0.28mm、0.24mm、0.22mm 等多种。

分辨率指整屏显示的像素的多少,是衡量显示器的一个常用指标。

这同屏幕尺寸及点距密切相关,可用屏幕实际显示的尺寸与点距相除来近似求得。

点距为0.28mm 的15英寸显示器,分辨率最高为1024×768。

(2)显示器尺寸
显示器屏幕尺寸以对角线来度量,常用的显示器有14、15、17、19、21 英寸等。

显示器水平方向长度与垂直方向高度之比一般为4:3。

(3)扫描频率
显示器采用光栅扫描方式,即轰击荧光屏的电子束在CRT 屏幕上从左到右(受水平同步信号HSYNC 控制)、从上到下(受垂直同步信号VSYNC 控制)做有规律的移动。

光栅扫描又分逐行扫描和隔行扫描。

电子束采用光栅扫描方式,从屏幕左上角一点开始,向右逐点进行扫描,形成一条水平线;到达最右端后,又回到下一条水平线的左端,重复上面的过程;当电子束完成右下角一点的扫描后,形成一帧。

此后,电子束又回到左上方起点,开始下一帧的扫描。

这种方法也就是常说的逐行扫描显示。

而隔行扫描指电子束在扫描时每隔一行扫一线,完成一屏后再返回来扫描剩下的线,这与电视机的原理一样。

隔行扫描的显示器比逐行扫描闪烁得更厉害,也会让使用者的眼睛更疲劳。

目前微机所用显示器几乎都是逐行扫描。

完成一行扫描所需时间称为水平扫描时间,其倒数称为行频率;完成一帧(整屏)扫描所需的时间称为垂直扫描时间,其倒数为垂直扫描频率,又称刷新频率,即刷新一屏的频率。

常见的有60Hz、75Hz 等,标准VGA 显示的场频60Hz,行频为31.5kHz。

(4)显示带宽
带宽则指显示器可以处理的频率范围。

如果60Hz 刷新频率的VGA 方式,其带宽达640×480×60=18.4MHz;70Hz 刷新频率1024×768 分辨率的SVGA 方式,其带宽达 1024×768×70=55.1MHz。

3、显示器工作时序SuperVGA timing
在VGA 中,水平同步脉冲在光栅扫描线需要回到水平开始位置也就是屏幕的左边的时候插入,垂直同步脉冲在光栅扫描线需要回到垂直开始位置也就是屏幕的上方的时候插入。

复合同步脉冲是水平同步脉冲与垂直同步信号的组合。

RGB 为像素数据,在没有图像投射到屏幕时插入消隐信号,当消隐有效时,RGB 信号无效。

(1)水平时序
在水平时序中,包括以下几个时序参数(见下页图):水平同步脉冲宽度(B);水平同步脉冲结束到水平门(可视区)的开始之间的宽度(C,后沿);一个视频行可视区域的宽度(D);一个完整的视频行的宽度(A),从水平门结束到下一个水平同步脉冲的开始(E,前沿)。

(2)垂直时序
在垂直时序与水平时序类似,包括以下几个不同的时序参数(见下页图):垂直同步脉冲宽度(P);垂直同步结束到垂直门的开始之间的宽度(Q);一个视频帧可是区域的宽度(R);一个完整视频帧的宽度(O),从垂直门结束到下一个垂直同步脉冲的开始(S)。

(2)水平时序与垂直时序的组合
因为显示器是逐行扫描,扫描到一列的一点到扫描到这列的下一点的时间是水平扫描一行的时间,如下图所示:水平扫描一行的时间是A=26.4us,垂直桢长628,所以垂直扫描一列的时间O=26.4X628=16.5792ms
Horizontal :
______________ _____________
| | |
_______________| VIDEO |_______________| VIDEO (next line)
___________ _____________________ ______________________
|_| |_|
B C <------D-----><-E->
<----------A---------->
Vertical :
______________ _____________
| | |
_______________| VIDEO |_______________| VIDEO (next frame)
___________ _____________________ ______________________
|_| |_|
P Q <------R-----><-S->
<----------O---------->
800*600 @ 60Hz:
Fh (kHz) :37.88
A (us) :26.4 水平扫描一行的时间
B (us) :3.2 HSYNC的脉冲宽度
C (us) :2.2 后沿
D (us) :20.0 可视区
E (us) :1.0 前沿
Fv (Hz) :60.32
O (ms) :16.579 垂直扫描一行的时间
P (ms) :0.106 VSYNC的脉冲宽度
Q (ms) :0.607 后沿
R (ms) :15.84 可视区
S (ms) :0.026 前沿
Horizonal timing information:
Vertical timing information:
*当有效时间超过了vsync 信号的上升沿,因此前沿为-1
4、系统结构示意图
5、硬件设计方法
(1)设置水平扫描计数,计数范围是水平帧长。

(2)用水平扫描计数产生水平同步信号
(3)水平每次扫描完一行,垂直扫描计数加1
(4)用垂直扫描计数产生水平同步信号
(5)当水平扫描和垂直扫描都在可视区范围内时按照行场坐标输出想显示的图形 设计技巧:将水平计数和垂直计数的零,都从可视区的开始计数。

这样在显示输出时可以指定起始坐标都是零。

四 实验要求:
1、在了解VGA工作原理与显示时序的基础上考虑如何用硬件描述语言实现
2、画出程序流程图
3、完成硬件描述语言设计,建立仿真文件。

50MHZ
CLOCK HSYNC VSYNC
4、软件仿真通过,下载到FPGA上进行硬件调试
参考代码(产生VGA时序):
parameter H_PIXELS = 'd806,//'d640,
H_FRONTPORCH = 'd37,//16,
H_SYNCTIME = 'd128,//'d96,
H_BACKPORCH = 'd85,//48,
H_SYNCSTART = 'd843,// H_PIXELS + H_FRONTPORCH,
H_SYNCEND = 'd971,// H_SYNCSTART + H_SYNCTIME,
H_PERIOD = 'd1056,//H_SYNCEND + H_BACKPORCH,
V_LINES = 'd604,//48,
V_FRONTPORCH = -1,//'d10,
V_SYNCTIME = 'd4,//2,
V_BACKPORCH = 'd21,//33,
V_SYNCSTART = 'd603, //V_LINES + V_FRONTPORCH,
V_SYNCEND = 'd607,// V_SYNCSTART + V_SYNCTIME,
V_PERIOD = 'd628; //V_SYNCEND + V_BACKPORCH;
reg [10:0] hcnt,vcnt;//水平、垂直计数
reg enable,hsyncint;
always @ (posedge clock or negedge resetn)//每个时钟对水平扫描计数
if(!resetn)
hcnt <= 0;
else if(hcnt<H_PERIOD)
hcnt <= hcnt + 1;
else
hcnt <= 0;
always @ (posedge clock or negedge resetn) //产生水平同步脉冲
if(!resetn)
hsyncint<= 1;
else if(hcnt >= H_SYNCSTART && hcnt < H_SYNCEND)
hsyncint <= 0;
else
hsyncint<= 1;
assign hsync = hsyncint;
always @ (posedge hsyncint or negedge resetn) //每一行水平计数完毕垂直计数加1
if(!resetn)
vcnt<=0;
else if(vcnt < V_PERIOD)
vcnt <= vcnt + 1;
else
vcnt<=0;
always @ (posedge hsyncint or negedge resetn) //产生垂直同步脉冲
if(!resetn)
vsync <=1;
else if(vcnt >= V_SYNCSTART && vcnt < V_SYNCEND)
vsync <=0;
else
vsync <=1;
always @ (posedge clock or negedge resetn) //产生输出使能信号为1时输出if(!resetn)
enable<=0;
else if(hcnt >= H_PIXELS || vcnt >= V_LINES)
enable<=0;
else
enable<=1;
实验二SRAM控制器
一实验目的:
1、学习异步设备的控制方法
2、学习双向总线的设计
3、学习SRAM的工作原理
4、学习SRAM的操作时序
5、学习FIFO的工作原理
二实验内容:
必做
1、编写程序在硬件上实现通过按键输入数据写到SRAM中,再把数据读出,输出到led 上显示
选作
1、编写一个256 Bytes,8位宽的SRAM读写控制器
2、用这个控制器实现FIFO的功能
3、在modelsim中实现验证
三实验原理说明:
1、SRAM硬件结构
SRAM属于典型的异步逻辑控制设备,所谓的异步,是指SRAM芯片不用时钟来控制。

SRAM芯片的管脚说明如下(以sypress公司的CY7C1079AV33,2MByte型SRAM为例): CE1_N,CE2_N:片选;OE_N:写使能;WE_N:读使能; A0-A20:地址;IO0-IO7:数据
SRAM真值表
2、SRAM控制时序
因为SRAM是异步设备,所以没用专用的时钟管脚,SRAM的读时序如下:
当SRAM芯片检测到OE_N的下降沿时并且WE_N是高电平,准备读数据,有一个延时之后数据读出,之后当检测到OE的上升沿,有一个延时之后输出数据关闭。

SRAM的写时序:当写时OE_N保持低电平
当SRAM检测到WE_N的上升延时,把数据总线的数据写入SRAM中。

3、SRAM控制器实现方法
从上面的说明可以看出,SRAM的时序并不复杂,下面介绍如何用硬件描述语言实现这个SRAM控制器。

(1)时钟处理
虽然SRAM是异步设备,但是需要用时钟来产生SRAM所需要的波形。

SRAM是高速CMOS工艺,可以在50MHZ的频率下工作,使用开发板上的50MHZ时钟不用分频。

(2)硬件结构
(3)双向总线的处理
因为IO0-IO7是SRAM的数据,既可以写入又可以读出数据。

作为控制器,要在SRAM写数据时,对于控制器是输出,要把双向总线打开。

其他时间应该关闭双向总线。

(4)程序示例(先向sram写一个数据再读出来)
begin
state
)
(
case
s1: begin
we<=1;
oe<=1;
state<=s2;
end
s2: begin
we<=0;
oe<=1;
state<=s3;
addr<=addr+1;
data_reg<=data_in;
end
s3: begin
we<=1;
oe<=1;
state<=s4;
end
s4: begin
we<=1;
oe<=0;
data_out<=data;
state<=s1;
end
endcase
end
根据程序画出波形图:
S1—S3 :WE从1变到0再变到1,是一个写准备,写的过程,WE的上升沿把数据写入S3-S4-S1:OE从1变到0再变到1,是一个读,读输出的过程,当OE从0回到1时可以在数据总线上取出数据
那么除了写数据以外的状态以外双向总线要为高阻态。

data=(state2||state3)?data_reg:8’hzz
4、用SRAM实现FIFO的功能(选作)
FIFO即先入先出寄存器,或移位寄存器,当输入数据后先面的数据向前移位,当数
据存满,再进入新的数据时,最开始的数据输出。

如下图表示
输入数据地址1 2 3 4 5 输出
x x x
x
x
1 1 x x x x x
2 2 1 x x x x
3 3 2 1 x x x
4 4 3 2 1 x x
5 5 4 3 2 1 x
6 6 5 4 3 2 1 用SRAM来实现:
输入数据地址1 2 3 4 5 输出
x x x x
x
x
1 1 x x x x x
2 1 2 x x x x
3 1 2 3 x x x
4 1 2 3 4 x x
5 1 2 3 4 5 x
6 6 2 3 4 5 1 说明:
写地址1----读地址2----写地址2---读地址3----写地址3----读地址4……
在此过程中需要寄存器来缓冲外界输入数据,请同学自行考虑具体方法
四补充:
1、 SRAM仿真模型:
module sram(addr,data,we,oe,ce1,ce2) ;
input[7:0]addr;
inout[7:0]data;
input we,oe,ce1,ce2;
wire[7:0] data;
reg[7:0] mem[255:0];
assign data=(!ce1&&ce2&&!oe&&we)?mem[addr]:8'hzz;//从sram输出数据wire[7:0]temp=mem[addr];
always @(posedge we)//向sram写入数据
mem[addr]<=data;
endmodule
通过sram仿真模型我们可以看到sram是如何操作的。

2、开发板SRAM管脚映射
采用ISSI公司的高速异步SRAM,容量为256K×16Bit。

字节使能信号独立,可以对每一个Byte 操作。

地址信号
SRAM管脚名称 FPGA对应管脚号外部总线信号名称
EA1 A0 PIN_135
A1 PIN_128
EA2
EA3 A2 PIN_127
EA4 A3 PIN_126
EA5 A4 PIN_125
EA6 A5 PIN_124
EA7 A6 PIN_98
A7 PIN_95
EA8
EA9 A8 PIN_94
EA10 A9 PIN_93
A10 PIN_88
EA11
EA12 A11 PIN_106
EA13 A12 PIN_107
A13PIN_108 EA14
EA15 A14 PIN_114
EA16 A15 PIN_113
EA17 A16 PIN_132
EA18 A17 PIN_133
数据信号
SRAM信号名称 FPGA对应管脚号外部总线信号名称
sram_db[0] PIN_122 ED0
sram_db[1] PIN_121 ED1
sram_db[2] PIN_120 ED2
sram_db[3] PIN_119 ED3
sram_db[4] PIN_105 ED4
sram_db[5] PIN_104 ED5
sram_db[6] PIN_101 ED6
sram_db[7] PIN_100 ED7
sram_db[8] PIN_78 ED8
sram_db[9] PIN_79 ED9
sram_db[10] PIN_82 ED10
sram_db[11] PIN_83 ED11
sram_db[12] PIN_84 ED12
sram_db[13] PIN_85 ED13
sram_db[14] PIN_86 ED14
sram_db[15] PIN_87 ED15
控制信号
SRAM信号名称 FPGA对应管脚号
CE# PIN_123
OE# PIN_118
WE# PIN_99
BE0 PIN_116
BE1 PIN_117
注:
IO8-IO15
IO0-IO7
BE0 BE1
H H Z Z
L H 有效Z
H L Z 有效
L L 有效有效
实验三SRAM应用――图象缓冲、变换
一实验目的:
1 实践sram控制器的操作原理
2 熟悉存储器乒乓的设计原理
3 熟悉运用modelsim进行系统的前仿真
二实验内容:
假设有一路从A/D采样的图象数据(ITU.656格式)输入到FPGA中,将图像数据变换分块存储到sram中然后再从sram中读出来按照格式变换为ITU.656格式输出。

由于sram读写不能同时操作,所以设置两片sram,sram1写时,对sram2作读操作。

写完sram1后交换读写顺序:读sram1,写sram2。

这就是所谓的乒乓操作。

三实验原理说明:
1、输入数据结构――数字视频格式
目前数字视频的国际标准是国际电联的ITU.656格式,其标准格式是采用了9个信号来传递视频。

EA V和SA V是时间参考信号,其格式为:FF 00 00 XY,其定义如下。

SAV_EVEN=8'H80
EAV_EVEN=8'H9D
SAV_ODD =8'HC7
EAV_ODD =8'HDA
视频输出的亮度和色度比例,即YCbCr的比例为为4:2:2。

其他两种常用的比例是4:2:0和4:1:1,示意图如下。

ITU.656格式输出的视频比例是4:2:2,顺序是。

.
2、实验任务
我们的目的:
1 当检测到每一帧的起始信号(SA V)时把4:2:2的图象格式变为4:2:0的图象格式
2 把每帧图象中的Y CB CR 按照16x16块的Y、8x8块的CB,CR提取出来
3 将图象按找宏块的顺序存储到第一片sram中(这样是为了做图象压缩编码方便)
4 在第一步时当检测到每一帧的起始信号(SA V)将另外一个sram中的数据取出来添到相应的Y CB CR的位置,还原成ITU656格式输出。

四硬件系统设计方法:
1、分析系统硬件是否满足要求
本系统采用SAA7113H作为图像采集芯片,采入数据8位位宽,一位输入时钟;采用SAA7121/SAA7128作为图象编码芯片,输入数据8位位宽,一位输出时钟。

图象尺寸720x576,4:2:2格式输入,每一场有720+360+360=1440个数据,图
象输入时变为4:2:0格式,则存储一帧图像需要(720+360)x576=622080 Byte 约合607.5KB。

硬件条件:两片单片为2MB 的sram 可以支持双ram 作乒乓操作。

结论硬件符合要求
2、规划系统功能框图
通过分析发现系统可以由4部分构成:
其中只有FPGA 控制部分是要求做程序设计的模块。

仔细分析FPGA 控制部分模块,发现其还可以细分:(1)检测数据产生ram 的读写和相应的地址数据(2)做乒乓处理模块。

其中第一部分还可以细分成几个小模块,如下所示
3、规定各部分模块的接口
根据功能框图很容易规定每个模块所需要的接口
4、分别设计各个小模块
1、检测每帧的起始信号(SAV)和结束信号(EAV)
每一帧的开始信号是FF 00 00 SA V,结束信号是FF 00 00EA V,每帧图象分为奇场(odd)和偶场(even)。

用以下标志位来标记是奇场或偶场,开始或结束。

SAV_EVEN=8'H80
EAV_EVEN=8'H9D
SAV_ODD =8'HC7
EAV_ODD =8'HDA
用两个状态信号even_state和odd_state分别标志奇场和偶场,当检测到开始信号时,相应的状态信号拉高
偶场开始与结束,奇场同理
……..
以下的过程可以用一个状态机来实现
但是如果当检测到pdata==eav时even_state(odd_state)再拉到低电平,那么会把FF 00 00 EA V这样的结束位也包括到even_state (odd_state)的状态中,这是我们不希望的。

所以要加入两个计数变量,当计到1439时(一场图象的长度)even_state (odd_state)就拉低。

case(state)
4'd0:begin
if(pdata==8'hff) state<=4'd1;
else state<=4'd0;
end
4'd1:begin
if(pdata==8'h00) state<=4'd2;
else state<=4'd0;
end
4'd2:begin
if(pdata==8'h00) state<=4'd3;
else state<=4'd0;
end
4'd3:begin
if(pdata==SAV_EVEN)
begin
state<=4'd4;even_state<=1'b1;
end
else if(pdata==SAV_ODD)
begin
state<=4'd5;odd_state<=1'b1;
end else state<=4'd0;
end
4'd4:begin
if(pdata==8'hff) state<=4'd6;
else state<=4'd4;
end
4'd6:begin
if(pdata==8'h00) state<=4'd7;
else state<=4'd4;
end
4'd7:begin
if(pdata==8'h00) state<=4'd8;
else state<=4'd4;
end
4'd8:begin
if(pdata==EAV_EVEN) begin state<=4'd0;end
else state<=4'd4;
end
4'd5:begin
if(pdata==8'hff) state<=4'd9;
else state<=4'd5;
end
4'd9:begin
if(pdata==8'h00) state<=4'd10;
else state<=4'd5;
end
4'd10:begin
if(pdata==8'h00) state<=4'd11;
else state<=4'd5;
end
4'd11:begin
if(pdata==EAV_ODD)
begin state<=4'd0;end
else state<=4'd5;
end
endcase
if(state_count==11'd1439
&&even_state)
begin even_state<=0;end
else if(state_count==11'd1439 &&odd_state)
begin odd_state<=0;end
2、分离Y CB CR信号

3、设计乒乓读写两片ram
在写sram模块中,当写完sram时会产生一个sele的信号,当sele 变化时表示一片sram已经写完,这时交换读写顺序。

一开始sele是低电平,写sram1,读sram2,当sram1写完sele拉高;之后写sram2,读sram1,写完sram2再拉低······
当写sram1时sele是低,当写sram2时sele是高。

得到以下程序:
//两片ram选择
Moduleram_sele(data1,addr1,wr1,rd1,ce1,data2,addr2,wr2,rd2,ce2 ,sele,data1ram,addr1ram,wr1ram,rd1ram,ce1ram,data2ram,addr2ram ,wr2ram,rd2ram,ce2ram);
//port
input [7:0] data1;
input [20:0] addr1,addr2;
input
wr1,wr2,rd1,rd2,ce1,ce2,sele;
output [7:0] data2;
inout [7:0] data1ram,data2ram;
output [20:0] addr1ram,addr2ram;
output
wr1ram,wr2ram,rd1ram,rd2ram,ce1ram,ce2ram;
wire [7:0] data2,data1ram,data2ram;
//sele=0时写ram1,读ram2;sele=1时写ram2,读ram1
assign data1ram=(!sele)?data1:8'hzz;
assign addr1ram=(!sele)?addr1:addr2;
wire wr1ram=(!sele)?wr1:wr2;
wire rd1ram=(!sele)?rd1:rd2;
wire ce1ram=(!sele)?ce1:ce2;
assign data2ram=(sele)?data1:8'hzz;
assign addr2ram=(sele)?addr1:addr2;
wire wr2ram=(sele)?wr1:wr2;
wire rd2ram=(sele)?rd1:rd2;
wire ce2ram=(sele)?ce1:ce2;
assign data2=(sele)?data1ram:data2ram;
endmodule
四仿真方法
仿真是整个设计所必不可少的环节,在计算机中仿真成功可以验证程序的逻辑正确。

仿真做每一个小模块都必须要做的工作,只有每个小模块的功能正确了才可能搭建出正确的硬件系统,同时在软件中也能简化今后在硬件上调试的工作量。

在较复杂的设计中一般采用modelsim软件或者cadence的nc-verilog软件,在本例中我们使用modelsim进行仿真。

1、如何使用modelsim读文本文件
从刚才的计算可以看出一帧图象的数据量很大,使用传统的方法在测试文件中指定输入数据是不可能的。

我们用其他软件比如excel,matlab生成图象输入数据,保存为.dat 文件存好:
比如:数据格式为:
之后在modelsim中使用如下语言调用文本,将文本中数据存放到一个数组中:
reg [0:7] mm [0:1670399];
reg [21:0] i;
wire [8*25-1:0] file_name;
assign file_name = "E:/intra/in/div.dat";
always #20 clk=~clk;
begin
$readmemh(file_name,mm);
end
always @ (negedge clk)//这样就得到了每个周期产生一个数据数据
if(!rst)
begin
i<=0;
end
else
begin
i<=i+1;
pdata<=mm[i];
end
2、如何使用modelsim写文本文件
同样的,图象的输出数据量也很大,我们用传统的方法去看输出波形也是不可靠的,
我们需要把结果也打印到文本中,与行为模型(或c语言版本的程序)所产生的标准输
出向量对比文件,这样可以很准确的指导结果是否正确。

例如:以下程序把读写文件结合
module test8;
reg [0:2] mm [0:63];
reg [0:2] mm1 [0:63];
integer Vec_File,i;
wire [8*25-1:0] file_name;
initial
begin
for(i=0;i<64;i=i+1)
mm[i]=3'b111;
end
assign file_name = "E:/intra/in/div1.dat";
initial
begin
Vec_File=$fopen(file_name);
for (i=0;i<64;i=i+1)
$fdisplayh(Vec_File,"%h ",mm[i]);//写文件
$display("file generated");
$fclose(Vec_File);
$readmemh(file_name,mm1);//读文件
for (i=0;i<64;i=i+1)
$display("mm1[%d]= %d",i,mm1[i]);
end
endmodule
3、如何调用sram仿真模型
在上一个实验中已经给出了sram的仿真模型,仿真模型故名思意只能用来仿真的,在测试模块中怎么调用呢?
在模块中使用如下语言:
sram1( //前面的代表引用模块的名称
sram
.data
(data1ram),
(addr1ram),
.addr
.wr (wr1ram),
.rd (rd1ram),
.ce (ce1ram)
);
sram sram2(
(addr2ram),
.addr
(data2ram),
.data
.wr (wr2ram),
.rd (rd2ram),
.ce (ce2ram)
);
//前面的代表在应用模块中的信号名,括号中的代表在本模块中的信号名
//---------------sram1 test bench module---------------------- module sram(addr,data,wr,rd,ce) ;
input[20:0]addr;
inout[7:0]data;
input wr,rd,ce;
wire[7:0] data;
reg[7:0] mem[2097151:0];
assign data=(!ce&&!rd&&wr)?mem[addr]:8'hzz;
wire[7:0]temp=mem[addr];
always @(posedge wr)
mem[addr]<=data;
endmodule
实验三 整型DCT 的硬件实现
一 实验目的:
学习蝶型图的硬件实现方法 联系使用流水线结构
二 实验内容:
使用硬件描述语言实现整形DCT 算法 在modelsim 中做仿真
三 实验原理:
H.264(一种图象压缩编码方法)中的变换编码和以前各种标准中的DCT 有所不同,以前标准中直接采用DCT 的定义进行变换,会带来两个问题:第一,需要进行浮点数操作,从而造成系统设计及运算上的复杂性;第二,由于变换核都是无理数,而有限精度的浮点数不可能精确地表示无理数,再加上浮点数的运算可能会引入舍入误差,这就使得在具体实现时会导致编解码的不匹配(mismatch),即反变换的输出结果和正变换的输入不一致。

为了克服这些问题,H.264采用基于4×4块的整数操作而不是实数运算,使得变换操作仅用整数加减和移位操作就可以完成,这样既降低了设计复杂度,又避免了编解码误匹配,能够得到与4×4 DCT 变化类似的编码效果,而由此带来的编码性能的减少微乎其微。

此整数变换中无乘法,采用基于提升结构的无乘法二进制DCT (Bin DCT),只包括加法和16位算术移位,这样大大减小了运算复杂度,尤其是对低端处理,减少了乘法运算且保持了整数变换的优点,精确的整数排除了编码器和解码器之间反变换的误匹配,保证了变换的效果。

我们可以通过各种公式推导出整数DCT 正变换的公式:
⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎣⎡⊗⎟⎟⎟⎟⎟⎠⎞⎜⎜⎜⎜⎜⎝⎛⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡−−−−−−⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣
⎡−−−−−−=222222222/1111112/11112/112/1111
2/1112/1111112
/12/111111b ab b ab ab a ab a b ab b ab ab a ab a X
Y (1.1)
式(1.1)中,虽然乘以1/2的操作可以用右移来实现,但这样会产生截断误差,因此,我们将1/2提到矩阵外面,并与右边的点乘合并,得:



⎥⎥
⎦⎤
⎢⎢
⎢⎢⎢⎣⎡⊗
⎟⎟⎟⎟⎟⎠⎞⎜⎜⎜⎜⎜⎝⎛⎥⎥⎥⎥
⎦⎤⎢⎢⎢⎢⎣⎡−−−−−−⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣
⎡−−−−−−=⊗=4/2/4/2/2/2/4/2/4/2
/2/2/11212111211111211221111121121111)(22222222
b ab b ab ab a ab a b ab b ab ab a ab a X E XC C Y f
T f f (1.2)
这就是H.264中所用到的整数变换公式,其变换核T f f XC C 仅用加减法(和左移)即可以实现。

而后面的点乘操作可以合并到随后的量化过程中去。

H.264中所用到的反DCT 变换公式如下:

⎥⎥⎥
⎦⎤⎢⎢⎢⎢⎣⎡−−−−−−⎟⎟⎟
⎟⎟⎠⎞⎜⎜
⎜⎜⎜⎝⎛⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎣⎡⊗⎥⎥⎥⎥⎦⎤⎢
⎢⎢
⎢⎣⎡−−−−−−=⊗=2/111
2/11111
12/12/1111112/1111112/11112/112/1111
)(22
222222b ab
b ab
ab a ab a b ab b ab ab a ab
a Y C E Y C X i
i T i (1.3) 其中与Y 点乘的操作与反量化合并,乘以系数1/2的操作由右移来实现,由于反量
化后的结果足够地大,所以这里不会出现截断误差的问题。

以上各式中,
21
=a ,5
2=b 。

H.264的整数DCT 变换可以分做两步完成:先对需要做变换的矩阵的每一列做一维变换,再对其结果的每一行做一维变换,这个次序也可以反过来,先行后列。

这样二维变换就可以用一维变换来实现。

在具体实现过程中,为了减少运算量,每一步可以采用蝶型算法,以公式(1.2)的第一步对X 的第一列进行一维变换为例,其运算过程如下式所示:
32103
32102
32101
32110
2222x x x x x x x x x x x x x x x x x x x x −+−=′+−−=′−−+=′+++=′ (1.4)
其中3,...,0,=n x n 为X 第一列的元素,3,...,0,=′n x n 为滤波结果。

由(1.4)式可见计算有很多重复,如30x x +就同时被计算0x ′和2x ′的公式所使用,所以可以将其暂时保存起来以避免重复计算,对应的蝶型算法如下图所示。

图4 蝶型算法
由以上可见,按公式(1.4)计算需要进行12次加法,4次乘法,而图4中的蝶型算法仅需8次加法,2次乘法,它利用了运算中的冗余,大大降低了运算量。

由于在反变换中使用精确的整数,这就避免了浮点DCT中逆变换不匹配的问题。

H.264利用了尺度DCT的思想,在变换中并不进行归一化运算,而是放在量化和反量化过程中完成,以此降低整个变换编码的运算量。

四硬件系统设计方法:
本实验要求每个时钟周期都有数据输入,都能生成一个输出数据。

这就需要用到流水线的操作方法,每一级流水线作一项工作,然后将中间结果送到下一级流水线。

如下所示:
典型的流水线采用多个always块来实现,每个always就是以及流水线:
always @ ( posedge clk or negedge rst_n )
if( !rst_n )
begin
a0 <= 0 ; a1<= 0 ; a2<= 0 ; a3<= 0 ;
end
else
begin
a0 <= data_in0 + data_in3 ;
a1 <= data_in1 + data_in2 ;
a2 <= data_in1 - data_in2 ;
a3 <= data_in0 - data_in3 ;
end
always @ ( posedge clk or negedge rst_n )
if( !rst_n )
begin
data_out0 <= 0 ;data_out1 <= 0 ;data_out2 <= 0 ;data_out3 <= 0 ;
end
else
begin
data_out0 <= a0 + a1 ;
data_out1 <= a0 – a1 ;
data_out2 <= a2 + a3 ;
data_out3 <= a2 - a3 ;
end
注意:
1 加法运算会产生进位,所以每加一次后数据宽度也要增加。

2 注意符号的问题,如果是负数求补码
31。

相关文档
最新文档