-
Notifications
You must be signed in to change notification settings - Fork 3
/
DDR2_Write_VHDL.vhd
211 lines (196 loc) · 5.78 KB
/
DDR2_Write_VHDL.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
---------------------------------------------------------------------
-- File : DDR2_Write_VHDL.vhd
-- Projekt : Prj_12_DDR2
-- Zweck : DDR2-Write-Funktion
-- Datum : 19.08.2011
-- Version : 2.0
-- Plattform : XILINX Spartan-3A
-- FPGA : XC3S700A-FGG484
-- Sprache : VHDL
-- ISE : ISE-Design-Suite V:13.1
-- Autor : UB
-- Mail : Becker_U(at)gmx.de
---------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--------------------------------------------
-- Beschreibung :
--
-- Die State-Machine schreibt
-- einen 64Bit Wert ins RAM
-- in 4 aufeinander folgenden 16bit-Zellen
--
-- die Adresse wird
-- von der übergeordneten CONTROL-Unit
-- gehandelt
--
-- solange die Write-Funktion läuft,
-- ist WRITE_BUSY=1
--------------------------------------------
entity DDR2_Write_VHDL is
--------------------------------------------
-- Port Deklerationen
--------------------------------------------
port (
reset_in : in std_logic;
clk_in : in std_logic;
clk90_in : in std_logic;
w_command_register : out std_logic_vector(2 downto 0);
w_cmd_ack : in std_logic;
w_burst_done : out std_logic;
write_en : in std_logic;
write_busy : out std_logic;
input_data : out std_logic_vector(31 downto 0);
write_data : in std_logic_vector(63 downto 0)
);
end DDR2_Write_VHDL;
architecture Verhalten of DDR2_Write_VHDL is
--------------------------------------------
-- Interne Signale
--------------------------------------------
constant CLK_ANZ : integer := 2; -- warte 3 Clockzyklen (2 bis 0 = 3)
signal v_counter : natural range 0 to CLK_ANZ := CLK_ANZ;
type STATE_WA_TYPE is (
WA_1_NOP,
WA_2_WRITE_CMD,
WA_3_WAIT_4_ACK1,
WA_4_WAIT_3_CLK,
WA_5_BURST_HI,
WA_6_BURST_OK,
WA_7_WAIT_4_ACK0
);
signal STATE_WA : STATE_WA_TYPE := WA_1_NOP;
type STATE_WB_TYPE is (
WB_1_NOP,
WB_2_DATA_LSB,
WB_3_T1,
WB_4_T2,
WB_5_DATA_MSB
);
signal STATE_WB : STATE_WB_TYPE := WB_1_NOP;
begin
-----------------------------------------
-- State-Machine WA : (Clock-0 Lo-Flanke)
-- 1. wartet auf das WRITE_EN=1 von der DDR2_Control
-- 2. sendet das WRITE-Kommando an das RAM
-- 3. wartet auf das ACK=1 vom RAM
-- 4. wartet 3 Clockzyklen
-- (solange dauert das schreiben von 64Bit)
-- 5. legt das BURST_DONE-Signal für 2 Clockzyklen an
-- 6. wartet auf das ACK=0 vom RAM
-- 7. Sprung zu Punkt 1
-----------------------------------------
P_Write_WA : process(clk_in,reset_in)
begin
if reset_in = '1' then
-- reset button ist gedrueckt
STATE_WA <= WA_1_NOP;
w_command_register <= "000"; -- NOP
w_burst_done <= '0';
elsif falling_edge(clk_in) then
case STATE_WA is
when WA_1_NOP =>
-- warte auf write enable signal
w_command_register <= "000"; -- NOP
v_counter <= CLK_ANZ;
w_burst_done <= '0';
if write_en = '1' then
STATE_WA <= WA_2_WRITE_CMD;
end if;
when WA_2_WRITE_CMD =>
-- CMD anlegen
w_command_register <= "100"; -- WRITE-CMD
STATE_WA <= WA_3_WAIT_4_ACK1;
when WA_3_WAIT_4_ACK1 =>
-- warten auf ACK=1 vom RAM
if w_cmd_ack = '1' then
STATE_WA <= WA_4_WAIT_3_CLK;
end if;
when WA_4_WAIT_3_CLK =>
-- warte 3 Clockzyklen
if v_counter = 0 then
-- burst_done auf HI
w_burst_done <= '1';
STATE_WA <= WA_5_BURST_HI;
else
w_burst_done <= '0';
v_counter <= v_counter - 1;
end if;
when WA_5_BURST_HI =>
-- NOP anlegen
w_command_register <= "000"; -- NOP
STATE_WA <= WA_6_BURST_OK;
when WA_6_BURST_OK =>
-- burst_done auf Lo
w_burst_done <= '0';
STATE_WA <= WA_7_WAIT_4_ACK0;
when WA_7_WAIT_4_ACK0 =>
-- warten auf ACK=0 vom RAM
if w_cmd_ack = '0' then
STATE_WA <= WA_1_NOP;
end if;
when others =>
NULL;
end case;
end if;
end process P_Write_WA;
-----------------------------------------
-- State-Machine WB : (Clock-90 Hi-Flanke)
-- 1. wartet bis State-Machine-WA das
-- WRITE-Kommando gesendet hat
-- 2. legt die LSB-Daten (32Bit) für das RAM an
-- 3. wartet auf das ACK=1 vom RAM
-- 4. wartet nochmal 2 Clockzyklen (WICHTIG !!)
-- 5. legt die MSB-Daten (32Bit) für das RAM an
-- 6. wartet bis State-Machine-WA das
-- BURST_DONE-Signal angelegt hat
-- 7. Sprung zu Punkt 1
-----------------------------------------
P_Write_WB : process(clk90_in,reset_in)
begin
if reset_in = '1' then
-- reset button ist gedrueckt
STATE_WB <= WB_1_NOP;
input_data <= (others => '0');
elsif rising_edge(clk90_in) then
case STATE_WB is
when WB_1_NOP =>
-- warte bis write start
input_data <= (others => '0');
if STATE_WA = WA_2_WRITE_CMD then
STATE_WB <= WB_2_DATA_LSB;
end if;
when WB_2_DATA_LSB =>
-- Daten (LSB) anlegen
-- und warten auf ACK
input_data <= write_data(31 downto 0);
if w_cmd_ack = '1' then
STATE_WB <= WB_3_T1;
end if;
when WB_3_T1 =>
input_data <= write_data(31 downto 0);
STATE_WB <= WB_4_T2;
when WB_4_T2 =>
input_data <= write_data(31 downto 0);
STATE_WB <= WB_5_DATA_MSB;
when WB_5_DATA_MSB =>
-- Daten (MSB) anlegen
-- und warten bis Write fertig
input_data <= write_data(63 downto 32);
if STATE_WA = WA_5_BURST_HI then
STATE_WB <= WB_1_NOP;
end if;
when others =>
NULL;
end case;
end if;
end process P_Write_WB;
-----------------------------------------
-- Write-Busy erzeugen :
-- solange der Write-Prozess im Gange
-- ist WRITE_BUSY = 1
-----------------------------------------
write_busy <= '0' when STATE_WA=WA_1_NOP else '1';
end Verhalten;