|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
" F) P S$ B4 J3 O& e/ I系统性的掌握技术开发以及相关要求,对个人就业以及职业发展都有着潜在的帮助,希望对大家有所帮助。后续会陆续更新 Xilinx 的 Vivado、ISE 及相关操作软件的开发的相关内容,学习FPGA设计方法及设计思想的同时,实操结合各类操作软件,会让你在技术学习道路上无比的顺畅,告别技术学习小BUG卡破脑壳,告别目前忽悠性的培训诱导,真正的去学习去实战应用,这种快乐试试你就会懂的。话不多说,上货。
% q( L* t2 l- b' e$ R; _% D $ a& J, ^' w1 A5 A8 d: O0 E- }
IP CORE 之 ROM 设计- ISE 操作工具
; {" X: Y5 Y/ m0 `1 W: q2 [4 t& n9 ]+ u' f
h0 g$ B5 J" c+ f% y b7 P, U( v
本篇实现基于叁芯智能科技的SANXIN -B02 FPGA开发板,如有入手开发板,可以登录官方淘宝店购买,还有配套的学习视频。" h& Q3 f' Y& U7 B
3 r9 E) e) K) B! ]# J. }1 y
XC6SLX9系列器件采用嵌入式内存结构,用以满足设计时需要芯片上内存的需求。设计者可以配置这些内存块成为各种内存功能,如:RAM、移位寄存器、ROM和FIFO缓冲区等。
L8 t$ ?- E5 @" u
SANXIN-B02的FPGA为XC6SLX9-2TQG144C, 此款FPGA共包含216K bit的内存。 5 j& t2 |& i" x% z7 {$ R% {% {+ o
. G0 h0 p: U, d) c* e1 {
8 E: Y( ~. w- e8 y3 u' [) P# {- c
M9K的内存块支持以下特性: 1. 每一个内存块有8192个bit(包括校验的话,就是9216bit) 2. 独立的读写使能 3. 端口可配置 4. 支持单端口和双端口模式 5. 支持字节使能功能 6. 支持时钟使能功能 7. 在RAM和ROM模式下,支持初始化数据 设计要求
, U6 v1 x, z/ C4 D: U
在FPGA内部构建深度为256,宽度为8的ROM。在不同的地址中放入与地址值大小相等的数据,即:0地址放0,1地址放1······ - 设计原理* l/ f! M2 c8 l; W0 X
ROM(read only memory)只读存储器,此种存储器不支持写操作,只支持读操作。在存储器建造时,将数据刻录进去。ROM能够实现掉电不丢失。 % L8 i; }( E9 p" M5 b0 T
本次设计ROM是利用FPGA片内嵌入的M9K构成的,所以不能够实现掉电不丢失。
6 }7 F" h/ U% x' d5 {
由于设计ROM深度为256,故而地址的宽度为8位。
. c% g. }- l( j5 u: f+ }
本次构建为ROM,所以在构建ROM之前应当首先设计好初始化文件(coe文件)。 ! M- F% G: @% O6 x2 e" P
ROM工作原理为,在时钟上升沿采样到rden为1时,将addr所指示的存储空间的数据进行输出。
1 T6 ^. Z) K9 G- }* ?* Z2 ~
- 设计架构和信号说明0 v6 z% S$ l- |% }9 g
4 b; k$ N1 ~9 k3 V$ E. j% e7 T# R本模块命名为rom_test。
& J8 z) o2 I* {( H5 u8 S+ ?
: c( |6 f o M4 M+ B$ ^+ S- g
1 d+ M' q9 e: y9 Q; J, r/ j' V
7 O; W! a: k! Q5 j
+ F% {& V ] ]* d- }# [
# N; I! l2 f) D1 g+ k$ s" }8 P) P) X9 P6 Z, l; K2 U
1 z3 U6 G' C( O5 }# e. D+ O
2 p4 n7 O" {3 i7 s8 x9 s; l% l1 y- g# g$ R l0 s
+ m8 Z o8 q0 \1 a# a% b, W) B8 f# w+ B1 f
' D- z& H6 s7 |' G; \, {
- 制作初始化文件 Z& _9 j; H+ |9 w2 A( r* E2 f
建立工程后,首先我们要生成一个coe文件,方法有很多,比如:matlab、excel表格生成数据等等。然而我们的coe文件是有一定格式的,格式如下: memory_initialization_radix=16; memory_initialization_vector=
2 x: Y& Y% C* o1 d* L/ P0 R8 N第一行是规定数据的进制,如果是16进制,就在等号后面写上16,二进制就写2,其他同理。第二行是数据,在第二行下面开始把数据一个一个的写出来,数据之间用逗号隔开,最后一个数据后面加分号。 7 H+ _, B! f$ W9 q+ w
内容编写完成后,另存为.coe文件。如图:
. t7 `& i! ?) Z- ~- k
B4 k: S/ K1 |# w Z+ v. i _
我们这里数据从0到255,地址默认。 4 u6 z& ]. { L, M+ [7 d: E& `
点击保存,coe文件就已经制作完成。
K2 f, G7 F/ a当然,如果数据很多,我们是不可能一个一个的来写的,那么我们有没有其他的方法呢,肯定是有的。下面向大家介绍一种简单的方法,那就是用MATLAB来写coe文件。
! F7 Z, N. ], ]- i首先我们打开MATLAB,在命令窗口输入以下代码: / t7 |- ^, @0 t( ?8 E. F, B/ \. ~
2 W+ X* R/ u' \3 c6 x/ ]) d" Q3 Z
/ T6 P) p) Y( y# K9 c4 U" K# Q7 t6 A6 V! C; s
代码输入无误后,保存文件,会看到有一个名字为data.coe的文件生成。我们用编辑器打开,会看到我们的数据文件是没有问题的。 ; X4 R1 p* V6 v( P
- 调用ip core之 rom+ F7 k9 G9 R% ], D9 e8 B* l
3 k' |0 G, F! [; |* kISE工具中,调用IP核的方法跟新建文件类似,所以我们在调用IP核的时候,点击Hierarchy中的rom_test,右键选择New Source。选择文件类型为IP (CORE Generator & Architecture Wizard)。文件名为my_rom。
% ~: X2 l# M, d( R/ u/ t9 R/ }0 d& d5 o8 D$ D
8 X- A* O. n3 z( O9 T. i9 ]
9 Z7 A) R! D, ]1 [$ \% j. D4 A. R2 j7 T" [
( s+ g- Y3 R: |8 \. E) j
; U }/ ]# o5 Z2 A1 K
6 Q- [! q8 v8 _
O" C& j" s" R( J2 W. g
& [* ?& V7 h4 a" N$ @0 i2 v7 q8 B! v( l3 F
' d8 r; c9 N. d在搜索界面,搜索block memory。会看到有两个选项,我们选择RAMs & ROMs里面的Block Memory Generator7.3。点击Next。然后点击Finish。 r+ d* s6 j/ j* u
. z Q w; D+ n! u/ C M9 r. N9 R' f3 @) }; V" Y/ V3 Y# C
$ b, U* o5 c" {: S9 T* L) K4 K& {3 W* W+ ?/ B/ \' D( C6 j5 @* H
) g }& o. L8 @ R- @2 I% G$ O- b- a+ {0 Q n) g+ G" Q
. f3 q2 z. G! O# L7 E, t
; e4 c& }9 g7 g3 x
/ p& s& y* M5 M8 g' z然后我们会看到如图界面,点击Next。弹出如下图示: ) ?! y" f0 U. r$ }* E: B: {
) a& @ H' t, y* Q5 c
' u" ^8 o1 C% H7 S" x
! t; `; v7 {' D _$ U8 ?$ d7 E- m5 s- ~; n5 ]& c
1 Q5 a, m9 u. _! S& J: |( h/ W
* O2 s& D4 H& |3 ?( f! u4 Z( y0 {% H! Z* N
6 s! X9 C, }! ^& f U) B3 w) v3 D+ {6 L; m2 Q+ |3 w$ c- J
存储器类型选择单端口ROM。
8 q \" }7 `9 T# [ROM分为单端口(1-port)和双端口(2-port)。ROM是一个只读存储器,通过给予地址和读使能,就可以得出对应的地址的数据。在FPGA中,ROM可是配置两套端口,这两套端口相同,都可以通过给予地址和读使能,得出对应的地址的数据,并且相互独立,但是共用同一段存储空间。
$ l/ t" j) p+ u6 V, @在此选择ROM :1-port。点击Next
. {' C7 _9 C( a% u9 A
1 {( H$ j: V# B% ` O
, `) u% G6 l6 J0 O1 D' e! ~: C R" V! z3 ~
3 Z9 u2 L( D. V/ O) h5 c这里我们以我们之前设置的数据文件为例,数据位宽为8,数据深度为256,使能ENA打开,如图设置。点击next。 9 x! @8 J+ T) T" o5 U" k: e
2 b; f8 Z8 P' u7 S
9 ~. ^3 {* d0 }) D- v2 S& S4 @; j) [, t
* }4 I- P9 K7 n$ P1 D; E4 N" S; L' |5 k1 R( P
此界面为数据设置界面,因为ROM为只读存储器,所以我们需要在使用前提前配置好数据。这里就需要我们之前做好的.coe文件。在Memeory Initialization下方把Load Init File勾选上。点击Browse,找到我们的文件位置。选好之后,点击Next。 " H- l; `# a3 ?+ c& _
4 X9 y2 K, K' @9 V' b* H, D G9 a
& I2 ?+ u8 q1 ?
( s8 Y. k2 M- v+ l0 [
, `/ C8 W1 z, X. J
2 ^! I% ?5 V9 F, ^
3 p: c3 C/ i3 h此界面是配置端口的界面,第一栏是复位端口的设置,我们这里不使用该端口,保持默认设置,点击Next。 - r8 D4 `- m* V) p- B/ c/ ^: N
) _# y! S6 H( S& ~0 \3 R- C, M- m
1 l0 I2 H) {% p& g2 s
$ H0 b" C, E! D' ^
# i$ f8 |( v" g4 g3 e. z
此界面保持默认设置,点击Generate。 4 ]1 Z) ]& Q3 M3 g
- 编写设计顶层
% U4 ~: t! w u$ B8 s
顶层模块负责例化my_rom。my_rom的例化代码在ipcore_dir -> my_rom.veo中。 3 k7 L+ t H( G/ q" G4 d8 V) ~
设计代码为:
5 J* f$ J/ B1 @) T1 E& J7 @5 f* c
6 k* `, I& `: N( }& l+ D5 I
2 o) j8 d3 T# |9 M! H
/ V5 C3 g z6 e/ b
# |# m5 j+ N6 X5 Z# y' m' L8 f1 P- RTL仿真
7 V3 s) R$ l: Q y |
设计仿真文件时,将所有的地址轮询一遍,查看输出的数据是否正确,rden信号设置为随机值,在不同的地址随机决定是否读出。 % ]8 I0 v; l+ W- E7 U" a- C
1 v" o8 P# U5 a: k( I/ G* F& t% Z
仿真代码为: : Q# q( }1 t" K6 y" F% j* _; z- n
8 {' e8 H. I4 y6 ~! B7 y- O
/ U1 Y* @1 W' o( o( \* E/ t4 ]7 i
% o: K3 n/ K- I( L2 Z4 v# R5 f6 ^
, ^: f+ t' D9 a, {+ Z, |repeat语句为重复语句,相当于把begin end中间的语句重复执行N次。 ' h$ x0 E& Q9 z% j0 r. y, E1 ]
6 ?5 \, x* E) P$ k8 ]8 |/ p& a仿真编译通过后,运行仿真。 9 s" I' `2 Q5 F
% H2 `, b1 r9 X) I
$ D+ Y: M4 R9 z/ T# ?6 I5 i* H# \$ U5 N
% f& Y/ K. W T7 l! v. M( J: ?; q从波形图中可以看出,当rden为高电平时,rdata输出数据,当rden为低电平时,rdata不输出新数据。
5 B2 t4 t, t" L将ROM设置为双端口时,addr、rden和rdata会多出一套,操作时序和方法是相同的。
1 t( M' U# o2 t5 \9 F% f' b* n
9 P$ ]; S, z6 h5 m% y ! o& N4 y5 ?# _: N& L8 `4 d
|
|