Abstract
之前討論過在DE2用軟體的C語言存取SDRAM,本文討論用硬體的Verilog存取SDRAM。
Introduction
使用環境:Quartus II 7.2 SP1 + MegaCore IP 7.2 SP1 + DE2(Cyclone II EP2C35F627C6)
在(原創) 如何在DE2用軟體存取SDRAM? (IC Design) (DE2) (Nios II) 討論過在Nios II下,用軟體C語言去存取SDRAM,由於DE2的Cyclone II是個FPGA,為了硬體加速,有時可能會想將演算法用硬體Verilog實現,這時就得用硬體Verilog去直接存取SDRAM。
如同上一篇的範例,用switch當成2進位的輸入,但這次改用七段顯示器做16進位輸出,使用到(原創) 如何顯示8位數的七段顯示器? (IC Design) (Verilog) (DE2)所開發的module。
Verilog / SDRAM_HR_HW.v
1
/*
2
(C) OOMusou 2008
http://oomusou.cnblogs.com
3
4
Filename : SDRAM_HR_HW.v
5
Compiler : Quartus II 7.2 SP1
6
Description : Demo how to use abstract base class simulate interface
7
Release : 04/25/2008 1.0
8
*/
9
module SDRAM_HR_HW (
10
input CLOCK_50,
11
input [
3
:
0
] KEY,
12
input [
17
:
0
] SW,
13
output [
17
:
0
] LEDR,
14
output [
6
:
0
] HEX0,
15
HEX1,
16
HEX2,
17
HEX3,
18
HEX4,
19
HEX5,
20
HEX6,
21
HEX7,
22
//
SDRAM side
23
output [
11
:
0
] DRAM_ADDR,
24
inout [
15
:
0
] DRAM_DQ,
25
output DRAM_BA_0,
26
DRAM_BA_1,
27
DRAM_RAS_N,
28
DRAM_CAS_N,
29
DRAM_CKE,
30
DRAM_CLK,
31
DRAM_WE_N,
32
DRAM_CS_N,
33
DRAM_LDQM,
34
DRAM_UDQM
35
);
36
37
wire RESET_n
=
KEY[
0
];
38
wire DONE;
//
write / read done
39
reg [
22
:
0
] addr;
//
address regitster
40
reg read,
//
read enable register
41
write;
//
write enable register
42
reg [
1
:
0
] state;
//
FSM state register
43
reg [
15
:
0
] data_in;
//
data input register
44
wire [
15
:
0
] DATA_OUT;
//
data output
45
reg [
15
:
0
] data_out;
//
data output register
46
47
assign LEDR
=
SW;
48
49
Sdram_Controller u0 (
50
//
HOST
51
.REF_CLK(CLOCK_50),
//
system clock
52
.RESET_N(RESET_n),
//
system reset
53
.ADDR(address),
//
address for controller request
54
.WR(write),
//
write request
55
.RD(read),
//
read request
56
.LENGTH(
8
'
h02), //request data length
57
.ACT(),
//
SDRAM ACK(acknowledge)
58
.DONE(DONE),
//
write/read done
59
.DATAIN(data_in),
//
Data input
60
.DATAOUT(DATA_OUT),
//
Data output
61
.IN_REQ(),
//
input data request
62
.OUT_VALID(),
//
output data vilid
63
.DM(
2
'
b00), //Data mask input
64
//
SDRAM
65
.SA(DRAM_ADDR),
66
.BA({DRAM_BA_1,DRAM_BA_0}),
67
.CS_N(DRAM_CS_N),
68
.CKE(DRAM_CKE),
69
.RAS_N(DRAM_RAS_N),
70
.CAS_N(DRAM_CAS_N),
71
.WE_N(DRAM_WE_N),
72
.DQ(DRAM_DQ),
73
.DQM({DRAM_UDQM,DRAM_LDQM}),
74
.SDR_CLK(DRAM_CLK)
75
);
76
77
SEG7_LUT_8 u1 (
78
.oSEG0(HEX0),
//
output SEG0
79
.oSEG1(HEX1),
//
output SEG1
80
.oSEG2(HEX2),
//
output SEG2
81
.oSEG3(HEX3),
//
output SEG3
82
.oSEG4(HEX4),
//
output SEG4
83
.oSEG5(HEX5),
//
output SEG5
84
.oSEG6(HEX6),
//
output SEG6
85
.oSEG7(HEX7),
//
output SEG7
86
.iDIG(data_out),
//
input data
87
.iWR(
1
'
b1), // write enable
88
.iCLK(CLOCK_50),
//
clock
89
.iRESET_n(RESET_n)
//
RESET
90
);
91
92
//
state 0 : prepare write
93
//
state 1 : read switch & write SDRAM
94
//
state 2 : prepare read
95
//
state 3 : read SDRAM & write to SEG7
96
always @(posedge CLOCK_50 or negedge RESET_n)
97
begin
98
if
(
!
RESET_n) begin
99
addr
<=
0
;
//
address register
100
read
<=
0
;
//
read enable register
101
write
<=
0
;
//
write enale register
102
state
<=
0
;
//
FSM state register
103
data_in
<=
0
;
//
data input register
104
end
105
else
106
begin
107
case
(state)
108
//
state 0 : prepare write
109
0
: begin
110
read
<=
0
;
//
read diable
111
write
<=
1
;
//
write enable
112
state
<=
1
;
//
next state
113
end
114
115
//
state 1 : read switch & write SDRAM
116
1
: begin
117
if
(DONE)
//
prepared done
118
begin
119
addr
<=
{
23
{
1
'
b0}}; // write SDRAM address
120
data_in
<=
{SW[
15
:
0
]};
//
write SDRAM data
121
122
//
ensure done change to 0
123
read
<=
0
;
//
read disable
124
write
<=
0
;
//
write disable
125
state
<=
2
;
//
next state
126
end
127
end
128
129
//
state 2 : prepare read
130
2
: begin
131
read
<=
1
;
//
read enable
132
write
<=
0
;
//
write disable
133
state
<=
3
;
//
next state
134
end
135
136
//
state 3 : read SDRAM & write to SEG7
137
3
: begin
138
if
(DONE) begin
139
addr
<=
{
23
{
1
'
b0}}; // read SDRAM address
140
data_out
<=
DATA_OUT;
//
read SDRAM data
141
142
read
<=
0
;
//
read disable
143
write
<=
0
;
//
write disable
144
state
<=
0
;
//
next state
145
end
146
end
147
endcase
148
end
149
end
150
151
endmodule
49行
Sdram_Controller u0 (
//
HOST
.REF_CLK(CLOCK_50),
//
system clock
.RESET_N(RESET_n),
//
system reset
.ADDR(address),
//
address for controller request
.WR(write),
//
write request
.RD(read),
//
read request
.LENGTH(
8
'
h02), //request data length
.ACT(),
//
SDRAM ACK(acknowledge)
.DONE(DONE),
//
write/read done
.DATAIN(data_in),
//
Data input
.DATAOUT(DATA_OUT),
//
Data output
.IN_REQ(),
//
input data request
.OUT_VALID(),
//
output data vilid
.DM(
2
'
b00), //Data mask input
//
SDRAM
.SA(DRAM_ADDR),
.BA({DRAM_BA_1,DRAM_BA_0}),
.CS_N(DRAM_CS_N),
.CKE(DRAM_CKE),
.RAS_N(DRAM_RAS_N),
.CAS_N(DRAM_CAS_N),
.WE_N(DRAM_WE_N),
.DQ(DRAM_DQ),
.DQM({DRAM_UDQM,DRAM_LDQM}),
.SDR_CLK(DRAM_CLK)
);
我們引進了Sdram_Controller,這是個2 port的controller,1 read 1 write,大部分狀況下,2 port已經夠用,4 port的我會另外討論。
77行
SEG7_LUT_8 u1 (
.oSEG0(HEX0),
//
output SEG0
.oSEG1(HEX1),
//
output SEG1
.oSEG2(HEX2),
//
output SEG2
.oSEG3(HEX3),
//
output SEG3
.oSEG4(HEX4),
//
output SEG4
.oSEG5(HEX5),
//
output SEG5
.oSEG6(HEX6),
//
output SEG6
.oSEG7(HEX7),
//
output SEG7
.iDIG(data_out),
//
input data
.iWR(
1
'
b1), // write enable
.iCLK(CLOCK_50),
//
clock
.iRESET_n(RESET_n)
//
RESET
);
引進了之前所寫的七段顯示器module,將output用七段顯示器表示。
91行
//
state 0 : prepare write
//
state 1 : read switch & write SDRAM
//
state 2 : prepare read
//
state 3 : read SDRAM & write to SEG7
always @(posedge CLOCK_50 or negedge RESET_n)
begin
if
(
!
RESET_n) begin
addr
<=
0
;
//
address register
read
<=
0
;
//
read enable register
write
<=
0
;
//
write enale register
state
<=
0
;
//
FSM state register
data_in
<=
0
;
//
data input register
end
else
begin
case
(state)
//
state 0 : prepare write
0
: begin
read
<=
0
;
//
read diable
write
<=
1
;
//
write enable
state
<=
1
;
//
next state
end
//
state 1 : read switch & write SDRAM
1
: begin
if
(DONE)
//
prepared done
begin
addr
<=
{
23
{
1
'
b0}}; // write SDRAM address
data_in
<=
{SW[
15
:
0
]};
//
write SDRAM data
//
ensure done change to 0
read
<=
0
;
//
read disable
write
<=
0
;
//
write disable
state
<=
2
;
//
next state
end
end
//
state 2 : prepare read
2
: begin
read
<=
1
;
//
read enable
write
<=
0
;
//
write disable
state
<=
3
;
//
next state
end
//
state 3 : read SDRAM & write to SEG7
3
: begin
if
(DONE) begin
addr
<=
{
23
{
1
'
b0}}; // read SDRAM address
data_out
<=
DATA_OUT;
//
read SDRAM data
state
<=
0
;
//
next state
end
end
endcase
end
end
我們採用了FSM,對SDRAM做存取。
1.當state為0時,送出寫入準備信號。
2.當state為1時,讀取switch值並寫入SDRAM。
3.當state為2時,送出讀取準備信號。
4.當state為3時,讀取SDRAM並回到state 0。
108行
0
: begin
read
<=
0
;
//
read diable
write
<=
1
;
//
write enable
state
<=
1
;
//
next state
end
當state為0時,read <= 0;,write <= 1;表示準備寫入SDRAM,state <= 1;進入下一個state。
115行
//
state 1 : read switch & write SDRAM
1
: begin
if
(DONE)
//
prepared done
begin
addr
<=
{
23
{
1
'
b0}}; // write SDRAM address
data_in
<=
{SW[
15
:
0
]};
//
write SDRAM data
//
ensure done change to 0
read
<=
0
;
//
read disable
write
<=
0
;
//
write disable
state
<=
2
;
//
next state
end
end
這是本程式最重要的一段程式碼。
當state為1時,對SDRAM正式寫入。
當DONE為0時,表示SDRAM還無法讀寫,必須先回到state 0做寫入準備,或state 2做讀取準備,等到DONE為1時才可對SDRAM作正常讀寫。
addr為指定寫入SDRAM的記憶體位址,data_in為欲寫入SDRAM的資料。DE2上的SDRAM容量為8 MB,由4個bank所組成,addr[22:20]為bank數,addr[19:0]為每個bank內的記憶體位址。
最後須將 read <= 0;與wrie <= 0;讓DONE還原成0,因為在Sdram_Controller.v的245行
if
(
!
WR
&&
!
RD)
mDONE
<=
0
;
DONE變成0,SDRAM可重新做讀取與寫入準備。最後 state <= 2;進入下一個state。
130行
//
state 2 : prepare read
2
: begin
read
<=
1
;
//
read enable
write
<=
0
;
//
write disable
state
<=
3
;
//
next state
end
道理同state 0,但此時是做讀取準備。
137行
//
state 3 : read SDRAM & write to SEG7
3
: begin
if
(DONE) begin
addr
<=
{
23
{
1
'
b0}}; // read SDRAM address
data_out
<=
DATA_OUT;
//
read SDRAM data
read
<=
0
;
//
read disable
write
<=
0
;
//
write disable
state
<=
0
;
//
next state
end
end
道理同state 1,但此時是從SDRAM讀取資料,從DATA_OUT讀取資料進register後,回到state 0。
完整程式碼下載
sdram_hr_hw.7z
Conclusion
SDRAM_Controller都放在完整程式碼中,有需要的人可自行下載。
相對於其他記憶體,SDRAM是最麻煩的,但其最便宜且容量最大,當你的資料很大時(如影像處理),使用SDRAM的機會就很大。在此範例也學到循序電路配合FSM後,可重複做不同的事情,這是硬體描述語言慣用的手法。
See Also
(原創) 如何在DE2用軟體存取SDRAM? (IC Design) (DE2) (Nios II)
(原創) 如何顯示8位數的七段顯示器? (IC Design) (Verilog) (DE2)
(原創) 如何在DE2用硬體存取SDRAM(4 port)? (IC Design) (DE2)
(筆記) DE2與SDRAM相關資料總整理 (SOC) (DE2)