Guidelines de indentado, nombres de variables, etc.:
----------------------------------------------------
Este es un pequeño fuente VHDL donde se muestran las convenciones de
indentado, nombres de las variables y detalles similares.
SETEdit fue modificado para incorporar la mayor parte posible de ayudas
tendientes a facilitar estos guidelines. En cada punto se explica que ayudas
provee el editor.
Encabezado:
-----------
El encabezado elegido es compatible con los requerimientos de OpenCores.
A ese encabezado se le agregaron datos interesantes tomando como ideas las
recomendaciones de la ESA (European Space Agency) y otras que se me
ocurrieron.
SETEdit: pmacro "\h"
Duda: el $Log de CVS es requerido en todas las recomendaciones, pero es como
mucho a mi modo de ver, es cuestión de probar.
Mayúsculas/minúsculas:
----------------------
En las palabras reservadas:
---------------------------
Mi gusto personal es que la primer letra sea mayúscula y el resto minúsculas,
por ejemplo:
Entity Prueba is
Generic(
);
Port(
);
End Entity Prueba;
Pero casi nadie usa esto y los guidelines de la ESA lo prohiben.
En las variables y demás:
-------------------------
La ESA recomienda identificadores con case mezclado. Pero OpenCores
recomienda single case para signals.
Solución: entities, architectures, funciones, procedimientos, etc. mezclado.
signals, variables, types, etc. lower.
constants y generics upper.
Largos de identificadores:
--------------------------
Se recomienda no exceder los 15 caracteres en signals, ports, etc. y los 13
caracteres en constants. El bakalint usa estos valore por defecto pero pueden
cambiarse.
Library/Use:
------------
Se colocan en líneas separadas y sin indentado.
Ejemplo:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
SETEdit: pmacro "#i" (Library/Use)
pmacro "#I" (Use)
pmacro "li" (IEEE standard libraries)
Entity/Architecture:
--------------------
Se utiliza el indentado por defecto de 3 caracteres.
Las declaraciones de los generic y port también indentan así.
Ejemplo:
entity Prueba is
generic(
XXXX : std_logic:='0');
port(
yyyy_i : in std_logic);
end entity Prueba;
architecture RTL of Prueba is
begin
código;
end architecture RTL; -- Entity: Prueba
Los port se declaran de a un valor por línea (no más) y se les agrega a sus
nombres _i, _o o _io para indicar el sentido. No se puede usar tipo buffer.
Hay que intentar evitar usar _i, _o y _io para señales, es preferible quitar
el _ en ese caso.
Las señales del bus wishbone agregan wb_ delante (además de _i o _o detrás).
Se deberá tratar de mantener alineados los ":" y los tipos de cada
declaración.
SETEdit: pmacro "ma" (Entity/Architecture)
pmacro "en" (Entity)
pmacro "ar" (Architecture)
"Intelligent indent": entity, begin, generic y port indentan 3
espacios
"El tab indenta buscando huecos": ayuda a mantener el indentado de
los : y los tipos.
Process:
--------
Todos los process deben tener un label y el process en la misma línea del
mismo.
El label debe ser descriptivo y dar idea de que hace el proceso.
SETEdit: pmacro "ps" (Process)
pmacro "pc" (Process for clock)
pmacro "p1" (Process w/clock+async rst)
pmacro "p2" (Process w/clock+sync rst)
Nota: p<Ctrl>+<Space> lista los pmacros con "p"
End:
----
Todos los end deben ser autodocumentados. Eso implica que el end de la
entidad Prueba es: end entity Prueba
SETEdit: Todos los pmacros que generan cosas con un end lo completan en forma
apropiada.
if/else/elsif:
--------------
Siguen el indentado de 3 caracteres. La ventaja es que se genera una `columna
de corte`:
|------ camino visual
v
if condición then
sentencia;
else
sentencia;
end if;
SETEdit: pmacro "i(" (If plus else)
pmacro "I(" (If, no else)
pmacro "ig" (If generate)
pmacro "if" (If/elsif/else/endif)
"Intelligent indent": if, else y elsif indentan 3 espacios
"El tab indenta buscando huecos": ayuda a mantener el hueco.
while:
------
También mantiene 3 espacios de indentado.
while condición loop
sentencia;
end loop;
SETEdit: pmacro "w(" (While loop)
"Intelligent indent": while indenta 3 espacios
for:
----
Para mantener el hueco visual se propone un indentado extra de 4 caracteres:
|------ camino visual
v
for i in 0 to 7 loop
sentencia;
end loop;
SETEdit: pmacro "f(" (For loop)
pmacro "fg" (For generate)
"Intelligent indent": for indenta 4 espacios
"El tab indenta buscando huecos": ayuda a mantener el hueco.
case/when:
----------
Para mantener el hueco visual se propone un indentado extra de 5 caracteres:
|------ camino visual
v
case sig is
when '0' =>
sentencia;
when others =>
sentencia;
end case;
Lo mismo aplica al when.
SETEdit: pmacro "s(" (Case) Nota: por ser el equivalente al switch de C/C++
pmacro "c:" (Case element (when)) Nota: por ser el equivalente al
case de C/C++
"Intelligent indent": case y when indentan 5 espacios
"El tab indenta buscando huecos": ayuda a mantener el hueco.
with/select:
------------
Para mantener el hueco visual se propone un indentado extra de 5 caracteres:
|------ camino visual
v
with a & b select destino <=
'0' when "00",
'1' when "11",
'Z' when others;
Esta construcción es compleja y se propone el indentado de arriba aunque
también podríamos adoptar:
with a & b select
destino <= '0' when "00",
'1' when "11",
'Z' when others;
El problema en este caso es que mantener el indentado es más complejo si el
nombre "destino" cambia.
SETEdit: pmacro "se" (Select signal (With))
"Intelligent indent": with indenta 5 espacios
"El tab indenta buscando huecos": ayuda a mantener el hueco.
Sentencias con paréntesis anidados que ocupan más de una línea:
---------------------------------------------------------------
Mantienen indentada la condición hasta que los paréntesis se cierran:
if (a>b and
c<d and
q>0) then
sentencia;
end if;
Se busca alinear todas las condiciones.
SETEdit: "Intelligent indent": mantiene el indentado.
Instanciación de componentes:
-----------------------------
El label y el nombre del componente van en la misma línea. El generic y el
port indentan usando 3 espacios:
Decenas: L7490
generic map(
a => q, ....)
port map(
a => g, ....);
SETEdit: pmacro "ci" (Component instantiation)
"Intelligent indent": generic y port indentan 3 espacios
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
<*** Este header es compatible con OpenCores
Se puede lograr con el pmacro "\h"
------------------------------------------------------------------------------
---- ----
---- WISHBONE Handler ----
---- ----
---- Internal file, can't be downloaded. ----
---- ----
---- Description: ----
---- That's a module used to easily write testbenches that uses ----
---- Wishbone modules. ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author: ----
---- - Salvador E. Tropea, salvador@inti.gov.ar ----
---- ----
------------------------------------------------------------------------------
---- ----
---- Copyright (c) 2005 Salvador E. Tropea <salvador@inti.gov.ar> ----
---- ----
---- For internal use, all rights reserved. ----
---- ----
------------------------------------------------------------------------------
<*** Esta sección agrega datos interesantes pedidos por la ESA y otros que
a mi me gusta poner.
---- ----
---- Design unit: WBHandler(simulator) (Entity and architecture) ----
---- File name: Guidelines.vhdl ----
---- Note: None ----
---- Limitations: None known ----
---- Errors: None known ----
---- Library: WBHandler_Lib ----
---- Dependencies: IEEE.std_logic_1164 ----
---- IEEE.numeric_std ----
---- Target FPGA: Spartan II (XC2S100-5-PQ208) ----
---- Language: VHDL ----
---- Wishbone: MASTER (rev B.3) ----
---- Synthesis tools: Xilinx Release 6.2.03i - xst G.31a ----
---- Simulation tools: GHDL [Sokcho edition] (0.1x) ----
---- Text editor: SETEdit 0.5.x ----
---- ----
------------------------------------------------------------------------------
--
-- CVS Revision History
--
-- $Log$
--
<*** Personalmente prefiero Library, pero casi nadie usa esto y los guidelines
de la ESA lo prohiben. Se obtiene con el pmacro "li"
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
<*** La ESA recomienda identificadores con case mezclado.
Pero OpenCores recomienda single case para signals.
Solución: entities, architectures, etc. mezclado.
signals, variables, types, etc. lower.
Esto se obtiene con "ma"
entity WBHandler is
<*** Este indentado es molesto pero simple: 3 caracteres por defecto
El editor lo hace con "Intelligent indent"
generic(
addr_w : integer:=8;
data_w : integer:=8);
port(
-- Simple port
<*** Cada signal en una línea, _i/_o/_io
addr_i : in std_logic_vector(addr_w-1 downto 0);
data_i : in std_logic_vector(data_w-1 downto 0);
data_o : out std_logic_vector(data_w-1 downto 0):=(others => '0');
rd_i,
wr_i : in std_logic;
rde_o,
wre_o : out std_logic:='0';
-- Wishbone side
<*** La de WB con wb_*_i/wb_o_i
wb_rst_i : in std_logic;
wb_clk_i : in std_logic;
wb_adr_o : out std_logic_vector(addr_w-1 downto 0):=(others => '0');
wb_dat_i : in std_logic_vector(data_w-1 downto 0);
wb_dat_o : out std_logic_vector(data_w-1 downto 0):=(others => '0');
wb_we_o : out std_logic:='0';
wb_stb_o : out std_logic:='0';
wb_cyc_o : out std_logic:='0';
awb_ck_i : in std_logic);
end entity WBHandler;
architecture Simulator of WBHandler is
begin
<*** Todos los process con label y el process en la misma línea
Es el "ps"
write_p: process
begin
wait until rd'event or wr'event or clk_i'event;
<*** Indentar buscando el hueco, esto se hace fácil con la opción 'El tab
indenta buscando huecos' de SETEdit y con 'Intelligent indent'
if/else es "i("
if wb_rst_i='1' then
wb_adr_o <= (others => '0');
wb_dat_o <= (others => 'Z');
wb_we_o <= '0';
wb_stb_o <= '0';
wb_cyc_o <= '0';
data_o <= (others => 'Z');
rde_o <= '0';
wre_o <= '0';
else
<*** El editor mantiene el indentado acá
if wr'event and wr='1' then
-- Write
wb_adr_o <= addr;
wb_dat_o <= idata;
wb_cyc_o <= '1';
wb_stb_o <= '1';
wb_we_o <= '1';
-- Wait for clock
<*** Las funciones de la IEEE tienen _ por lo que parece que fueron
pensadas para usarse en un solo "case", lamentablemente no es
coherente el uso, pero en el package la escribieron así:
wait until rising_edge(wb_clk_i);
wait for 1 ns;
-- Wait for ack
if wb_ack_i='0' then
wait until wb_ack_i='1';
end if;
wait for 1 ns;
-- End of write
wb_adr_o <= (others => '0');
wb_dat_o <= (others => 'Z');
wb_cyc_o <= '0';
wb_stb_o <= '0';
wb_we_o <= '0';
-- Tell it to our client
wre_o <= '1';
else
wre_o <= '0';
end if;
if rd'event and rd='1' then
-- Read
wb_adr_o <= addr;
wb_cyc_o <= '1';
wb_stb_o <= '1';
-- Wait for clock
wait until rising_edge(wb_clk_i);
wait for 1 ns;
-- Wait for ack
if wb_ack_i='0' then
wait until wb_ack_i='1';
end if;
wait for 1 ns;
-- End of read
wb_adr_o <= (others => '0');
data_o <= dat_i;
wb_cyc_o <= '0';
wb_stb_o <= '0';
wb_we_o <= '0';
-- Tell it to our client
rde_o <= '1';
else
rde_o <= '0';
end if;
end if;
<*** Autodocumentar usando así:
end process write_p;
end architecture Simulator;