IP CORE 之 ROM 设计- ISE 操作工具
; A9 ~. Y9 i# i0 `+ a4 n- D7 c; d- z8 x3 O& p7 h4 g1 n0 c
# @+ ~3 K" \! }8 A6 `
本篇实现基于叁芯智能科技的SANXIN -B02 FPGA开发板,如有入手开发板,可以登录官方淘宝店购买,还有配套的学习视频。
8 r. [# s) h. }# c# r% L0 h
+ O" c" X \6 Z. N" u
XC6SLX9系列器件采用嵌入式内存结构,用以满足设计时需要芯片上内存的需求。设计者可以配置这些内存块成为各种内存功能,如:RAM、移位寄存器、ROM和FIFO缓冲区等。
# Z3 n' J% ~" j% E/ o
SANXIN-B02的FPGA为XC6SLX9-2TQG144C, 此款FPGA共包含216K bit的内存。
- P0 F0 R- b, r; ^6 _2 f% c& B
$ U% t$ s5 ~# f1 j: p
. z8 \# m1 f1 C6 X0 I- f& |
M9K的内存块支持以下特性:
1. 每一个内存块有8192个bit(包括校验的话,就是9216bit)
2. 独立的读写使能
3. 端口可配置
4. 支持单端口和双端口模式
5. 支持字节使能功能
6. 支持时钟使能功能
7. 在RAM和ROM模式下,支持初始化数据
设计要求
% s# z8 y7 f* ^+ O* K
在FPGA内部构建深度为256,宽度为8的ROM。在不同的地址中放入与地址值大小相等的数据,即:0地址放0,1地址放1······
- 设计原理3 Y3 G+ j4 B( d7 Q* J" S! Y: j8 h
ROM(read only memory)只读存储器,此种存储器不支持写操作,只支持读操作。在存储器建造时,将数据刻录进去。ROM能够实现掉电不丢失。
$ O2 Q. F1 b) u' y% D4 W) B/ `' b
本次设计ROM是利用FPGA片内嵌入的M9K构成的,所以不能够实现掉电不丢失。
9 }) K8 _7 W0 K7 T5 f9 H) l
由于设计ROM深度为256,故而地址的宽度为8位。
k, H. X6 o6 x
本次构建为ROM,所以在构建ROM之前应当首先设计好初始化文件(coe文件)。
% f4 Z+ i0 k& u d; }7 T) _
ROM工作原理为,在时钟上升沿采样到rden为1时,将addr所指示的存储空间的数据进行输出。
1 p& W- k8 W( P" n- P9 T. ]8 p
- 设计架构和信号说明
) m, n" b/ z3 u3 a3 C- [
1 v+ R! i/ H: \3 Q) s1 n0 X$ `本模块命名为rom_test。
3 T9 M2 v$ e7 J# g
. M/ p3 j5 w3 A/ [
. o, J& [$ r8 X3 @1 f2 ^4 T& R* D2 _' e( ?
" Q/ X) _$ f Q
! R4 \' z l E+ N( z- o1 l' Z t* s$ x3 q
5 O) r+ _# k R1 ^3 i% P% I: ^2 E4 i O+ {6 g" { t5 d% i
' P9 t/ c6 P3 w( {) {1 R' G
. |( w) k b, m) @ C; |# t
8 ~, [! }% l# W: e% C7 i& ~
0 @" o* Q* V2 v/ A
- 制作初始化文件& j% B2 G: ]0 m9 u$ r5 e) |: x" [
建立工程后,首先我们要生成一个coe文件,方法有很多,比如:matlab、excel表格生成数据等等。然而我们的coe文件是有一定格式的,格式如下:
memory_initialization_radix=16;
memory_initialization_vector=
/ [5 {: d( u+ `: B& h& |
第一行是规定数据的进制,如果是16进制,就在等号后面写上16,二进制就写2,其他同理。第二行是数据,在第二行下面开始把数据一个一个的写出来,数据之间用逗号隔开,最后一个数据后面加分号。
+ N6 W! p P2 m. Y$ I- a# ~8 [: m' }7 G内容编写完成后,另存为.coe文件。如图:
3 E# N7 p% _ d! {# i& ] Q* c
+ ]; {7 v y7 g! I7 e2 D2 {( U
我们这里数据从0到255,地址默认。
, d0 N* \' A3 `' E0 `# K5 F点击保存,coe文件就已经制作完成。
( A B8 k* ~0 G! H, P当然,如果数据很多,我们是不可能一个一个的来写的,那么我们有没有其他的方法呢,肯定是有的。下面向大家介绍一种简单的方法,那就是用MATLAB来写coe文件。
; `4 e- J8 z$ Y8 x
首先我们打开MATLAB,在命令窗口输入以下代码:
0 U' m- w9 X0 ?% u( H
9 `# x5 y! e) x1 G. A' w8 |* P0 l6 T- k+ a! y
( i; p* h4 r( a5 P+ O& e \: D
代码输入无误后,保存文件,会看到有一个名字为data.coe的文件生成。我们用编辑器打开,会看到我们的数据文件是没有问题的。
3 i' {( S1 F/ d1 B$ G/ O& e- 调用ip core之 rom
/ A N/ a9 p2 L F# N' n j& o$ [
2 y9 ^- R0 M) q# u- v
ISE工具中,调用IP核的方法跟新建文件类似,所以我们在调用IP核的时候,点击Hierarchy中的rom_test,右键选择New Source。选择文件类型为IP (CORE Generator & Architecture Wizard)。文件名为my_rom。
|9 {+ A0 ~% V
2 r' R; N! i5 L4 W5 J5 p& v: i
# x0 m3 [9 K" M/ x5 z) s5 L
3 o1 A& s1 N" s. Y$ {& P! Y* @4 i5 k5 v' [4 \ `
0 Q/ }, g; p: r+ \: h
7 ^; _% `; I. |7 a% }0 j0 ]. @5 f$ f! h% `! P4 r$ [( w
2 o) ^& r- N; K* E& D4 t* {( g6 [9 g8 S
5 n6 K7 d+ _. M. p* O2 r! z4 O+ d- ?7 X2 S$ Z' j
在搜索界面,搜索block memory。会看到有两个选项,我们选择RAMs & ROMs里面的Block Memory Generator7.3。点击Next。然后点击Finish。
8 A* F5 j8 j9 N3 ~1 w" a! r$ r, _$ d( b& ^( Y$ |0 x
) {: |: [ g ]% L8 Z
0 U" c1 \2 F/ U4 ]
5 b) j/ |0 e1 y" C
7 b5 f* w: R# G
1 ~ h( h; P4 m7 z2 c6 Y5 v3 J
9 j+ W8 c1 w/ v5 n0 g: v
5 T- J" ^/ `, u$ |& S* @
/ N& ]3 K5 d7 E+ ?) T$ A/ o! t然后我们会看到如图界面,点击Next。弹出如下图示:
+ l4 b5 f1 Q( a2 T* v
( q5 } T! F, V" e0 N" l- q: w: J- P, L$ x9 t
% X7 p: u1 `9 W# a
9 s) E; u, P1 x ?5 O: m
7 I. i9 M3 C: E2 E4 {9 s( ^! k# o0 a. _
4 t( s# A1 E8 Z' u4 L: d
! @, e# c* I! `5 _. L1 n
; g/ U( ^, s, U9 a% V8 B
存储器类型选择单端口ROM。
( Q5 J2 V' @: p4 k
ROM分为单端口(1-port)和双端口(2-port)。ROM是一个只读存储器,通过给予地址和读使能,就可以得出对应的地址的数据。在FPGA中,ROM可是配置两套端口,这两套端口相同,都可以通过给予地址和读使能,得出对应的地址的数据,并且相互独立,但是共用同一段存储空间。
& m! Q/ X' y, o& S& g6 ^ w3 n( J. d, G在此选择ROM :1-port。点击Next
" }: } ?* ~0 a: y/ j4 G8 c
* @: M! I& c! l& d
9 k( k2 r0 s1 n% `
. q! I5 H9 x$ l& @$ z
! J. g5 p) s1 O这里我们以我们之前设置的数据文件为例,数据位宽为8,数据深度为256,使能ENA打开,如图设置。点击next。
Y A' y9 Z Q/ ?
, o: L0 N; \/ z( V$ ^% b. A9 c
) G( w% t ?( X! t, _
3 O4 l* b9 _# I9 I+ K4 I
% E+ d6 Y/ U0 v6 n: d此界面为数据设置界面,因为ROM为只读存储器,所以我们需要在使用前提前配置好数据。这里就需要我们之前做好的.coe文件。在Memeory Initialization下方把Load Init File勾选上。点击Browse,找到我们的文件位置。选好之后,点击Next。
- z* M G5 B$ r& Z
% ]3 h) l# E/ k _# x
6 n$ W% [+ |0 C. X2 V% t
( @% S& L% B: c# H
" s; z$ Z1 W T) u: c5 Z4 T+ ?3 i# \; N: ^3 V
\8 x0 ]6 t+ r/ U6 d" i3 v! e此界面是配置端口的界面,第一栏是复位端口的设置,我们这里不使用该端口,保持默认设置,点击Next。
2 q1 c1 Z* ]8 t* \5 [* V4 i( F
: e% V& ?- a' p8 j3 w( S
, |& B3 ]9 v: b, k
; z# A4 g, c+ v) ~- e" h1 w" X7 d: r: C
此界面保持默认设置,点击Generate。
3 T) V4 \3 O( \8 P. B- 编写设计顶层
' Z) _% F7 L! d$ e3 `
顶层模块负责例化my_rom。my_rom的例化代码在ipcore_dir -> my_rom.veo中。
# O& |) y* A6 E& E) I/ R' @设计代码为:
) z$ q% C$ [$ x9 a: r
A$ q q" t# K+ F- v
* R: H; B4 y) t( K" r/ q# ?
+ d. ?8 J/ N7 K* k9 [9 V7 W
- _" a4 I9 s+ N4 L3 U3 }
- RTL仿真- G$ u4 R+ K7 B2 U! U4 ~* K
设计仿真文件时,将所有的地址轮询一遍,查看输出的数据是否正确,rden信号设置为随机值,在不同的地址随机决定是否读出。
: b. Y) ]/ L* U8 a
0 b; J# k2 l- n
仿真代码为:
* y A$ y' T# c: }
* ^$ M( Y: D8 I! f0 P5 E, P
: @, Z. d6 Q( U6 P8 m) Y4 }
8 d5 r h$ L, o1 N2 T; z6 P6 H( x# z! @& R+ ~8 e) k) |# }2 a
repeat语句为重复语句,相当于把begin end中间的语句重复执行N次。
) y. |8 I/ l. J/ f- ?4 G8 V
. ]- m- h5 G# {& v仿真编译通过后,运行仿真。
1 C# i- u9 }1 A; s/ H1 T4 _& K
0 s4 H7 a/ V0 [! Z
n! W3 T, g4 {/ }+ s, K6 L. S& {" W
$ q$ A/ M6 P5 n1 z+ p& l( x+ _! {. z从波形图中可以看出,当rden为高电平时,rdata输出数据,当rden为低电平时,rdata不输出新数据。
, l& W$ \1 |. z) }. ^' j
将ROM设置为双端口时,addr、rden和rdata会多出一套,操作时序和方法是相同的。
& B. [4 U0 [3 r( m/ {
& U% h, B7 P$ t9 d* a7 e% q/ x3 |