1 --===========================================================================--
2 -- --
3 -- Synthesizable Serial Peripheral Interface Master --
4 -- --
5 --===========================================================================--
6 --
7 -- File name : spi-
master.vhd
8 --
9 -- Entity name : spi-
master
10 --
11 --
Purpose : Implements a SPI Master Controller
12 --
13 --
Dependencies : ieee.std_logic_1164
14 --
ieee.std_logic_unsigned
15 --
16 --
Author : Hans Huebner
17 --
18 --
Email : hans@huebner.org
19 --
20 -- Web : http:
//opencores.org/project,system09
21 --
22 --
Description : This core implements a SPI master interface.
23 -- Transfer size
is 4,
8,
12 or 16 bits.
24 -- The SPI clock
is 0 when idle, sampled
on
25 -- the rising edge
of the SPI clock.
26 -- The SPI clock
is derived from the
bus clock
input
27 -- divided by
2,
4,
8 or 16.
28 --
29 -- clk, reset, cs, rw, addr, data_in, data_out
and irq
30 -- represent the System09
bus interface.
31 -- spi_clk, spi_mosi, spi_miso
and spi_cs_n are the
32 --
standard SPI signals meant
to be routed off-
chip.
33 --
34 -- The SPI core provides
for four
register addresses
35 -- that the CPU can
read or writen
to:
36 --
37 -- Base + $
00 ->
DL: Data Low LSB
38 -- Base + $
01 ->
DH: Data High MSB
39 -- Base + $
02 -> CS: Command/
Status
40 -- Base + $
03 ->
CO: Config
41 --
42 --
CS: Write bits:
43 --
44 -- CS[
0] START : Start transfer
45 -- CS[
1]
END : Deselect device
after transfer
46 -- (
or immediately
if START =
'0')
47 -- CS[
2] IRQEN : Generate IRQ at
end of transfer
48 -- CS[
6:
4] SPIAD : SPI device address
49 --
50 --
CS: Read bits
51 --
52 -- CS[
0] BUSY : Currently transmitting data
53 --
54 --
CO: Write bits
55 --
56 -- CO[
1:
0] DIVIDE: SPI clock divisor,
57 --
00=clk/
2,
58 --
01=clk/
4,
59 --
10=clk/
8,
60 --
11=clk/
16
61 -- CO[
3:
2] LENGTH: Transfer length,
62 --
00=
4 bits,
63 --
01=
8 bits,
64 --
10=
12 bits,
65 --
11=
16 bits
66 --
67 -- Copyright (C)
2009 -
2010 Hans Huebner
68 --
69 -- This program
is free software: you can redistribute it
and/
or modify
70 -- it under the terms
of the GNU General Public License as published by
71 -- the Free Software Foundation, either version
3 of the License,
or
72 --
(at your option) any later version.
73 --
74 -- This program
is distributed
in the hope that it will be useful,
75 -- but WITHOUT ANY WARRANTY; without even the implied warranty
of
76 -- MERCHANTABILITY
or FITNESS
FOR A PARTICULAR PURPOSE. See the
77 -- GNU General Public License
for more details.
78 --
79 -- You should have received a copy
of the GNU General Public License
80 -- along
with this program. If
not, see <http:
//www.gnu.org/licenses/>.
81 --
82 --
83 --===========================================================================--
84 -- --
85 -- Revision History --
86 -- --
87 --===========================================================================--
88 --
89 --
Version Author Date Description
90 --
91 --
0.1 Hans Huebner
23 February
2009 SPI
bus master
for System09
92 --
0.2 John Kent
16 June
2010 Added GPL notice
93 --
94 --
95
96 library ieee;
97 use ieee.std_logic_1164.
all;
98 use ieee.std_logic_unsigned.
all;
99
100 entity spi_master
is
101 port (
102 --
103 --
CPU Interface Signals
104 --
105 clk :
in std_logic;
106 reset :
in std_logic;
107 cs :
in std_logic;
108 rw :
in std_logic;
109 addr :
in std_logic_vector(
1 downto 0);
110 data_in :
in std_logic_vector(
7 downto 0);
111 data_out :
out std_logic_vector(
7 downto 0);
112 irq :
out std_logic;
113 --
114 --
SPI Interface Signals
115 --
116 spi_miso :
in std_logic;
117 spi_mosi :
out std_logic;
118 spi_clk :
out std_logic;
119 spi_cs_n :
out std_logic_vector(
7 downto 0)
120 );
121 end;
122
123 architecture rtl
of spi_master
is
124
125 -- State
type of the SPI transfer state machine
126 type state_type
is (s_idle, s_running);
127 signal state : state_type;
128 -- Shift
register
129 signal shift_reg :
std_logic_vector(
15 downto 0);
130 -- Buffer
to hold data
to be sent
131 signal spi_data_buf :
std_logic_vector(
15 downto 0);
132 --
Start transmission flag
133 signal start :
std_logic;
134 -- Number
of bits transfered
135 signal count :
std_logic_vector(
3 downto 0);
136 --
Buffered SPI clock
137 signal spi_clk_buf :
std_logic;
138 -- Buffered SPI clock
output
139 signal spi_clk_out :
std_logic;
140 --
Previous SPI clock state
141 signal prev_spi_clk :
std_logic;
142 -- Number
of clk cycles-
1 in this SPI clock period
143 signal spi_clk_count :
std_logic_vector(
2 downto 0);
144 --
SPI clock divisor
145 signal spi_clk_divide :
std_logic_vector(
1 downto 0);
146 --
SPI transfer length
147 signal transfer_length :
std_logic_vector(
1 downto 0);
148 -- Flag
to indicate that the SPI slave should be deselected
after the current
149 --
transfer
150 signal deselect :
std_logic;
151 -- Flag
to indicate that an IRQ should be generated at the
end of a transfer
152 signal irq_enable :
std_logic;
153 -- Internal chip
select signal, will be demultiplexed through the cs_mux
154 signal spi_cs :
std_logic;
155 --
Current SPI device address
156 signal spi_addr :
std_logic_vector(
2 downto 0);
157 begin
158
159 -- Read CPU
bus into internal registers
160 cpu_write :
process(clk, reset)
161 begin
162 if reset =
'1' then
163 deselect <=
'0';
164 irq_enable <=
'0';
165 start <=
'0';
166 spi_clk_divide <=
"11";
167 transfer_length <=
"11";
168 spi_data_buf <= (
others =>
'0');
169 elsif
falling_edge(clk)
then
170 start <=
'0';
171 if cs =
'1' and rw =
'0' then
172 case addr
is
173 when "00" =>
174 spi_data_buf(
7 downto 0) <=
data_in;
175 when "01" =>
176 spi_data_buf(
15 downto 8) <=
data_in;
177 when "10" =>
178 start <= data_in(
0);
179 deselect <= data_in(
1);
180 irq_enable <= data_in(
2);
181 spi_addr <= data_in(
6 downto 4);
182 when "11" =>
183 spi_clk_divide <= data_in(
1 downto 0);
184 transfer_length <= data_in(
3 downto 2);
185 when others =>
186 null;
187 end case;
188 end if;
189 end if;
190 end process;
191
192 -- Provide data
for the CPU
to read
193 cpu_read :
process(shift_reg, addr, state, deselect, start)
194 begin
195 data_out <= (
others =>
'0');
196 case addr
is
197 when "00" =>
198 data_out <= shift_reg(
7 downto 0);
199 when "01" =>
200 data_out <= shift_reg(
15 downto 8);
201 when "10" =>
202 if state = s_idle
then
203 data_out(
0) <=
'0';
204 else
205 data_out(
0) <=
'1';
206 end if;
207 data_out(
1) <=
deselect;
208 when others =>
209 null;
210 end case;
211 end process;
212
213 spi_cs_n <=
"11111110" when spi_addr =
"000" and spi_cs =
'1' else
214 "11111101" when spi_addr =
"001" and spi_cs =
'1' else
215 "11111011" when spi_addr =
"010" and spi_cs =
'1' else
216 "11110111" when spi_addr =
"011" and spi_cs =
'1' else
217 "11101111" when spi_addr =
"100" and spi_cs =
'1' else
218 "11011111" when spi_addr =
"101" and spi_cs =
'1' else
219 "10111111" when spi_addr =
"110" and spi_cs =
'1' else
220 "01111111" when spi_addr =
"111" and spi_cs =
'1' else
221 "11111111";
222
223 --
SPI transfer state machine
224 spi_proc :
process(clk, reset)
225 begin
226 if reset =
'1' then
227 count <= (
others =>
'0');
228 shift_reg <= (
others =>
'0');
229 prev_spi_clk <=
'0';
230 spi_clk_out <=
'0';
231 spi_cs <=
'0';
232 state <=
s_idle;
233 irq <=
'Z';
234 elsif
falling_edge(clk)
then
235 prev_spi_clk <=
spi_clk_buf;
236 irq <=
'Z';
237 case state
is
238 when s_idle =>
239 if start =
'1' then
240 count <= (
others =>
'0');
241 shift_reg <=
spi_data_buf;
242 spi_cs <=
'1';
243 state <=
s_running;
244 elsif deselect =
'1' then
245 spi_cs <=
'0';
246 end if;
247 when s_running =>
248 if prev_spi_clk =
'1' and spi_clk_buf =
'0' then
249 spi_clk_out <=
'0';
250 count <= count +
"0001";
251 shift_reg <= shift_reg(
14 downto 0) &
spi_miso;
252 if ((count =
"0011" and transfer_length =
"00")
253 or (count =
"0111" and transfer_length =
"01")
254 or (count =
"1011" and transfer_length =
"10")
255 or (count =
"1111" and transfer_length =
"11"))
then
256 if deselect =
'1' then
257 spi_cs <=
'0';
258 end if;
259 if irq_enable =
'1' then
260 irq <=
'1';
261 end if;
262 state <=
s_idle;
263 end if;
264 elsif prev_spi_clk =
'0' and spi_clk_buf =
'1' then
265 spi_clk_out <=
'1';
266 end if;
267 when others =>
268 null;
269 end case;
270 end if;
271 end process;
272
273 --
Generate SPI clock
274 spi_clock_gen :
process(clk, reset)
275 begin
276 if reset =
'1' then
277 spi_clk_count <= (
others =>
'0');
278 spi_clk_buf <=
'0';
279 elsif
falling_edge(clk)
then
280 if state = s_running
then
281 if ((spi_clk_divide =
"00")
282 or (spi_clk_divide =
"01" and spi_clk_count =
"001")
283 or (spi_clk_divide =
"10" and spi_clk_count =
"011")
284 or (spi_clk_divide =
"11" and spi_clk_count =
"111"))
then
285 spi_clk_buf <=
not spi_clk_buf;
286 spi_clk_count <= (
others =>
'0');
287 else
288 spi_clk_count <= spi_clk_count +
"001";
289 end if;
290 else
291 spi_clk_buf <=
'0';
292 end if;
293 end if;
294 end process;
295
296 spi_mosi_mux :
process(shift_reg, transfer_length)
297 begin
298 case transfer_length
is
299 when "00" =>
300 spi_mosi <= shift_reg(
3);
301 when "01" =>
302 spi_mosi <= shift_reg(
7);
303 when "10" =>
304 spi_mosi <= shift_reg(
11);
305 when "11" =>
306 spi_mosi <= shift_reg(
15);
307 when others =>
308 null;
309 end case;
310 end process;
311
312 spi_clk <=
spi_clk_out;
313
314 end rtl;
转载于:https://www.cnblogs.com/shangdawei/archive/2012/05/16/2503736.html
相关资源:数据结构—成绩单生成器