1 ----------------------------------------------------------------------------------
2 --
Company:
3 --
Engineer: shangdawei@gmail.com
4 --
5 -- Create Date:
08:
46:
25 05/
12/
2012
6 --
Design Name:
7 -- Module Name: spi_master -
Behavioral
8 --
Project Name:
9 --
Target Devices:
10 --
Tool versions:
11 --
Description:
12 --
13 --
Dependencies:
14 --
15 --
Revision:
16 -- Revision
0.01 -
File Created
17 --
Additional Comments:
18 --
19 ----------------------------------------------------------------------------------
20
21 library IEEE;
22 use IEEE.std_logic_1164.
all;
23
24 -- Uncomment the following
library declaration
if using
25 -- arithmetic functions
with Signed
or Unsigned values
26 use IEEE.NUMERIC_STD.
all;
27
28 -- Uncomment the following
library declaration
if instantiating
29 -- any Xilinx primitives
in this code.
30 --
library UNISIM;
31 --
use UNISIM.VComponents.
all;
32
33 entity spi_master
is
34 generic (
35 C_MODE : natural :=
0; -- dymatic change enabled
when C_MODE >
3
36 C_WIDTH : natural :=
9 );
37 port (
38 i_clock :
in std_logic; --
system clock
39 i_tick :
in std_logic; --
xfer enable
40 i_cpol :
in std_logic; --
spi clock polarity
41 i_cpha :
in std_logic; --
spi clock phase
42 o_sck :
out std_logic; --
spi clock
43 o_ss_n :
out std_logic; -- spi ss_n ( Ready/
nBusy )
44 o_mosi :
out std_logic; -- master
out, slave
in
45 i_miso :
in std_logic; -- master
in, slave
out
46 i_repeat :
in std_logic; --
repeat receive
47 i_tx_valid :
in std_logic; --
initiate transaction
48 o_tx_taken :
out std_logic; --
tx data taken
49 o_rx_valid :
out std_logic; --
rx data valid
50 i_tx_msb :
in std_logic_vector (
4 downto 0); -- msb
of transmit word
51 o_rx_data :
out std_logic_vector (C_WIDTH-
1 downto 0); -- (
to fifo
or rdr )
52 i_tx_data :
in std_logic_vector (C_WIDTH-
1 downto 0)); -- ( from fifo
or tdr )
53 end spi_master;
54
55 architecture Behavioral
of spi_master
is
56
57 signal cpha :
std_logic;
58 signal cpol :
std_logic;
59 signal cpol_cpha : unsigned (
1 downto 0);
60 signal rx_sample :
std_logic;
61 signal tx_taken :
std_logic :=
'0';
62 signal tx_pending :
std_logic :=
'0';
63 signal rx_last :
std_logic;
64 signal rx_done :
std_logic :=
'0';
65 signal xfer_done :
std_logic :=
'0';
66 signal rx_valid :
std_logic :=
'0';
67 signal miso :
std_logic;
68 signal sck :
std_logic :=
'0';
69 signal mosi :
std_logic :=
'0';
70 signal ss_n :
std_logic :=
'1';
71 signal rx_cntr : unsigned(
5 downto 0 ) := (
others =>
'0' ); -- max
32 bits
72 signal shift_reg :
std_logic_vector (C_WIDTH-
1 downto 0) := (
others =>
'0' );
73 signal sreg_load :
std_logic;
74
75 begin
76 o_sck <=
sck;
77 o_mosi <=
mosi;
78 o_ss_n <=
ss_n;
79 o_tx_taken <=
tx_taken;
80 o_rx_valid <=
rx_valid;
81 o_rx_data <=
shift_reg;
82
83 cpol_cpha <= to_unsigned( C_MODE,
2 );
84 cpha <= i_cpha
when C_MODE >
3 else cpol_cpha(
0);
85 cpol <= i_cpol
when C_MODE >
3 else cpol_cpha(
1);
86
87 rx_sample <= (
not ( sck
xor cpha
xor cpol ) )
and (
not ss_n ); -- diff
with cpha/
cpol
88 rx_last <=
'1' when ( rx_cntr = unsigned(i_tx_msb) )
and ( sck = ( cpha
xor cpol) )
else '0';
89 rx_done <= rx_last
when rising_edge( i_clock )
and (i_tick =
'1' ); --
for both cpha
90 sreg_load <= ( i_tx_valid
and ss_n )
or ( i_tx_valid
and rx_done ); -- idle
or running
91
92 -- xfer done : whether restart
next xfer,
or go idle
93 process begin
94 wait until rising_edge( i_clock );
95 if (i_tick =
'1' )
then
96 if ( cpha =
'0' )
then
97 xfer_done <=
rx_done;
98 else -- ( cpha =
'1' )
99 xfer_done <=
rx_last;
100 end if;
101 end if;
102 end process;
103
104 process begin
105 wait until rising_edge( i_clock );
106 if rx_last = '1' then -- rx_last : 1 spi clock cycle
107 rx_valid <= i_tick; -- rx_valid : 1 clock cycle
108 else
109 rx_valid <= '0';
110 end if;
111 end process;
112
113 -- host can
write next data
to xfer
114 process begin
115 wait until rising_edge( i_clock );
116 if ss_n = '1' then -- first xfer only, always tx_taken
117 tx_taken <= i_tick and sreg_load;
118 else -- last xfer no tx_taken ( sreg_load = '0' )
119 tx_taken <= i_tick and rx_done and sreg_load;
120 end if; -- other xfer give ack
121 end process;
122
123 --
Counting SPI word length : rx_bit #
124 process begin
125 wait until rising_edge( i_clock );
126 if (i_tick =
'1' )
then
127 if ( ss_n =
'1' )
or ( rx_last =
'1' )
then
128 rx_cntr <= (
others =>
'0' );
129 elsif (sck = ( cpha
xor cpol ) )
then
130 rx_cntr <= rx_cntr +
1;
131 end if;
132 end if;
133 end process;
134
135 process begin
136 wait until rising_edge( i_clock );
137 if (i_tick =
'1' )
then
138 if cpha =
'0' then
139 if ( rx_done =
'1' )
then
140 tx_pending <=
sreg_load;
141 elsif ( xfer_done =
'1' )
then
142 tx_pending <=
'0';
143 end if;
144 end if;
145 end if;
146 end process;
147
148
149 --
Writing the ss_n
150 -- xfer done : whether restart
next xfer,
or go idle
151 process begin
152 wait until rising_edge( i_clock );
153 if (i_tick =
'1' )
then
154 if ( i_tx_valid =
'1' )
then -- xfer_done -> tx_taken ->
i_tx_valid
155 ss_n <=
'0'; -- i_tx_valid
until xfer_done
for cpha =
'1'
156
157 elsif ( xfer_done =
'1' )
then -- cpha =
'0'
158 ss_n <= (
not i_repeat)
and (
not tx_pending ) ;
159 end if;
160 end if;
161 end process;
162
163 --
Generating the SPI clock
164 -- xfer done : whether restart
next xfer,
or go idle
165 process begin
166 wait until rising_edge( i_clock );
167 if (i_tick =
'1' )
then
168 if ( xfer_done =
'1' )
then --- cpha =
'1' --- --- cpha =
'0' ---
169 if ( i_repeat =
'1' )
or ( sreg_load =
'1' )
or ( tx_pending =
'1' )
then
170 sck <=
not sck;
171 else
172 sck <= cpol; --
idle
173 end if;
174 elsif ( ss_n =
'0' )
then
175 sck <=
not sck;
176 else
177 sck <= cpol; --
idle
178 end if;
179 end if;
180 end process;
181
182 -- Writing the mosi from init data
or shifted data
183 process begin
184 wait until rising_edge( i_clock );
185 if (i_tick =
'1' )
then
186 if sreg_load =
'1' then
187 -- mosi <=
i_tx_data( to_integer( unsigned(i_tx_msb) ) );
188 mosi <=
shift_reg( to_integer( unsigned(i_tx_msb) ) );
189 else
190 mosi <=
shift_reg( to_integer( unsigned(i_tx_msb) ) );
191 end if;
192 end if;
193 end process;
194
195 -- Reading the miso
line and shifting
for mosi at
next tick
196 process begin
197 wait until rising_edge( i_clock );
198 if (i_tick =
'1' )
then
199 if sreg_load =
'1' then
200 shift_reg <=
i_tx_data;
201 elsif ( rx_sample =
'1' )
then -- mosi
is ready
to set at
next i_tick
202 shift_reg <= shift_reg(shift_reg
'high-1 downto 0 ) & i_miso;
203
204 end if;
205 end if;
206 end process;
207
208 end Behavioral;
1 --------------------------------------------------------------------------------
2 --
Company:
3 --
Engineer:
4 --
5 -- Create Date:
23:
02:
26 05/
13/
2012
6 --
Design Name:
7 -- Module Name: D:/projects/arm9_ise/chapter8/chapter8/
spi_xfer_tb.vhd
8 --
Project Name: chapter8
9 --
Target Device:
10 --
Tool versions:
11 --
Description:
12 --
13 -- VHDL Test Bench Created by ISE
for module: spi_xfer
14 --
15 --
Dependencies:
16 --
17 --
Revision:
18 -- Revision
0.01 -
File Created
19 --
Additional Comments:
20 --
21 --
Notes:
22 -- This testbench has been automatically generated using types
std_logic and
23 --
std_logic_vector for the ports
of the unit under test. Xilinx recommends
24 -- that these types always be used
for the top-level I/O
of a design
in order
25 --
to guarantee that the testbench will bind correctly
to the post-
implementation
26 --
simulation model.
27 --------------------------------------------------------------------------------
28 library ieee;
29 use ieee.std_logic_1164.
all;
30
31 -- Uncomment the following
library declaration
if using
32 -- arithmetic functions
with Signed
or Unsigned values
33 use ieee.numeric_std.
all;
34
35 entity spi_xfer_tb
is
36 end spi_xfer_tb;
37
38 architecture behavior
of spi_xfer_tb
is
39
40 constant C_MODE : natural :=
4;
41 constant C_WIDTH : natural :=
8;
42
43 -- Component Declaration
for the Unit Under Test (UUT)
44
45 component spi_xfer
46 generic (
47 C_MODE : natural :=
4; --
dymatic change enabled
48 C_WIDTH : natural :=
16 );
49 port (
50 i_clock :
in std_logic; --
system clock
51 i_tick :
in std_logic; --
xfer enable
52 i_cpol :
in std_logic; --spi clock polarity -- sck
when idle
53 i_cpha :
in std_logic; --
spi clock phase
54 i_miso :
in std_logic; --master
in, slave
out
55 o_mosi :
out std_logic; --master
out, slave
in
56 o_sck :
out std_logic; --
spi clock
57 o_ss_n :
out std_logic; --
spi ss_n
58 i_repeat :
in std_logic; --
xfering ...
59 i_tx_valid :
in std_logic; --
initiate transaction
60 i_tx_data :
in std_logic_vector (C_WIDTH-
1 downto 0); --data
to transmit
61 i_tx_msb :
in std_logic_vector (
4 downto 0); -- #
of bit to transmit word
62 o_tx_taken :
out std_logic; --
tx data complete
63 o_rx_data :
out std_logic_vector (C_WIDTH-
1 downto 0); --
data received
64 o_rx_valid :
out std_logic); --
rx data ready
65 end component;
66
67
68 --
Inputs
69 signal i_repeat :
std_logic :=
'0';
70 signal i_clock :
std_logic :=
'0';
71 signal i_tick :
std_logic :=
'0';
72 signal i_cpol :
std_logic :=
'0';
73 signal i_cpha :
std_logic :=
'0';
74 signal i_miso :
std_logic :=
'0';
75 signal i_tx_valid :
std_logic :=
'0';
76 signal i_tx_data :
std_logic_vector(C_WIDTH-
1 downto 0) := (
others =>
'0');
77 signal i_tx_msb :
std_logic_vector(
4 downto 0) :=
std_logic_vector( to_unsigned(C_WIDTH-
1,
5) );
78
79 --
Outputs
80 signal o_ss_n :
std_logic; --
spi ss_n
81 signal o_mosi :
std_logic;
82 signal o_sck :
std_logic;
83 signal o_tx_taken :
std_logic;
84 signal o_rx_data :
std_logic_vector(C_WIDTH-
1 downto 0);
85 signal o_rx_valid :
std_logic;
86
87 signal tx_cntr : unsigned(
15 downto 0) := X
"0000";
88 --
Clock period definitions
89 constant i_clock_period :
time :=
10 ns;
90
91 constant spi_div : natural :=
1;
92 signal tick_sr : unsigned(spi_div
downto 0) := to_unsigned(
1, spi_div+
1);
93
94 begin
95
96 --
Instantiate the Unit Under Test (UUT)
97 uut : spi_xfer
98 generic map (
99 C_MODE =>
C_MODE,
100 C_WIDTH =>
C_WIDTH )
101 port map (
102 i_clock =>
i_clock,
103 i_tick =>
i_tick,
104 i_cpol =>
i_cpol,
105 i_cpha =>
i_cpha,
106 i_miso =>
i_miso,
107 o_mosi =>
o_mosi,
108 o_sck =>
o_sck,
109 o_ss_n =>
o_ss_n,
110 i_repeat =>
i_repeat,
111 i_tx_valid =>
i_tx_valid,
112 i_tx_data =>
i_tx_data,
113 i_tx_msb =>
i_tx_msb,
114 o_tx_taken =>
o_tx_taken,
115 o_rx_data =>
o_rx_data,
116 o_rx_valid =>
o_rx_valid
117 );
118
119 -- Clock
process definitions
120 i_clock_process :
process
121 begin
122 i_clock <=
'0';
123 wait for i_clock_period/
2;
124 i_clock <=
'1';
125 wait for i_clock_period/
2;
126 end process;
127
128 i_tick <= tick_sr(
0);
129 tick_sr <= tick_sr(tick_sr
'high-1 downto 0) & tick_sr(tick_sr'high)
when rising_edge ( i_clock );
130
131 -- Stimulus
process
132 stim_proc :
133 process ( i_clock )
134 begin
135 if rising_edge( i_clock )
then
136 if ( tx_cntr <
100 )
then --
delay
137 i_cpol <=
'0';
138 i_cpha <=
'0';
139 i_tx_msb <=
"00111";
140 i_tx_data <= X
"55";
141 tx_cntr <= tx_cntr +
1;
142 elsif ( tx_cntr <
103 )
then --
setup
143 if ( tx_cntr =
100 )
then
144 i_tx_valid <=
'1';
145 tx_cntr <= tx_cntr +
1;
146 elsif ( o_tx_taken =
'1' )
then
147 i_tx_data <= i_tx_data(i_tx_data
'high-1 downto 0) & i_tx_data(i_tx_data'high);
148 tx_cntr <= tx_cntr +
1;
149 end if;
150
151 elsif ( tx_cntr <
120 )
then --
delay
152 i_tx_valid <=
'0';
153 if ( o_ss_n =
'1' )
then
154 i_cpol <=
'0';
155 i_cpha <=
'1';
156 tx_cntr <= tx_cntr +
1;
157 end if;
158 elsif ( tx_cntr <
123 )
then
159 if ( tx_cntr =
120 )
then
160 i_tx_valid <=
'1';
161 tx_cntr <= tx_cntr +
1;
162 elsif ( o_tx_taken =
'1' )
then
163 i_tx_data <= i_tx_data(i_tx_data
'high-1 downto 0) & i_tx_data(i_tx_data'high);
164 tx_cntr <= tx_cntr +
1;
165 end if;
166
167 elsif ( tx_cntr <
140 )
then --
delay
168 i_tx_valid <=
'0';
169 if ( o_ss_n =
'1' )
then
170 i_cpol <=
'1';
171 i_cpha <=
'0';
172 tx_cntr <= tx_cntr +
1;
173 end if;
174 elsif ( tx_cntr <
143 )
then
175 if ( tx_cntr =
140 )
then
176 i_tx_valid <=
'1';
177 tx_cntr <= tx_cntr +
1;
178 elsif ( o_tx_taken =
'1' )
then
179 i_tx_data <= i_tx_data(i_tx_data
'high-1 downto 0) & i_tx_data(i_tx_data'high);
180 tx_cntr <= tx_cntr +
1;
181 end if;
182
183 elsif ( tx_cntr <
160 )
then
184 i_tx_valid <=
'0';
185 if ( o_ss_n =
'1' )
then
186 i_cpol <=
'1';
187 i_cpha <=
'1';
188 tx_cntr <= tx_cntr +
1;
189 end if;
190 elsif ( tx_cntr <
163 )
then
191 if ( tx_cntr =
160 )
then
192 i_tx_valid <=
'1';
193 tx_cntr <= tx_cntr +
1;
194 elsif ( o_tx_taken =
'1' )
then
195 i_tx_data <= i_tx_data(i_tx_data
'high-1 downto 0) & i_tx_data(i_tx_data'high);
196 tx_cntr <= tx_cntr +
1;
197 end if;
198
199 elsif ( tx_cntr <
180 )
then
200 i_tx_valid <=
'0';
201 if ( o_ss_n =
'1' )
then
202 i_cpol <=
'0';
203 i_cpha <=
'0';
204 tx_cntr <= tx_cntr +
1;
205 end if;
206 elsif ( tx_cntr <
183 )
then
207 if ( tx_cntr =
180 )
then
208 i_tx_valid <=
'1';
209 tx_cntr <= tx_cntr +
1;
210 elsif ( o_tx_taken =
'1' )
then
211 i_repeat <=
'1';
212 i_tx_valid <=
'0';
213 tx_cntr <= to_unsigned(
183, tx_cntr
'length);
214 end if;
215 elsif ( tx_cntr <
185 )
then
216 if o_rx_valid =
'1' then
217 tx_cntr <= tx_cntr +
1;
218 end if;
219 else
220 i_repeat <=
'0';
221 end if;
222 end if;
223 end process;
224
225
226 end;
转载于:https://www.cnblogs.com/shangdawei/archive/2012/05/16/2503706.html
相关资源:数据结构—成绩单生成器