1 | %------------------------------------------------------------------------------ |
---|
2 | % $Id: document-morpheo-vhdl_generation-fr.tex 94 2008-12-15 11:04:03Z rosiere $ |
---|
3 | %------------------------------------------------------------------------------ |
---|
4 | |
---|
5 | \SEction{Introduction} |
---|
6 | |
---|
7 | Ce document est une aide pour les développeur des générateurs de modèles VHDL de \cpu. |
---|
8 | Il est décomposé en 5 sections : |
---|
9 | \begin{itemize} |
---|
10 | \item Dans la section \ref{tree}, nous présentons l'arborescence des répertoires. |
---|
11 | \item Dans la section \ref{vhdl_declaration}, nous expliciterons l'API ({\it Application Programming Interface}) pour la déclaration des signaux et des types du VHDL. |
---|
12 | \item Dans la section \ref{vhdl_body}, nous présenterons l'API pour générer le comportement des composants. |
---|
13 | \item Dans la section \ref{vhdl_structural}, nous expliquerons la manière de créer des sous composants. |
---|
14 | \item Dans la section \ref{example}, nous montrerons quelques exemples. |
---|
15 | \end{itemize} |
---|
16 | |
---|
17 | \Section{Arborescence}\label{tree} |
---|
18 | |
---|
19 | Dans le répertoire contenant le projet, nous avons les répertoires suivant : |
---|
20 | \begin{description} |
---|
21 | \item[IPs/systemC/processor/Morpheo/Documentation/ :] Contient différent document décrivant certain point du projet, dont cette documentation. |
---|
22 | \item[IPs/systemC/processor/Morpheo/Behavioural/ :] |
---|
23 | \item[IPs/systemC/processor/Morpheo/Behavioural/include/ :] |
---|
24 | \begin{description} |
---|
25 | \item [Parameters.h :] Contient la classe {\it Parameters}, cette classe définit les paramètres constants. |
---|
26 | \item [Vhdl.h :] Contient la classe {\it Vhdl}. |
---|
27 | \end{description} |
---|
28 | \item[IPs/systemC/processor/Morpheo/Behavioural/\dots/Component :] Chaque composant est inclue dans un répertoire spécifique. |
---|
29 | \item[IPs/systemC/processor/Morpheo/Behavioural/\dots/Component/include :] |
---|
30 | \begin{description} |
---|
31 | \item [Parameters.h :] Contient la classe {\it Parameters}, elle dérive de la classe contenu dans le fichier le répertoire {\it \dots/Behavioural/include/}. |
---|
32 | \item [Component.h :] Contient la classe {\it Component}. Il définit l'interface, les registres ainsi que les méthodes du modèle systemC. |
---|
33 | \item [Types.h :] Contient les types spéciaux. |
---|
34 | \end{description} |
---|
35 | \item[IPs/systemC/processor/Morpheo/Behavioural/\dots/Component/src :] |
---|
36 | \begin{description} |
---|
37 | \item [Component\_transition.cpp :] |
---|
38 | \item [Component\_genMoore.cpp :] |
---|
39 | \item [Component\_genMealy\_XXX.cpp :] |
---|
40 | |
---|
41 | \item [Component\_vhdl\_declaration.cpp :] |
---|
42 | \item [Component\_vhdl\_body.cpp :] |
---|
43 | \end{description} |
---|
44 | \item[IPs/systemC/processor/Morpheo/Behavioural/\dots/Component/Selftest :] |
---|
45 | \end{description} |
---|
46 | |
---|
47 | \Section{VHDL : déclaration}\label{vhdl_declaration} |
---|
48 | |
---|
49 | Les déclarations ce font dans le fichier {\it Component\_vhdl\_declaration.cpp}. |
---|
50 | |
---|
51 | \subSection{Interfaces} |
---|
52 | L'interface est définit dans le modèle SystemC. Il n'ont pas nécessaire de la redéfinir pour le modèle VHDL. |
---|
53 | |
---|
54 | La nomenclature est la suivante : |
---|
55 | \begin{itemize} |
---|
56 | \item La direction en minuscule ({\it in}, {\it out}). |
---|
57 | \item Le nom de l'interface en majuscule ({\it READ}, {\it PUSH}, \dots). |
---|
58 | \item Le numéro de l'interface (la première interface aura le numéro 0. S'il n'y a qu'une interface, celle ci aura tout de même le numéro 0). |
---|
59 | \item Le nom du signal en majuscule ({\it VAL}, {\it ADDRESS}, \dots). |
---|
60 | \end{itemize} |
---|
61 | |
---|
62 | Par exemple pour la 2 ème interface de lecture d'un banc de registre : |
---|
63 | \begin{verbatim} |
---|
64 | in_READ_1_VAL : in std_logic; |
---|
65 | out_READ_1_ACK : out std_logic; |
---|
66 | in_READ_1_ADDRESS : in std_logic_vector(8 downto 0); |
---|
67 | out_READ_1_DATA : out std_logic_vector(31 downto 0); |
---|
68 | \end{verbatim} |
---|
69 | |
---|
70 | Chaque composent (aussi bien combinatoire que séquentielle) possède un signal d'horloge et un signal de reset. (Ce dernier est actif à l'état bas). Ils ont tout les deux le même nom quelque soit le composant. |
---|
71 | \begin{verbatim} |
---|
72 | in_CLOCK : in std_logic; |
---|
73 | in_NRESET : in std_logic; |
---|
74 | \end{verbatim} |
---|
75 | |
---|
76 | \subSection{Types} |
---|
77 | |
---|
78 | Le type de base utilisé est le {\it std\_logic\_vector} (ou std\_logic si le vecteur est sur un seul bit). Pour cela on utilise la fonction suivante : |
---|
79 | |
---|
80 | \begin{verbatim} |
---|
81 | std::string std_logic (uint32_t size); |
---|
82 | \end{verbatim} |
---|
83 | |
---|
84 | Pour accéder à une partie du vecteur on utilise la fonction {\it std\_logic\_range}. Elle a les prototypes suivant : |
---|
85 | \begin{verbatim} |
---|
86 | std::string std_logic_range (uint32_t size, |
---|
87 | uint32_t max , |
---|
88 | uint32_t min , |
---|
89 | bool force=false); |
---|
90 | std::string std_logic_range (uint32_t max , |
---|
91 | uint32_t min , |
---|
92 | bool force=false); |
---|
93 | std::string std_logic_range (uint32_t size, |
---|
94 | bool force=false); |
---|
95 | \end{verbatim} |
---|
96 | |
---|
97 | La première fonction fais un test sur la taille que la seconde ne fait pas. |
---|
98 | L'argument de la troisième définit la taille (ce qui implique que la borne minimum est 0 et la borne maximum est size-1). |
---|
99 | Toute les surcharges ont le bolléen optionnel {\it force}. S'il est à faux, alors des tests seront effectués sur les bornes et la taille, sinon aucun test n'est effectué. |
---|
100 | |
---|
101 | Par exemple : |
---|
102 | \begin{verbatim} |
---|
103 | std_logic_range(4,false) renvoie "(3 downto 0)". |
---|
104 | std_logic_range(1,false) renvoie "(0)". |
---|
105 | std_logic_range(1,true ) renvoie "(0 downto 0)". |
---|
106 | \end{verbatim} |
---|
107 | |
---|
108 | Pour les types plus complexe, la classe {\it Vhdl} possède une méthode générique. Le premier argument est le nom du type le second est le type. |
---|
109 | |
---|
110 | \begin{verbatim} |
---|
111 | void set_type (std::string name, |
---|
112 | std::string type); |
---|
113 | \end{verbatim} |
---|
114 | |
---|
115 | L'exemple suivant définit un type représentat un tableau de {\it nb\_word} mots de {\it size\_word} bit chacun : |
---|
116 | \begin{verbatim} |
---|
117 | vhdl->set_type ("Tregfile", |
---|
118 | "array "+std_logic_range(nb_word)+" of "+std_logic(size_word)); |
---|
119 | \end{verbatim} |
---|
120 | |
---|
121 | \subSection{Constantes} |
---|
122 | |
---|
123 | La déclaration de constante, ce fait avec la méthode {\it set\_constant} de la classe {\it Vhdl}. Les différentes surcharges de cette méthode est le type des arguments {\it type} et {\it init}. |
---|
124 | |
---|
125 | \begin{verbatim} |
---|
126 | void set_constant (std::string name, |
---|
127 | std::string type, |
---|
128 | std::string init); |
---|
129 | void set_constant (std::string name, |
---|
130 | uint32_t size, |
---|
131 | std::string init); |
---|
132 | void set_constant (std::string name, |
---|
133 | uint32_t size, |
---|
134 | uint32_t init); |
---|
135 | \end{verbatim} |
---|
136 | |
---|
137 | Par exemple pour coder les états d'un automate à 5 états en One Hot : |
---|
138 | \begin{verbatim} |
---|
139 | vhdl->set_constant ("State_idle",5,1); |
---|
140 | \end{verbatim} |
---|
141 | |
---|
142 | Dans le cas de signaux de type {\it std\_logic}, au lieu de déclarer des constantes, il existe deux fonctions permettant d'utiliser des constantes directement dans le corps du composant. |
---|
143 | La première est {\it std\_logic\_others}. Elle permet de définir des constantes dont soit les bits sont à pleins un soit à plein zéro. |
---|
144 | |
---|
145 | \begin{verbatim} |
---|
146 | std::string std_logic_others (uint32_t size, |
---|
147 | bool cst ); |
---|
148 | \end{verbatim} |
---|
149 | |
---|
150 | Pour toute les autres constantes, la méthode {\it std\_logic\_conv} transforme un entier en {\it std\_logic\_vector}. |
---|
151 | |
---|
152 | \begin{verbatim} |
---|
153 | std::string std_logic_conv (uint32_t size, |
---|
154 | std::string value); |
---|
155 | std::string std_logic_conv (uint32_t size, |
---|
156 | uint32_t value); |
---|
157 | \end{verbatim} |
---|
158 | |
---|
159 | |
---|
160 | \subSection{Signaux internes} |
---|
161 | |
---|
162 | Les signaux internes sont définit grâce au méthode {\it set\_signal}. Le premier argument est le nom du signal. Le second est soit un type soit une taille (dans le cas où le type est un {\it std\_logic\_vector}). |
---|
163 | \begin{verbatim} |
---|
164 | void set_signal (std::string name, |
---|
165 | std::string type); |
---|
166 | void set_signal (std::string name, |
---|
167 | uint32_t size); |
---|
168 | \end{verbatim} |
---|
169 | |
---|
170 | La méthode est également surchargé si le signal à besoin d'une initialisation. |
---|
171 | |
---|
172 | \begin{verbatim} |
---|
173 | void set_signal (std::string name, |
---|
174 | std::string type, |
---|
175 | std::string init); |
---|
176 | void set_signal (std::string name, |
---|
177 | uint32_t size, |
---|
178 | std::string init); |
---|
179 | void set_signal (std::string name, |
---|
180 | uint32_t size, |
---|
181 | uint32_t init); |
---|
182 | \end{verbatim} |
---|
183 | |
---|
184 | En vhdl il est possible de renommer une champ d'un signal. Ceci ce fait à l'aide de la fonction {\it set\_alias}. Elle prend 4 arguments. Le premier étant le nom du signal après le renommage. le second est soit le type, soit la taille du {\it std\_logic\_vector} du signal rénommé. Les deux derniers conserné le signal à renommé : le nom de ce dernier ainsi que l'intervalle. Pour le dernier paramètre il est recommandé d'utilisé la fonction {\it std\_logic\_range}. |
---|
185 | |
---|
186 | \begin{verbatim} |
---|
187 | void set_alias (std::string name1 , |
---|
188 | std::string type1 , |
---|
189 | std::string name2 , |
---|
190 | std::string range2); |
---|
191 | void set_alias (std::string name1 , |
---|
192 | uint32_t size1 , |
---|
193 | std::string name2 , |
---|
194 | std::string range2); |
---|
195 | \end{verbatim} |
---|
196 | |
---|
197 | |
---|
198 | \Section{VHDL : comportement}\label{vhdl_body} |
---|
199 | |
---|
200 | Le comportement du composant est définit dans le fichier {\it Component\_vhdl\_body.cpp}. |
---|
201 | |
---|
202 | Il n'y a pas de fonction aidant à l'écriture du Vhdl. |
---|
203 | La méthode {\it set\_body} permet de définir une ligne de code VHDL. Un retour à la ligne est automatiquement inséré. Le premier argument est pour l'indentation. |
---|
204 | \begin{verbatim} |
---|
205 | void set_body (uint32_t depth, |
---|
206 | std::string text ); |
---|
207 | void set_body (std::string text ); |
---|
208 | \end{verbatim} |
---|
209 | |
---|
210 | Pour les commentaires, il y a la fonction {\it set\_comment}. |
---|
211 | \begin{verbatim} |
---|
212 | void set_comment (uint32_t depth, |
---|
213 | std::string text ); |
---|
214 | void set_comment (std::string text ); |
---|
215 | \end{verbatim} |
---|
216 | |
---|
217 | |
---|
218 | |
---|
219 | \Section{VHDL : structurelle}\label{vhdl_structural} |
---|
220 | |
---|
221 | \Section{Exemples}\label{example} |
---|
222 | |
---|
223 | \subSection{Banc de Registres Monolithique} |
---|
224 | |
---|
225 | \subsubSection{Fichier RegisterFile\_Monolithic\_vhdl\_declaration.cpp} |
---|
226 | \begin{verbatim} |
---|
227 | void RegisterFile_Monolithic::vhdl_declaration (Vhdl * & vhdl) |
---|
228 | { |
---|
229 | vhdl->set_type ("Tregfile", "array " + std_logic_range(_param->_nb_word,true)+ |
---|
230 | " of "+ |
---|
231 | std_logic(_param->_size_word)); |
---|
232 | |
---|
233 | vhdl->set_signal ("reg_DATA", "Tregfile"); |
---|
234 | }; |
---|
235 | \end{verbatim} |
---|
236 | \subsubSection{Fichier RegisterFile\_Monolithic\_vhdl\_body.cpp} |
---|
237 | \begin{verbatim} |
---|
238 | void RegisterFile_Monolithic::vhdl_body (Vhdl * & vhdl) |
---|
239 | { |
---|
240 | vhdl->set_body (0,""); |
---|
241 | vhdl->set_comment(0,"---------------------------------------------------"); |
---|
242 | vhdl->set_comment(0," Ackitement"); |
---|
243 | vhdl->set_comment(0,"---------------------------------------------------"); |
---|
244 | vhdl->set_body (0,""); |
---|
245 | |
---|
246 | for (uint32_t i = 0; i < _param->_nb_port_read; i++) |
---|
247 | vhdl->set_body (0,"out_READ_"+toString(i)+"_ACK <= '1';"); |
---|
248 | for (uint32_t i = 0; i < _param->_nb_port_write; i++) |
---|
249 | vhdl->set_body (0,"out_WRITE_"+toString(i)+"_ACK <= '1';"); |
---|
250 | |
---|
251 | vhdl->set_body (0,""); |
---|
252 | vhdl->set_comment(0,"---------------------------------------------------"); |
---|
253 | vhdl->set_comment(0," Read RegisterFile"); |
---|
254 | vhdl->set_comment(0,"---------------------------------------------------"); |
---|
255 | vhdl->set_body (0,""); |
---|
256 | |
---|
257 | for (uint32_t i = 0; i < _param->_nb_port_read; i++) |
---|
258 | { |
---|
259 | std::string str_address; |
---|
260 | if (_param->_have_port_address) |
---|
261 | str_address = "conv_integer(in_READ_"+toString(i)+"_ADDRESS)"; |
---|
262 | else |
---|
263 | str_address = "0"; |
---|
264 | |
---|
265 | vhdl->set_body (0,"out_READ_"+toString(i)+"_DATA <= reg_DATA ("+str_address+ |
---|
266 | ") when in_READ_"+toString(i)+"_VAL = '1' else "+ |
---|
267 | std_logic_others(_param->_size_word,0)+";"); |
---|
268 | } |
---|
269 | |
---|
270 | vhdl->set_body (0,""); |
---|
271 | vhdl->set_comment(0,"---------------------------------------------------"); |
---|
272 | vhdl->set_comment(0," Write RegisterFile"); |
---|
273 | vhdl->set_comment(0,"---------------------------------------------------"); |
---|
274 | vhdl->set_body (0,""); |
---|
275 | |
---|
276 | vhdl->set_body (0,"RegisterFile_write: process (in_CLOCK)"); |
---|
277 | vhdl->set_body (0,"begin -- process RegisterFile_write"); |
---|
278 | vhdl->set_body (1,"if in_CLOCK'event and in_CLOCK = '1' then"); |
---|
279 | |
---|
280 | for (uint32_t i = 0; i < _param->_nb_port_write; i++) |
---|
281 | { |
---|
282 | std::string str_address; |
---|
283 | if (_param->_have_port_address) |
---|
284 | str_address = "conv_integer(in_WRITE_"+toString(i)+"_ADDRESS)"; |
---|
285 | else |
---|
286 | str_address = "0"; |
---|
287 | |
---|
288 | vhdl->set_body (2,"if (in_WRITE_"+toString(i)+"_VAL = '1') then"); |
---|
289 | vhdl->set_body (3,"reg_DATA("+str_address+") <= in_WRITE_"+toString(i)+"_DATA;"); |
---|
290 | vhdl->set_body (2,"end if;"); |
---|
291 | } |
---|
292 | |
---|
293 | vhdl->set_body (1,"end if;"); |
---|
294 | vhdl->set_body (0,"end process RegisterFile_write;"); |
---|
295 | }; |
---|
296 | \end{verbatim} |
---|
297 | |
---|
298 | \subsubSection{Fichier RegisterFile\_Monolithic.vhdl} |
---|
299 | \begin{verbatim} |
---|
300 | library ieee; |
---|
301 | use ieee.numeric_bit.all; |
---|
302 | use ieee.numeric_std.all; |
---|
303 | use ieee.std_logic_1164.all; |
---|
304 | use ieee.std_logic_arith.all; |
---|
305 | use ieee.std_logic_misc.all; |
---|
306 | --use ieee.std_logic_signed.all; |
---|
307 | use ieee.std_logic_unsigned.all; |
---|
308 | --use ieee.std_logic_textio.all; |
---|
309 | |
---|
310 | |
---|
311 | library work; |
---|
312 | use work.RegisterFile_Monolithic_Pack.all; |
---|
313 | |
---|
314 | |
---|
315 | entity RegisterFile_Monolithic is |
---|
316 | port ( in_CLOCK : in std_logic; |
---|
317 | in_NRESET : in std_logic; |
---|
318 | in_READ_0_VAL : in std_logic; |
---|
319 | out_READ_0_ACK : out std_logic; |
---|
320 | in_READ_0_ADDRESS : in std_logic_vector(8 downto 0); |
---|
321 | out_READ_0_DATA : out std_logic_vector(31 downto 0); |
---|
322 | in_WRITE_0_VAL : in std_logic; |
---|
323 | out_WRITE_0_ACK : out std_logic; |
---|
324 | in_WRITE_0_ADDRESS: in std_logic_vector(8 downto 0); |
---|
325 | in_WRITE_0_DATA : in std_logic_vector(31 downto 0) |
---|
326 | ); |
---|
327 | end RegisterFile_Monolithic; |
---|
328 | |
---|
329 | architecture behavioural of RegisterFile_Monolithic is |
---|
330 | type Tregfile is array (511 downto 0) of std_logic_vector(31 downto 0); |
---|
331 | |
---|
332 | signal reg_DATA : Tregfile; |
---|
333 | |
---|
334 | begin |
---|
335 | ----------------------------------------------------- |
---|
336 | -- Ackitement |
---|
337 | ----------------------------------------------------- |
---|
338 | |
---|
339 | out_READ_0_ACK <= '1'; |
---|
340 | out_WRITE_0_ACK <= '1'; |
---|
341 | |
---|
342 | ----------------------------------------------------- |
---|
343 | -- Read RegisterFile |
---|
344 | ----------------------------------------------------- |
---|
345 | |
---|
346 | out_READ_0_DATA <= reg_DATA (conv_integer(in_READ_0_ADDRESS)) |
---|
347 | when in_READ_0_VAL = '1' |
---|
348 | else (others => '0'); |
---|
349 | |
---|
350 | ----------------------------------------------------- |
---|
351 | -- Write RegisterFile |
---|
352 | ----------------------------------------------------- |
---|
353 | |
---|
354 | RegisterFile_write: process (in_CLOCK) |
---|
355 | begin -- process RegisterFile_write |
---|
356 | if in_CLOCK'event and in_CLOCK = '1' then |
---|
357 | if (in_WRITE_0_VAL = '1') then |
---|
358 | reg_DATA(conv_integer(in_WRITE_0_ADDRESS)) <= in_WRITE_0_DATA; |
---|
359 | end if; |
---|
360 | end if; |
---|
361 | end process RegisterFile_write; |
---|
362 | end behavioural; |
---|
363 | |
---|
364 | \end{verbatim} |
---|