-
Notifications
You must be signed in to change notification settings - Fork 201
Capítulo 13: Inicializando registros
Ejemplos de este capítulo en github
Ya podemos responder a la pregunta planteada en el capítulo 8 sobre cómo realizar la inicialización de los registros. Los registros sintetizados están a 0. Normalmente necesitamos cargar en ellos un valor inicial, y que luego funcionen para lo que hayan sido diseñados. En este capítulo mostraremos cómo hacerlo, usando las herramientas que ya conocemos: el multiplexor y el inicializador
Partimos de un registro genérico de N bits, que ya conocemos, con una entrada din, una salida dout y una señal de reloj
Queremos que se cargue con un valor inicial al principio y que luego funcione normalmente. Para hacerlo colocamos un multiplexor de 2 a 1 en su entrada (para dividir la entrada en 2). Por una entrada del multiplexor ponemos el valor inicial y por la otra la entrada genérica del registro din2.
Es muy importante que el valor inicial se introduzca por la fuente 0 del multiplexor.
Ahora ya simplemente conectamos un inicializador a la entrada de selección del multiplexor.
De esta forma, al arrancar, el inicializador emitirá un 0 y por la entrada din del registro llegará el valor inicial. En el siguiente franco de subida este valor inicial se captura y el inicializador pasa a 1, por lo que ahora se seleccionará la fuente 1, que será por donde vengan los datos del registro en el régimen normal de funcionamiento
Vamos a reacer el circuito blink4 del capítulo 8. Este circuito hacía parpadear los 4 leds a la vez, produciendo la secuencia: 0000, 1111, 0000 ...
Ahora lo vamos a mejorar haciendo que se pueda poner cualquier valor inicial en el registro, lográndose la secuencia INI, ~INI, INI ... (valor inicial y su negado alternativamente):
La descripción de este circuito en Verilog es:
//-- reginit.v module reginit(input wire clk, output wire [3:0] data);
//-- Parametros del secuenciador: parameter NP = 23; //-- Bits del prescaler parameter INI = 4'b1100; //-- Valor inicial a cargar en registro
//-- Reloj a la salida del presacaler wire clk_pres;
//-- Salida del regitro reg [3:0] dout;
//-- Entrada del registro wire [3:0] din;
//-- Señal de seleccion del multiplexor reg sel = 0;
//-- Registro always @(posedge(clk_pres)) dout <= din;
//-- Conectar el registro con la salida assign data = dout;
//-- Multiplexor de inicializacion assign din = (sel == 0) ? INI : ~dout;
//-- Inicializador always @(posedge(clk_pres)) sel <= 1;
//-- Prescaler prescaler #(.N(NP)) PRES ( .clk_in(clk), .clk_out(clk_pres) );
endmodule
El multiplexor de 2 a 1 ha implementado usando el operador ? : (similar al del lenguaje C). Es un if-else abreviado:
assign din = (sel == 0) ? INI : ~dout;
Es equivalente a:
always @* if (sel == 0) din <= INI; else din <= ~dout;
pero la primera notación es más compacta
0 You are leaving the privative sector (EN)
1 ¡Hola mundo! (EN) (RU)
2 De un bit a datos (EN)
3 Puerta NOT (EN)
4 Contador de 26 bits (EN)
5 Prescaler de N bits (EN)
6 Múltiples prescalers (EN)
7 Contador de 4 bits con prescaler (EN)
8 Registro de 4 bits (EN)
9 Inicializador (EN)
10 Registro de desplazamiento (EN)
11 Multiplexor de 2 a 1 (EN)
12 Multiplexor de M a 1 (EN)
13 Inicializando registros (EN)
14 Registro de N bits con reset síncrono
15 Divisor de frecuencias
16 Contador de segundos
17 Generando tonos audibles
18 Tocando notas
19 Secuenciando notas
20 Comunicaciones serie asíncronas
21 Baudios y transmisión
22 Reglas de diseño síncrono
23 Controladores y autómatas finitos
24 Unidad de transmisión serie asíncrona
25 Unidad de recepción serie asíncrona
26 Memoria ROM
27 Memoria ROM genérica
28 Memoria RAM
29 Puertas triestado
30 Hacia el microprocesador y más allá