1 http:
//eewiki.net/display/LOGIC/Serial+Peripheral+Interface+(SPI)+Master+(VHDL)
2
3 --------------------------------------------------------------------------------
4 --
5 --
FileName: spi_master.vhd
6 --
Dependencies: none
7 -- Design Software: Quartus II Version
9.0 Build
132 SJ Full Version
8 --
9 -- HDL CODE
IS PROVIDED
"AS IS." DIGI-
KEY EXPRESSLY DISCLAIMS ANY
10 -- WARRANTY
OF ANY KIND, WHETHER EXPRESS
OR IMPLIED, INCLUDING BUT
NOT
11 -- LIMITED
TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY, FITNESS
FOR A
12 -- PARTICULAR PURPOSE,
OR NON-INFRINGEMENT.
IN NO EVENT SHALL DIGI-
KEY
13 -- BE LIABLE
FOR ANY INCIDENTAL, SPECIAL, INDIRECT
OR CONSEQUENTIAL
14 -- DAMAGES, LOST PROFITS
OR LOST DATA, HARM
TO YOUR EQUIPMENT, COST
OF
15 -- PROCUREMENT
OF SUBSTITUTE GOODS, TECHNOLOGY
OR SERVICES, ANY CLAIMS
16 -- BY THIRD PARTIES (INCLUDING BUT
NOT LIMITED
TO ANY DEFENSE THEREOF),
17 -- ANY CLAIMS
FOR INDEMNITY
OR CONTRIBUTION,
OR OTHER SIMILAR COSTS.
18 --
19 --
Version History
20 -- Version
1.0 7/
23/
2010 Scott Larson
21 --
Initial Public Release
22 --
23 --------------------------------------------------------------------------------
24
25 library ieee;
26 use ieee.std_logic_1164.
all;
27 use ieee.std_logic_arith.
all;
28 use ieee.std_logic_unsigned.
all;
29
30 entity spi_master
is
31 generic(
32 slaves :
INTEGER :=
8; --number
of spi slaves
33 d_width :
INTEGER :=
8); --data
bus width
34 port(
35 clock :
in STD_LOGIC; --
system clock
36 reset_n :
in STD_LOGIC; --
asynchronous reset
37 enable :
in STD_LOGIC; --
initiate transaction
38 cpol :
in STD_LOGIC; --
spi clock polarity
39 cpha :
in STD_LOGIC; --
spi clock phase
40 cont :
in STD_LOGIC; --
continuous mode command
41 clk_div :
in INTEGER; --system clock cycles per
1/
2 period
of sclk
42 addr :
in INTEGER; --address
of slave
43 tx_data :
in STD_LOGIC_VECTOR(d_width-
1 downto 0); --data
to transmit
44 miso :
in STD_LOGIC; --master
in, slave
out
45 sclk :
buffer STD_LOGIC; --
spi clock
46 ss_n :
buffer STD_LOGIC_VECTOR(slaves-
1 downto 0); --slave
select
47 mosi :
out STD_LOGIC; --master
out, slave
in
48 busy :
out STD_LOGIC; --busy / data ready
signal
49 rx_data :
out STD_LOGIC_VECTOR(d_width-
1 downto 0)); --
data received
50 end spi_master;
51
52 architecture logic
of spi_master
is
53 type machine
is(ready, execute); --state machine data
type
54 signal state : machine; --
current state
55 signal slave :
INTEGER; --slave selected
for current transaction
56 signal clk_ratio :
INTEGER; --
current clk_div
57 signal count :
INTEGER; --counter
to trigger sclk from system clock
58 signal clk_toggles :
INTEGER range 0 to d_width*
2 +
1; --
count spi clock toggles
59 signal assert_data :
STD_LOGIC; --
'1' is tx sclk toggle,
'0' is rx sclk toggle
60 signal continue :
STD_LOGIC; --flag
to continue transaction
61 signal rx_buffer :
STD_LOGIC_VECTOR(d_width-
1 downto 0); --receive data
buffer
62 signal tx_buffer :
STD_LOGIC_VECTOR(d_width-
1 downto 0); --transmit data
buffer
63 signal last_bit_rx :
INTEGER range 0 to d_width*
2; --last rx data
bit location
64 begin
65 process(clock, reset_n)
66 begin
67
68 if(reset_n =
'0')
then --
reset system
69 busy <=
'1'; --set busy
signal
70 ss_n <= (
others =>
'1'); --deassert
all slave
select lines
71 mosi <=
'Z'; --set master
out to high impedance
72 rx_data <= (
others =>
'0'); --clear receive data
port
73 state <= ready; --go
to ready state
when reset
is exited
74
75 elsif(clock
'EVENT and clock = '1') then
76 case state
is --
state machine
77
78 when ready =>
79 busy <=
'0'; --clock
out not busy
signal
80 ss_n <= (
others =>
'1'); --set
all slave
select outputs high
81 mosi <=
'Z'; --set mosi
output high impedance
82 continue <=
'0'; --
clear continue flag
83
84 --user
input to initiate transaction
85 if(enable =
'1')
then
86 busy <=
'1'; --set busy
signal
87 if(addr < slaves)
then --check
for valid slave address
88 slave <= addr; --clock
in current slave selection
if valid
89 else
90 slave <=
0; --set
to first slave
if not valid
91 end if;
92 if(clk_div =
0)
then --check
for valid spi speed
93 clk_ratio <=
1; --set
to maximum speed
if zero
94 count <=
1; --initiate system-
to-
spi clock counter
95 else
96 clk_ratio <= clk_div; --set
to input selection
if valid
97 count <= clk_div; --initiate system-
to-
spi clock counter
98 end if;
99 sclk <= cpol; --
set spi clock polarity
100 assert_data <=
not cpha; --
set spi clock phase
101 tx_buffer <= tx_data; --clock
in data
for transmit into
buffer
102 clk_toggles <=
0; --
initiate clock toggle counter
103 last_bit_rx <= d_width*
2 + conv_integer(cpha) -
1; --set last rx data
bit
104 state <= execute; --proceed
to execute state
105 else
106 state <= ready; --remain
in ready state
107 end if;
108
109 when execute =>
110 busy <=
'1'; --set busy
signal
111 ss_n(slave) <=
'0'; --set proper slave
select output
112
113 --system clock
to sclk ratio
is met
114 if(count = clk_ratio)
then
115 count <=
1; --reset system-
to-
spi clock counter
116 assert_data <=
not assert_data; --switch transmit/
receive indicator
117 clk_toggles <= clk_toggles +
1; --
increment spi clock toggles counter
118
119 --
spi clock toggle needed
120 if(clk_toggles <= d_width*
2 and ss_n(slave) =
'0')
then
121 sclk <=
not sclk; --
toggle spi clock
122 end if;
123
124 --
receive spi clock toggle
125 if(assert_data =
'0' and clk_toggles < last_bit_rx +
1 and ss_n(slave) =
'0')
then
126 rx_buffer <= rx_buffer(d_width-
2 downto 0) & miso; --shift
in received
bit
127 end if;
128
129 --
transmit spi clock toggle
130 if(assert_data =
'1' and clk_toggles < last_bit_rx)
then
131 mosi <= tx_buffer(d_width-
1); --clock
out data
bit
132 tx_buffer <= tx_buffer(d_width-
2 downto 0) &
'0'; --shift data transmit
buffer
133 end if;
134
135 --
last data receive, but continue
136 if(clk_toggles = last_bit_rx
and cont =
'1')
then
137 tx_buffer <= tx_data; --reload transmit
buffer
138 clk_toggles <= last_bit_rx - d_width*
2 +
1; --
reset spi clock toggle counter
139 continue <=
'1'; --
set continue flag
140 end if;
141
142 --normal
end of transaction, but continue
143 if(continue =
'1')
then
144 continue <=
'0'; --
clear continue flag
145 busy <=
'0'; --clock
out signal that first receive data
is ready
146 rx_data <= rx_buffer; --clock
out received data
to output port
147 end if;
148
149 --
end of transaction
150 if((clk_toggles = d_width*
2 +
1)
and cont =
'0')
then
151 busy <=
'0'; --clock
out not busy
signal
152 ss_n <= (
others =>
'1'); --set
all slave selects high
153 mosi <=
'Z'; --set mosi
output high impedance
154 rx_data <= rx_buffer; --clock
out received data
to output port
155 state <= ready; --
return to ready state
156 else --
not end of transaction
157 state <= execute; --remain
in execute state
158 end if;
159
160 else --system clock
to sclk ratio
not met
161 count <= count +
1; --
increment counter
162 state <= execute; --remain
in execute state
163 end if;
164
165 end case;
166 end if;
167 end process;
168 end logic;
转载于:https://www.cnblogs.com/shangdawei/archive/2012/05/14/2498945.html
相关资源:数据结构—成绩单生成器