1 |
2 |
DavidRAMBA |
--=============================================================================
|
2 |
|
|
-- TITRE : IF_SPI
|
3 |
|
|
-- DESCRIPTION :
|
4 |
|
|
-- Implémente une interface SPI master avec une vitesse de clk_sys / div_rate
|
5 |
|
|
-- Le bus parallèle accepte en entrée un flux de données à écrire et fourni
|
6 |
|
|
-- en sortie un flux de données lues.
|
7 |
|
|
-- Il supporte 3 types de commandes selon type_com et sur ordre de exec_com
|
8 |
|
|
-- type_com | opération
|
9 |
|
|
-- 0 | Emet sur SPI la totalité des octets fournis précédemment sur TX_DAT
|
10 |
|
|
-- 1 | Emet sur SPI la totalité des octets fournis précédemment sur TX_DAT
|
11 |
|
|
-- | et récupère en lecture sur SPI nb_read octet et les met à disposition
|
12 |
|
|
-- | sur RX_DAT
|
13 |
|
|
-- FICHIER : if_spi.vhd
|
14 |
|
|
--=============================================================================
|
15 |
|
|
-- CREATION
|
16 |
|
|
-- DATE AUTEUR PROJET REVISION
|
17 |
|
|
-- 29/02/2012 DRA CONCERTO V1.0
|
18 |
|
|
--=============================================================================
|
19 |
|
|
-- HISTORIQUE DES MODIFICATIONS :
|
20 |
|
|
-- DATE AUTEUR PROJET REVISION
|
21 |
|
|
--=============================================================================
|
22 |
|
|
|
23 |
|
|
LIBRARY IEEE;
|
24 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
25 |
|
|
USE IEEE.STD_LOGIC_ARITH.ALL;
|
26 |
|
|
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
-- Uncomment the following library declaration if instantiating
|
31 |
|
|
-- any Xilinx primitives in this code.
|
32 |
|
|
--library UNISIM;
|
33 |
|
|
--use UNISIM.VComponents.all;
|
34 |
|
|
|
35 |
|
|
ENTITY if_smi IS
|
36 |
|
|
GENERIC (
|
37 |
|
|
div_rate : INTEGER := 6 -- Diviseur d'horloge système pour obtenir le débit SMI = 2^div_rate
|
38 |
|
|
);
|
39 |
|
|
PORT (
|
40 |
|
|
-- Ports système
|
41 |
|
|
clk_sys : IN STD_LOGIC; -- Clock système à 64 MHz
|
42 |
|
|
rst_n : IN STD_LOGIC; -- Reset génrél système
|
43 |
|
|
|
44 |
|
|
-- Interface série
|
45 |
|
|
mdc : OUT STD_LOGIC; -- Signal MDC de l'IF SMI
|
46 |
|
|
mdio : INOUT STD_LOGIC; -- Signal MDIO de l'IF SMI
|
47 |
|
|
|
48 |
|
|
smi_datwr : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
|
49 |
|
|
smi_datrd : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
|
50 |
|
|
smi_com : IN STD_LOGIC
|
51 |
|
|
);
|
52 |
|
|
END if_smi;
|
53 |
|
|
|
54 |
|
|
ARCHITECTURE rtl of if_smi is
|
55 |
|
|
SIGNAL div_clk : STD_LOGIC_VECTOR(div_rate-1 DOWNTO 0); -- Compteur pur diviser l'horloge système
|
56 |
|
|
SIGNAL rise_clk : STD_LOGIC; -- Front montant de l'horloge SMI
|
57 |
|
|
SIGNAL fall_clk : STD_LOGIC; -- Front descendant de l'horloge SMI
|
58 |
|
|
SIGNAL mask_clk : STD_LOGIC; -- Signal de masque de l'horloge SMI
|
59 |
|
|
SIGNAL cpt_bit : STD_LOGIC_VECTOR(6 DOWNTO 0); -- Compteur de bit pour le ser/deser
|
60 |
|
|
SIGNAL shifter_tx : STD_LOGIC_VECTOR(63 DOWNTO 0); -- SER Tx
|
61 |
|
|
SIGNAL shifter_rx : STD_LOGIC_VECTOR(15 DOWNTO 0); -- DESER Rx
|
62 |
|
|
SIGNAL txena : STD_LOGIC; -- Pour sortir le MDIO du 'Z'
|
63 |
|
|
SIGNAL sendcom : STD_LOGIC; -- Fenêtre d'envoi d'une commande
|
64 |
|
|
SIGNAL com_rdwrn : STD_LOGIC; -- Pour mémoriser le type de commande RD ou WR
|
65 |
|
|
|
66 |
|
|
BEGIN
|
67 |
|
|
------------------------------------------
|
68 |
|
|
-- Process de generation de la clock SMI
|
69 |
|
|
------------------------------------------
|
70 |
|
|
gen_clk : PROCESS(clk_sys, rst_n)
|
71 |
|
|
BEGIN
|
72 |
|
|
IF (rst_n = '0') THEN
|
73 |
|
|
div_clk <= (OTHERS => '0');
|
74 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
75 |
|
|
div_clk <= div_clk + 1;
|
76 |
|
|
END IF;
|
77 |
|
|
END PROCESS;
|
78 |
|
|
|
79 |
|
|
mdc <= 'Z' WHEN (mask_clk = '0') ELSE div_clk(div_clk'LEFT); -- La clock est active en fonction de la machine d'état
|
80 |
|
|
-- rise_clk est actif au cycle qui précède le front montant effectif
|
81 |
|
|
rise_clk <= '1' WHEN (div_clk = CONV_STD_LOGIC_VECTOR(2**(div_rate-1)-1, div_rate)) ELSE '0';
|
82 |
|
|
-- fall_clk est actif au cycle qui précède le front descendant effectif
|
83 |
|
|
fall_clk <= '1' WHEN (div_clk = CONV_STD_LOGIC_VECTOR(2**div_rate-1, div_rate)) ELSE '0';
|
84 |
|
|
|
85 |
|
|
mdio <= 'Z' WHEN (txena = '0') ELSE shifter_tx(63);
|
86 |
|
|
smi_datrd <= shifter_rx;
|
87 |
|
|
|
88 |
|
|
rx : PROCESS(clk_sys, rst_n)
|
89 |
|
|
BEGIN
|
90 |
|
|
IF (rst_n = '0') THEN
|
91 |
|
|
shifter_rx <= (others => '0');
|
92 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
93 |
|
|
IF (mask_clk = '1' AND rise_clk = '1') THEN
|
94 |
|
|
shifter_rx <= shifter_rx(14 DOWNTO 0) & mdio;
|
95 |
|
|
END IF;
|
96 |
|
|
END IF;
|
97 |
|
|
END PROCESS;
|
98 |
|
|
|
99 |
|
|
com: PROCESS(clk_sys, rst_n)
|
100 |
|
|
BEGIN
|
101 |
|
|
IF (rst_n = '0') THEN
|
102 |
|
|
sendcom <= '0';
|
103 |
|
|
txena <= '0';
|
104 |
|
|
com_rdwrn <= '0';
|
105 |
|
|
mask_clk <= '0';
|
106 |
|
|
shifter_tx <= (others => '1');
|
107 |
|
|
cpt_bit <= (OTHERS => '0');
|
108 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
109 |
|
|
IF (sendcom = '1') THEN
|
110 |
|
|
IF (fall_clk = '1') THEN
|
111 |
|
|
IF (cpt_bit = "0000000") THEN
|
112 |
|
|
mask_clk <= '1';
|
113 |
|
|
txena <= '1';
|
114 |
|
|
cpt_bit <= cpt_bit + 1;
|
115 |
|
|
ELSE
|
116 |
|
|
IF (cpt_bit /= "1000000") THEN
|
117 |
|
|
cpt_bit <= cpt_bit + 1;
|
118 |
|
|
shifter_tx <= shifter_tx(62 downto 0) & '0';
|
119 |
|
|
ELSE
|
120 |
|
|
mask_clk <= '0';
|
121 |
|
|
sendcom <= '0';
|
122 |
|
|
txena <= '0';
|
123 |
|
|
END IF;
|
124 |
|
|
-- IF (cpt_bit = "0110000") AND (com_rdwrn = '1') THEN
|
125 |
|
|
IF (cpt_bit = "0101110") AND (com_rdwrn = '1') THEN
|
126 |
|
|
txena <= '0';
|
127 |
|
|
END IF;
|
128 |
|
|
END IF;
|
129 |
|
|
END IF;
|
130 |
|
|
ELSE
|
131 |
|
|
IF (smi_com = '1') THEN
|
132 |
|
|
cpt_bit <= (OTHERS => '0');
|
133 |
|
|
sendcom <= '1'; -- On mémorise la réception de la commande
|
134 |
|
|
shifter_tx <= x"FFFFFFFF" & smi_datwr; --"0101" & "00000" & "11011" & "00" & "1000000000000000";
|
135 |
|
|
IF (smi_datwr(29 DOWNTO 28) = "01") THEN
|
136 |
|
|
com_rdwrn <= '0';
|
137 |
|
|
ELSIF (smi_datwr(29 DOWNTO 28) = "00") THEN
|
138 |
|
|
com_rdwrn <= smi_datwr(27); -- Cas particulier des registres spéciaux du SWITCH
|
139 |
|
|
ELSE
|
140 |
|
|
com_rdwrn <= '1';
|
141 |
|
|
END IF;
|
142 |
|
|
END IF;
|
143 |
|
|
END IF;
|
144 |
|
|
END IF;
|
145 |
|
|
END PROCESS;
|
146 |
|
|
|
147 |
|
|
END rtl;
|
148 |
|
|
|