3641 |
kaklik |
1 |
-- this module transmit a given constant data when requested |
|
|
2 |
-- and then signals done. |
|
|
3 |
-- |
|
|
4 |
-- G_DATA has to contain also the address and the r/w bit |
|
|
5 |
-- |
|
|
6 |
-- MSB of G_DATA will go first |
|
|
7 |
-- P1DATA_P2DATA_P3DATA |
|
|
8 |
-- |
|
|
9 |
-- version for multiple devices with different data |
|
|
10 |
|
|
|
11 |
library ieee; |
|
|
12 |
use ieee.std_logic_1164.all; |
|
|
13 |
use ieee.numeric_std.all; |
|
|
14 |
|
|
|
15 |
entity spi_master_transmit is |
|
|
16 |
generic ( |
|
|
17 |
G_DATA1 : std_logic_vector; |
|
|
18 |
G_DATA2 : std_logic_vector; |
|
|
19 |
G_NUM_BITS_PACKET : integer; |
|
|
20 |
G_NUM_PACKETS : integer; |
|
|
21 |
G_NUM_BITS_PAUSE : integer |
|
|
22 |
); |
|
|
23 |
port ( |
|
|
24 |
|
|
|
25 |
i_clk : in std_logic; |
|
|
26 |
i_rst : in std_logic; |
|
|
27 |
|
|
|
28 |
o_done : out std_logic; |
|
|
29 |
|
|
|
30 |
-- selects which data to transfer. If '0', it transfers G_DATA1 |
|
|
31 |
i_data_selector : in std_logic; |
|
|
32 |
|
|
|
33 |
-- SPI ports: |
|
|
34 |
o_n_ce : out std_logic_vector; |
|
|
35 |
o_dout : out std_logic; |
|
|
36 |
o_clk : out std_logic |
|
|
37 |
|
|
|
38 |
); |
|
|
39 |
|
|
|
40 |
end spi_master_transmit; |
|
|
41 |
|
|
|
42 |
architecture behavioral of spi_master_transmit is |
|
|
43 |
|
|
|
44 |
subtype t_pause_counter is integer range 0 to G_NUM_BITS_PAUSE; |
|
|
45 |
signal s_pause_counter : t_pause_counter; |
|
|
46 |
subtype t_bit_counter is integer range 0 to G_NUM_BITS_PACKET - 1; |
|
|
47 |
signal s_bit_counter : t_bit_counter; |
|
|
48 |
subtype t_packet_counter is integer range 0 to G_NUM_PACKETS; |
|
|
49 |
signal s_packet_counter : t_packet_counter; |
|
|
50 |
subtype t_device_counter is integer range 0 to o_n_ce'length - 1; |
|
|
51 |
signal s_device_counter : t_device_counter; |
|
|
52 |
|
|
|
53 |
signal s_clk_inv : std_logic; |
|
|
54 |
|
|
|
55 |
--signal s_o_dout_d : std_logic; |
|
|
56 |
signal s_o_clk_en : std_logic; |
|
|
57 |
|
|
|
58 |
constant C_DATALEN_PER_DEVICE : integer := G_NUM_BITS_PACKET*G_NUM_PACKETS; |
|
|
59 |
|
|
|
60 |
signal s_cs_out : std_logic_vector( o_n_ce'range ); |
|
|
61 |
|
|
|
62 |
begin |
|
|
63 |
|
|
|
64 |
assert( G_DATA1'length = C_DATALEN_PER_DEVICE*o_n_ce'length ) report "The size of G_DATA1 does not match the number of devices and other generics." severity failure; |
|
|
65 |
assert( G_DATA2'length = C_DATALEN_PER_DEVICE*o_n_ce'length ) report "The size of G_DATA2 does not match the number of devices and other generics." severity failure; |
|
|
66 |
|
|
|
67 |
-- inverted clock: |
|
|
68 |
s_clk_inv <= not i_clk; |
|
|
69 |
|
|
|
70 |
-- output clock: |
|
|
71 |
o_clk <= i_clk and s_o_clk_en; |
|
|
72 |
|
|
|
73 |
-- done: |
|
|
74 |
o_done <= '1' when ( (i_rst = '0') and (s_packet_counter = 0) and (s_pause_counter = 0) and (s_bit_counter = 0 ) and (s_device_counter=0) ) else |
|
|
75 |
'0'; |
|
|
76 |
|
|
|
77 |
transmitter_process : process( s_clk_inv ) |
|
|
78 |
begin |
|
|
79 |
if( rising_edge( s_clk_inv ) ) then |
|
|
80 |
if( i_rst = '1' ) then |
|
|
81 |
s_bit_counter <= 0; |
|
|
82 |
s_pause_counter <= t_pause_counter'high; |
|
|
83 |
s_packet_counter <= t_packet_counter'high; |
|
|
84 |
s_device_counter <= t_device_counter'high; |
|
|
85 |
s_cs_out( s_cs_out'low ) <= '0'; |
|
|
86 |
s_cs_out( s_cs_out'high downto s_cs_out'low+1 ) <= ( others => '1' ); |
|
|
87 |
o_n_ce <= ( o_n_ce'range => '1' ); |
|
|
88 |
o_dout <= '0'; |
|
|
89 |
s_o_clk_en <= '0'; |
|
|
90 |
elsif( s_bit_counter > 0 ) then |
|
|
91 |
o_n_ce <= s_cs_out; |
|
|
92 |
if( i_data_selector = '0' ) then |
|
|
93 |
o_dout <= G_DATA1( s_bit_counter + s_packet_counter*G_NUM_BITS_PACKET - 1 + s_device_counter*C_DATALEN_PER_DEVICE ); -- here s_packet_counter points to the current packet and s_bit_counter is one bit behind, therefore the -1. |
|
|
94 |
else |
|
|
95 |
o_dout <= G_DATA2( s_bit_counter + s_packet_counter*G_NUM_BITS_PACKET - 1 + s_device_counter*C_DATALEN_PER_DEVICE ); |
|
|
96 |
end if; |
|
|
97 |
s_bit_counter <= s_bit_counter - 1; |
|
|
98 |
s_o_clk_en <= '1'; |
|
|
99 |
elsif( s_pause_counter > 0 ) then |
|
|
100 |
o_n_ce <= ( o_n_ce'range => '1' ); |
|
|
101 |
s_pause_counter <= s_pause_counter - 1; |
|
|
102 |
o_dout <= '0'; |
|
|
103 |
s_o_clk_en <= '0'; |
|
|
104 |
elsif( s_packet_counter > 0 ) then |
|
|
105 |
s_bit_counter <= t_bit_counter'high; |
|
|
106 |
s_pause_counter <= t_pause_counter'high; |
|
|
107 |
s_packet_counter <= s_packet_counter - 1; |
|
|
108 |
o_n_ce <= s_cs_out; |
|
|
109 |
if( i_data_selector = '0' ) then |
|
|
110 |
o_dout <= G_DATA1( s_bit_counter + s_packet_counter*G_NUM_BITS_PACKET - 1 + s_device_counter*C_DATALEN_PER_DEVICE ); -- here s_bit_counter = 0, s_packet_counter points to previous packet. Therefore -1 to get the msb of current packet. |
|
|
111 |
else |
|
|
112 |
o_dout <= G_DATA2( s_bit_counter + s_packet_counter*G_NUM_BITS_PACKET - 1 + s_device_counter*C_DATALEN_PER_DEVICE ); |
|
|
113 |
end if; |
|
|
114 |
s_o_clk_en <= '1'; |
|
|
115 |
elsif( s_device_counter > 0 ) then |
|
|
116 |
s_cs_out <= s_cs_out( s_cs_out'high-1 downto s_cs_out'low ) & '1'; |
|
|
117 |
s_device_counter <= s_device_counter - 1; |
|
|
118 |
|
|
|
119 |
-- follows pause. |
|
|
120 |
s_bit_counter <= 0; |
|
|
121 |
s_pause_counter <= t_pause_counter'high; |
|
|
122 |
s_packet_counter <= t_packet_counter'high; |
|
|
123 |
o_n_ce <= ( o_n_ce'range => '1' ); |
|
|
124 |
o_dout <= '0'; |
|
|
125 |
s_o_clk_en <= '0'; |
|
|
126 |
|
|
|
127 |
end if; |
|
|
128 |
end if; |
|
|
129 |
end process; |
|
|
130 |
|
|
|
131 |
|
|
|
132 |
end architecture; |