IP CORE 之 ROM 设计- ISE 操作工具
, C* j" j! a" \8 r
- j _, H; a5 {8 \8 M' C
; A# x1 T+ x* @. H1 n+ u本篇实现基于叁芯智能科技的SANXIN -B02 FPGA开发板,如有入手开发板,可以登录官方淘宝店购买,还有配套的学习视频。, m; S: L9 m/ L. ?3 t( @& h3 {0 N
; x! o9 m' q4 ]/ T
XC6SLX9系列器件采用嵌入式内存结构,用以满足设计时需要芯片上内存的需求。设计者可以配置这些内存块成为各种内存功能,如:RAM、移位寄存器、ROM和FIFO缓冲区等。
* W3 s, |- Y+ D0 U
SANXIN-B02的FPGA为XC6SLX9-2TQG144C, 此款FPGA共包含216K bit的内存。
4 Q1 q. {0 \6 g
2 N! Y# }5 ^1 W: N
; e5 N$ o k' N, H0 Q' `: ~+ d
M9K的内存块支持以下特性:
1. 每一个内存块有8192个bit(包括校验的话,就是9216bit)
2. 独立的读写使能
3. 端口可配置
4. 支持单端口和双端口模式
5. 支持字节使能功能
6. 支持时钟使能功能
7. 在RAM和ROM模式下,支持初始化数据
设计要求
. [6 g" ^. Q: |/ \$ _ C7 ]8 K; P' o
在FPGA内部构建深度为256,宽度为8的ROM。在不同的地址中放入与地址值大小相等的数据,即:0地址放0,1地址放1······
- 设计原理
- n: e* ?' t* W% s4 A% D
ROM(read only memory)只读存储器,此种存储器不支持写操作,只支持读操作。在存储器建造时,将数据刻录进去。ROM能够实现掉电不丢失。
8 i$ Y* h/ y& {4 W+ E4 F
本次设计ROM是利用FPGA片内嵌入的M9K构成的,所以不能够实现掉电不丢失。
$ i$ A* K+ K; @1 N. P" L% ]2 H
由于设计ROM深度为256,故而地址的宽度为8位。
! `6 z5 c+ @* u( C: v8 u* O) b( m
本次构建为ROM,所以在构建ROM之前应当首先设计好初始化文件(coe文件)。
, o5 T) x' @/ G* R; d& o8 K! T
ROM工作原理为,在时钟上升沿采样到rden为1时,将addr所指示的存储空间的数据进行输出。
6 ?- @: `3 O7 y
1 K5 K1 p' ^1 X. Q8 {& X0 V本模块命名为rom_test。
* i6 R l, B8 J4 ]8 j/ \6 O6 ~
& N( j3 y/ V7 \; H
: `5 ]- N0 Z4 H- q7 \
$ b5 p0 L) C; r$ p
! I( M) P0 O; k ^' M0 L* Q* ~
: `, o8 i# @8 [3 f1 h
/ ]7 p. q6 \& P- e1 Q, M2 U
# p* Y1 g( F3 ^+ X
7 Y8 B6 s0 z! R' \( C3 A. f" \8 c$ S: g% J- g, \( H! Q ^
$ g7 V! h8 \* }$ ?
+ O0 Q; S7 t% X4 c
4 i/ e$ }( D( o- 制作初始化文件: {$ O$ V) T1 c9 h
建立工程后,首先我们要生成一个coe文件,方法有很多,比如:matlab、excel表格生成数据等等。然而我们的coe文件是有一定格式的,格式如下:
memory_initialization_radix=16;
memory_initialization_vector=
9 s+ _: [5 u( F) r! ~0 ^第一行是规定数据的进制,如果是16进制,就在等号后面写上16,二进制就写2,其他同理。第二行是数据,在第二行下面开始把数据一个一个的写出来,数据之间用逗号隔开,最后一个数据后面加分号。
5 W' i @, j) b1 Z6 O内容编写完成后,另存为.coe文件。如图:
5 X) a4 P# G# X; n7 n: @& }: V* e$ ]
2 i8 k$ s& o) X5 [* r. w0 d7 P+ a/ w& m
我们这里数据从0到255,地址默认。
6 T# `4 z% K* c. ^- i
点击保存,coe文件就已经制作完成。
) x' ~2 L; K9 w# | A1 V当然,如果数据很多,我们是不可能一个一个的来写的,那么我们有没有其他的方法呢,肯定是有的。下面向大家介绍一种简单的方法,那就是用MATLAB来写coe文件。
7 G- K" F6 F8 j1 ~" i9 |% D% s5 M4 k @首先我们打开MATLAB,在命令窗口输入以下代码:
6 r+ k* o* E) K' k$ I, i7 _5 b
# J' H2 G( k$ d
+ b; V4 T! v* E0 V- Y% ~ Q+ C5 V4 |$ G6 X( j6 E/ U0 G
代码输入无误后,保存文件,会看到有一个名字为data.coe的文件生成。我们用编辑器打开,会看到我们的数据文件是没有问题的。
3 A4 u. V. M3 D
- 调用ip core之 rom
" F$ T7 {% k; R' n
; d' b3 M* @: Q8 D2 m8 Y3 x
ISE工具中,调用IP核的方法跟新建文件类似,所以我们在调用IP核的时候,点击Hierarchy中的rom_test,右键选择New Source。选择文件类型为IP (CORE Generator & Architecture Wizard)。文件名为my_rom。
1 R5 S- m3 c4 y$ e! y H
5 I& m2 w3 O b0 R- i! ~
5 [6 p. p: O* E# S/ I; @. S# `, _) ]
# ^; o2 L4 P- x/ c3 {# Z1 T+ C1 G3 F D& h! c& J+ w6 B
* w, ?8 y I. @$ ^* u, r; L7 x1 d3 l
, v7 A2 y w6 `( l/ ~) V4 L! D0 z( k- v+ B5 a2 J5 l; }. p9 ]
7 K7 J. R! V& k( X5 B5 R. G
( m# }( ^" P% L) r3 y5 k5 b
( ^# S9 o. g# [1 O, d [. R; p
在搜索界面,搜索block memory。会看到有两个选项,我们选择RAMs & ROMs里面的Block Memory Generator7.3。点击Next。然后点击Finish。
S' O: q# T5 ]
% x' h. ]! u2 y/ P% L4 Q8 G
0 N9 g* m# u# y4 `6 ^- p
' m6 I6 S0 ]7 o Z: ]2 S
9 y: T) {- Y( D; K* `( R" r4 V% s7 X* ?
1 C J: T. `( i
- W$ x% s, A, y$ s& B
' ^% y# H1 H4 s, y: U3 |$ v
, |+ c7 n3 o6 u# R/ ~: G5 m0 z8 E5 o然后我们会看到如图界面,点击Next。弹出如下图示:
7 a' J X+ w7 c6 `- a
5 Z; Y" b4 L6 ?6 |( Q8 F! F2 `/ v- P
# G. B3 w& s$ l/ q4 z) l0 O9 S$ w1 E7 u- s; A
6 |, X# @! J0 F; `7 ]7 i
5 C8 `/ b9 \7 `3 ~% _$ V/ g$ j1 G3 B" q! f% O
' T4 U8 s; ~1 }# t6 M Q, h* f. q& r# l4 {! b4 ?& J) o; m6 l0 M0 r
存储器类型选择单端口ROM。
$ B0 V! e" a0 N& e0 {
ROM分为单端口(1-port)和双端口(2-port)。ROM是一个只读存储器,通过给予地址和读使能,就可以得出对应的地址的数据。在FPGA中,ROM可是配置两套端口,这两套端口相同,都可以通过给予地址和读使能,得出对应的地址的数据,并且相互独立,但是共用同一段存储空间。
0 Z$ \; \" }; O
在此选择ROM :1-port。点击Next
5 V/ m7 n/ K4 E! |) ?& c
+ Y$ L/ z. D; {8 u( [* t: r
; X, M# O4 M6 N& E) ?7 \3 H, }* Z2 g+ `* _1 X L2 J
2 m+ S! L6 j7 P+ j这里我们以我们之前设置的数据文件为例,数据位宽为8,数据深度为256,使能ENA打开,如图设置。点击next。
9 \( |$ u, v$ p7 |4 z4 n
! ?' n* _% H* _* I4 T
* |7 D& g. S. X+ p7 G1 q# M1 g# Q
5 Y" ]; p: J1 k! M
$ |9 |4 ]8 z- N/ B3 D3 A/ a此界面为数据设置界面,因为ROM为只读存储器,所以我们需要在使用前提前配置好数据。这里就需要我们之前做好的.coe文件。在Memeory Initialization下方把Load Init File勾选上。点击Browse,找到我们的文件位置。选好之后,点击Next。
9 T8 a3 v. I2 ^0 C* ?, W9 v7 H, V/ a' Z6 b! V
4 Y9 v( F3 z! H
& E* K" \6 b, L
5 c- M) l" L K9 b" G' g
: y8 [8 p( M0 [2 N+ k5 u" T: V- D
( X/ ]! F1 P: _" u4 ^5 Z4 c' V6 L/ @4 K此界面是配置端口的界面,第一栏是复位端口的设置,我们这里不使用该端口,保持默认设置,点击Next。
+ S2 H5 U: Y8 P B1 U ]) E
! o" I. v0 J' M7 w
5 K! k. l! }- a; s8 H9 X
9 x5 s: B4 L4 U4 J5 o3 \9 K
4 X2 W/ s, l& G M+ Y此界面保持默认设置,点击Generate。
7 O5 M1 k8 K+ ]( i: d- 编写设计顶层
5 l6 f2 p: b6 z& |
顶层模块负责例化my_rom。my_rom的例化代码在ipcore_dir -> my_rom.veo中。
4 p* ^6 s: |8 Q; H) w/ K
设计代码为:
0 M$ v1 \6 _3 C) f) H& i, w8 D
7 B7 j" V+ M3 f9 L! W2 E
2 J9 G( y* c+ g6 y! S
. {+ j9 H/ Q6 h0 b& g
! I1 p; a- @/ j$ J9 R
- RTL仿真
?; J" b! I9 N+ E; p. F& F
设计仿真文件时,将所有的地址轮询一遍,查看输出的数据是否正确,rden信号设置为随机值,在不同的地址随机决定是否读出。
: {! }, ?3 S: [7 u+ Q
% A5 R0 Y5 T, w' g( S6 `) Q/ ?仿真代码为:
/ s( V' @" X! ^# e6 K( o- t
0 W; [1 F5 K) {0 p0 J& G% c7 ^
* A" r1 L m2 J- P. Q; m' `6 T5 s" ?1 T# U
8 Q/ O; @( ]6 ^* Y% arepeat语句为重复语句,相当于把begin end中间的语句重复执行N次。
' y0 ]0 n& d! F/ V. @
* m* I) F' X, y( J K仿真编译通过后,运行仿真。
7 E$ V; c7 w, r) e) i& }( G
4 U7 ]3 |$ h; q9 ]% V5 S, R
8 m6 C0 J0 S5 s7 I: p; e, z. J7 O0 f; O3 [" a9 r/ l0 ~
. U3 N' n& u; K8 r: q从波形图中可以看出,当rden为高电平时,rdata输出数据,当rden为低电平时,rdata不输出新数据。
i/ q+ M: L! r8 Z% N2 D将ROM设置为双端口时,addr、rden和rdata会多出一套,操作时序和方法是相同的。
$ j/ v/ u- t- l9 Z5 @* _/ h/ f
0 v. @% N2 z& [# d& e4 L