sábado, 31 de julio de 2010

Codificación de Máquinas de Estado (FSM) con Synplify y XST

FSM codificación con Synplify:
Cuando se desea una asignación de código de estados específica para la FSM, Synplify permite realizar la asignación usando la siguiente sintaxis:


1 type fsm_type is (idle, setup, txing, stop);
2 attribute syn_enum_encoding: string;
3 attribute syn_enum_encoding of fsm_type: type is "111 101 001 011";


Cuando se desee asignar una codificación tal como Gray, OneHot, Sequential or Binary, se debe usar la siguiente sintaxis:

1 type fsm_type is (idle, setup, txing, stop);
2 attribute syn_encoding: string;
3 signal curr_state, nxt_state: fsm_type;
4 attribute syn_encoding of curr_state: signal is "onehot";

Importante: para que efectivamente Synplify realice las asignaciones específicadas por el atributo syn_encoding o syn_enum_encoding, la opción FSM Compiler en la pantalla principal de Synplify debe estar sin marcar (not checked).
En caso de usar Tcl script, use el siguiente comando para no hacer uso del FSM Compiler::

set_options -symbolic_fsm_compiler 0


Implementacion Segura (Safe Implementation):
Por defecto Synplify generará FSM optimizadas por velocidad y área; sin embargo hay casos en los la prioridad de la FSM es que funcione correctamente ante cualquier circunstancia. En el modo Safe Implementation, Synplify agregará lógica de modo que si la FSM alguna vez cae en un estado invalido (estado no asignado), sera forzada al estado de reset; evitando así que la FSM se 'cuelgue' dejando de funcionar correctamente. Para habilitar esta característica se usa el mismo atributo syn_encoding pero agregándole la opción safe. Sintaxis: 

1 attribute syn_encoding of curr_state: signal is "safe,onehot";

FSM codificación con Xilinx XST:
Se puede usar la siguiente sintaxis para una asignación de código de estados específica:

1 type fsm_type is (idle, setup, txing, stop);
2 attribute enum_encoding: string;
3 attribute enum_encoding of fsm_type: type is "111 101 001 011";


Sin embargo  XST no tendrá en cuenta lo especificado en el atributo a menos que se active el modo FSM en modo 'user' (usuario). El modo FSM 'user' se puede seleccionar de dos modos, usando attribute o mediante Project Manager.
Usando attribute:

4 attribute fsm_encoding: string;
5 signal curr_state, nxt_state: fsm_type;
6 attribute fsm_encoding of curr_state: signal is "user";

GUI:
- Click el botón derecho del mouse sobre la opción Synthesize-XST
- Seleccione Properties
- Seleccione HDL Options
- Seleccione FSM Encoding Algorithm como User


El atributo fsm_encoding también se usa en el caso que se desee una asignación de estados con alguno de los siguientes valores:
- Auto
- OneHot
- Compact
- Sequential
- Gray
- Johnson
- Speed1
Para especificar una codificacion use la siguiente sintaxis:

1 type fsm_type is (idle, setup, txing, stop);
2 attribute fsm_encoding: string;
3 signal curr_state, nxt_state: fsm_type;
4 attribute fsm_encoding of curr_state: signal is "one-hot";

En caso de no especificar ninguna codificacion en particular Auto sera usado por XST por defecto.
Implementacion Segura (Safe Implementation):
En el modo Safe Implementation, XST genera lógica adicional que fuerza la FSM a un estado válido en caso que la FSM entre en un estado inválido. Sintaxis:
 1 type fsm_type is (idle, setup, txing, stop);
2 attribute safe_implementation: string;
3 signal curr_state, nxt_state: fsm_type;
4 attribute safe_implementacion of curr_state: signal is "yes";

viernes, 16 de julio de 2010

ieee.numeric_std.all vs. ieee.std_logic_arith.all;


Los siguientes paquetes
ieee.numeric_std.all / ieee.std_logic_arith.all / ieee.unsigned.all/ ieee.signed.all;
 nunca deberían usarse juntos.
ieee.numeric_std.all se refiere a un paquete de la librería estandard de la IEEE; la que debería ser usada para todos los diseños nuevos.
ieee.std_logic_arith.all,ieee.std_logic_unsigned.all, ieee.std_logic_signed.all se refieren a un paquete definido por Synposys algunos años atrás, y que por ser una de las herramientas de síntesis más usadas, estos paquetes eran usados casi por defecto.

Hasta el día de hoy Xilinx ISE usa los siguientes paquetes,  por defecto, cuando se usa la opción de crear un nuevo módulo VHDL:

 use ieee.std_logic_arith.all;
 use ieee.std_logic_unsigned.all;


A fin de que el código VHDL ha escribir sea 100% IEEE estandard, estos dos paquetes deben ser reemplazados por:

 use ieee.numeric_std.all;

Sin embargo, vale la pena aclarar lo siguiente: el paquete std_logic_arith es normalmente usado porque tiene definido operaciones matemáticas, como suma y resta, para el tipo std_logic, el std_logic_vector y el tipo integer. El paquete numeric_std  NO tiene definidas operaciones matemáticas para std_logic, std_logic_vector, pero sí las tiene definidas para los tipos signed,  unsigned e integer. Por ello para los casos en que sean necesarias operaciones matemáticas entre señales o variables, estas se deberán declarar como tipo signed, unsigned  o integer, y usar 'casting' o funciones de conversión para pasar de unsigned/signed/integer a std_logic_vector.
El ejemplo más típico es el de un contador descrito en VHDL. La forma correcta de describirlo sería la siguiente:

 1 library ieee;
 2 use ieee.std_logic_1164.all;
 3 use ieee.numeric_std.all;
 4
 5 -- entity declaration
 6 entity counter_load is
 7    port (
 8         -- clock, reset ports
 9         clock     : in std_logic;
10         reset     : in std_logic;
11         -- control ports
12         load      : in std_logic;
13         -- input ports
14         initial_value   : in std_logic_vector(3 downto 0);
15         -- output ports
16         count   : out std_logic_vector(3 downto 0)
17  ) ;
18 end counter_load;
19
20 -- architecture declaration
21 architecture counter_load_beh of counter_load is
22  signal count_i: unsigned(3 downto 0);
23
24 -- architecture body
25 begin
26    count_proc: process(clock, reset)
27   begin
28     if(reset='0') then
29       count_i <= (others => '0');
30     elsif(rising_edge(clock)) then
31       if (load = '1') then
32         count_i <= unsigned(initial_value);
33       else
34         count_i <= count_i + 1;
35       end if;
36     end if;
37   end process count_proc;
38
39   count <= std_logic_vector(count_i);
40
41 end architecture counter_load_beh; 

En este ejemplo se puede ver el use de 'cast'. En linea 32 se usa el cast unsigned para asignar el standard_logic_vector initial_value al unsigned count_i. Mientras que en linea 39 se usa el cast std_logic_vector para asignar el unsigned count_i al standard_logic_vector count.

Otro ejemplo similar es el siguiente:

 1 library ieee;
 2 use ieee.std_logic_1164.all;
 3 use ieee.numeric_std.all;
 4
 5 -- entity declaration
 6 entity counter_ud is
 7    port (
 8         --  clocks, reset ports  
 9         clock     : in std_logic;
10         reset     : in std_logic;
11         --  control ports  
12         load   : in std_logic;
13         --  inputs ports  
14         initial_value: std_logic_vector(3 downto 0);
15         --  output ports
16         count   : out std_logic_vector(3 downto 0)
17         );
18 end counter_ud;
19
20 -- architecture declaration
21 architecture counter_ud_beh of counter_ud is
22   signal count_i: integer range 0 to 15;
23
24 -- architecture body
25 begin
26   count_proc: process(clock, reset)
27   begin
28     if(reset='0') then
29       count_i <= 0;
30     elsif(rising_edge(clock)) then
31       if(load = '1') then
32         count_i <= to_integer(unsigned(initial_value));
33       else
34         count_i <= count_i + 1;
35       end if;
36     end if;
37   count <= std_logic_vector(to_unsigned(count_i,4));
38   end process count_proc;
39
40 end architecture counter_ud_beh;

En este caso en línea 32 ocurre algo interesante: primero se usa el cast unsigned para convertir a unsigned el std_logic_vector initial_value. Luego se usa la función to_integer para convetir el unsigned a integer y asignárselo a count_i, que lógicamente es de tipo integer. En línea 37 ocurre algo similar, pero no igual :) : se usa la función to_unsigned para convertir el entero count_i que se puede representar con 4 bits (count_i es declarado de 0 a 15), y luego se usa el cast std_logic_vector para pasar de unsigned a std_logic_vector y así poder asignar el vector a count que es un std_logic_vector.

Dentro de poco pondré un cuadro que resume los cast y functions de conversiones ......
Espero que te sea de utilidad....
Nuevo!! : baja el pdf haciendo click aca  -> :) 

jueves, 15 de julio de 2010

Xilinx XST y la inserción de BUFG/BUFGMX para controlar latches

Como bien es enseñado y todos los diseñadores lo dicen, latches no deberían ser usados en diseños sincrónicos; sin embargo hay casos en que realmente son necesarios y no queda otra que usarlos.

La herramienta de síntesis del ISE, XST, inserta automáticamente un BUFG o BUFGMX entre el pad de entrada del FPGA de la señal de control/habilitación del latch y la entrada de habilitación del latch. De este modo XST usa el ruteo de específico para reloj (clock routing) para controlar la habilitación (gate) del Latch. Esta inserción automática se puede verificar ya sea leyendo el reporte del Place and Route, o usando la herramienta FPGA Editor.
Para la comprobación de lo antes dicho se sintetizó el código que está el pie de esta entrada (sin el uso del atributo), y claramente se puede ver en la siguiente figura, que es una captura parcial del FPGA Editor, el ruteo de la señal de control del latch usando el ruteo dedicado del reloj.




Para evitar el mal uso de este importante y escaso recurso, se le debe indicar al XST que no use un BUFG o BUFGMX para controlar el latch, sino que use un simple IBUF, es decir, el buffer de entrada que se usa para cualquier otra senal que no sea de reloj. XST provee al diseñador ciertos atributos para casos como este (y muchos otros) detallados en la guía "XST User Guide".
Para éste caso se hace uso del atributo BUFFER_TYPE, asignándole el valor ‘ibuf’. Nota: BUFFER_TYPE es un atributo que reemplaza al attribute CLOCK_BUFFER usado en versiones anteriores al ISE 12. Xilinx aconseja el uso de BUFFER_TYPE para nuevos diseños.
La sintáxis del atributo es la siguiente:

  attribute buffer_type: string;
  attribute buffer_type of: signal is"{bufgdll|ibufg|bufgp|ibuf|bufr|none}";

La siguiente figura confirma el resultado esperado cuando se utiliza el atributo BUFFER_TYPE con la senal 'control' asignándole el valor 'ibuf'::



El código VHDL usado para la realización de las pruebas es el siguiente:

 1 library ieee;
 2 use ieee.std_logic_1164.all;
 3
 4 entity latch_test_no_buffer is
 5   port(
 6     data:           in std_ulogic;
 7     control:        in std_ulogic;
 8     latched_data: out std_ulogic
 9     );
10 end latch_test_no_buffer;
11
12 architecture beh of latch_test_no_buffer is
13   attribute buffer_type: string;
14   attribute buffer_type of control: signal is "ibuf";
15 begin
16  latch_proc: process(data, control)
17   begin  
18     if(control = '1') then
19       latched_data <= data;
20     end if;
21  end process latch_proc;
22 end beh;

martes, 13 de julio de 2010

Mux Genérico: elaborado, pero cortito y muy útil . . .


 1 library ieee;
 2 use ieee.std_logic_1164.all;
 3 use ieee.numeric_std.all;
 4
 5 entity mux_clq is
 6  generic(mux_bits_sel: positive:=4);
 7  port(
 8   mux_inp: in std_logic_vector((2**mux_bits_sel)-1 downto 0);
 9   mux_sel: in std_logic_vector(mux_bits_sel-1 downto 0);
10   mux_out: out std_logic
11   );
12 end mux_clq;
13
14 architecture mux_beh of mux_clq is
15 begin
16   mux_out <= mux_inp(to_integer(unsigned(mux_sel)));    
17 end mux_beh;

jueves, 1 de julio de 2010

Cambiando el valor de un 'generic' en simulación con ModelSim

Como es sabido el valor asignado a un generic en VHLD o a un parameter in Verilog es un valor constante, establecido durante al tiempo de elaboración, y por ende no de puede cambiar durante la simulación del sistema. En caso de querer llevar a cabo simulación con diferentes valores de generics, existen dos opciones cuando se usa ModelSim:
- Uso de configuraciones. Una para cada valor deseado del generic.
- Uso de opciones del comandando vsim. Las opciones -g y -G (ModelSim es sensible a la diferencia entre minúsculas y mayúsculas) permiten asignar los valores deseados a los generics correspondientes.

Opción -g
: asigna valores a los generics que no tienen un valor explícito. Sintáxis:
-g<nombre>=<valor> (observe que no hay espacios)

Ejemplos:
vsim -gwidth=16 . . . . . (asigna el valor 16 al generic width)

Para un generic de una instancia específica se debe usar el path jerárquico correspondiente:
vsim -g/top/counter/u1/max_cnt=53 . . .

Para múltiples generic se deben usar múltiples -g opciones:
vsim -g/top/counter/u1/max_cnt=53 -g/top/counter/u2/max_cnt=7 -gaddr_bus_width=32 . .

Opción -G: es similar a la opción -g pero SOBRESCRIBIRÁ los valores explícitos de los generics/parameters asignados oportunamente ya sea en la entidad/módulo o en la instanciación (generic map).