Este artículo se enfoca en usar Verilog para describir circuitos secuenciales síncronos.
En un artículo anterior, discutimos la descripción de los circuitos combinacionales utilizando elementos del lenguaje Verilog. Este artículo se enfoca en describir circuitos secuenciales síncronos. Primero veremos un modelo general para circuitos síncronos y luego discutiremos la descripción de Verilog de un contador bidireccional como ejemplo.
En un circuito combinacional, la salida depende solo del valor presente de las entradas. Sin embargo, la salida de un circuito secuencial depende no solo del valor actual de las entradas sino también del estado del circuito. El estado del circuito está determinado por los valores anteriores de las entradas.
Por lo tanto, un circuito secuencial tiene memoria y su salida depende de la secuencia de las entradas pasadas. Estos circuitos utilizan elementos de memoria, como flip-flops (FF), para almacenar el estado actual del sistema.
Cuando se trata de un circuito secuencial grande, el problema de diseño se vuelve mucho más accesible si utilizamos la metodología síncrona en lugar del enfoque asíncrono. En un circuito síncrono, todos los elementos de almacenamiento son activados por la misma señal de reloj. Esto nos da un mejor control sobre el sistema porque, en este caso, sabemos cuándo los elementos de almacenamiento van a muestrear los datos.
Dado que todos los elementos de almacenamiento de un sistema síncrono están conectados al mismo reloj, podemos modelar el sistema como se muestra en la Figura 1.
En este modelo, el cuadro discontinuo representa todos los elementos de almacenamiento del sistema (FF de tipo D en este ejemplo). Los bloques fuera de la caja discontinua son circuitos combinacionales.
La "lógica de estado siguiente" procesa las "Entradas" y el estado actual del sistema, representado por "state_reg", para determinar el estado siguiente del sistema ("state_next"). Con el próximo flanco ascendente del reloj, "state_next" se almacenará en las FF. El bloque "Lógica de salida" es nuevamente un circuito combinacional que procesa las "Entradas" y "state_reg" para determinar las salidas del sistema.
La separación de un sistema síncrono a elementos de almacenamiento y algunos circuitos combinacionales como se muestra en la Figura 1 nos ayuda a encontrar más fácilmente la descripción HDL del sistema. Solo necesitamos describir algunos circuitos combinacionales y conectarlos a los elementos de memoria. Mientras que la descripción HDL de los circuitos combinacionales se discutió en un artículo anterior, para los elementos de memoria usualmente usamos algunas plantillas HDL conocidas.
Veremos el código Verilog de un contador universal para aclarar estos conceptos, pero antes de eso, debemos analizar la descripción HDL de un flip-flop tipo D, también conocido como DFF.
(Para obtener más información sobre los dispositivos de memoria de bit único biestable de flip-flop, consulte nuestro artículo sobre la conversión de flip-flops D en flip-flops SR, JK y T.)
En general, un DFF se puede implementar utilizando las puertas lógicas básicas. Sin embargo, esto no se recomienda en absoluto cuando se usa un HDL para implementar un DFF en un FPGA. El método seguro y eficiente es describir que un FF está usando algunas plantillas HDL conocidas como se explica en la siguiente sección. De hecho, la herramienta de síntesis reconoce plantillas como FFs y utiliza algunas estructuras optimizadas para implementarlas.
La Figura 2 a continuación muestra el símbolo de DFF de borde positivo (Figura 2-a) y de borde negativo (Figura 2-b). En el borde del reloj, la entrada (D) de un DFF se muestrea y pasa a la salida (Q). Para un DFF de borde positivo, el borde de muestreo es el borde ascendente del reloj (Figura 2-a), mientras que un DFF de borde negativo es sensible al borde descendente del reloj. Un FF generalmente tiene un reinicio (rst) que puede usarse para inicializar el sistema a un estado conocido.
El código de Verilog para un DFF de borde positivo se muestra a continuación:
1 módulo D_FF
2 (
3 hilos de entrada clk, reset,
4 cables de entrada d,
5 salidas reg q
6);
7 siempre @ (mensaje de posición, reinicio de posición)
8 si (restablecer)
9 q
La línea 7 de este código utiliza la palabra clave "posedge" antes de las entradas "clk" y "reset" en la lista de sensibilidad del bloque "siempre". "Posedge", que significa borde positivo, le dice a la herramienta de síntesis que el bloque "siempre" debe activarse en el borde ascendente de las señales "clk" y "reset".
Tenga en cuenta que el borde ascendente de "clk" y "reset" están en la lista de sensibilidad. Por lo tanto, un flanco ascendente de "reinicio" activará el bloque "siempre" independientemente de la condición de señal "clk". En otras palabras, el "reinicio" de este DFF es asíncrono.
Las líneas 8 a 11 usan la declaración "if" de Verilog que se trató en nuestro artículo anterior. Cuando se activa el bloque "siempre", se comprueba el "reinicio". Si la lógica es alta, la salida DFF se restablece (q <= 1’b0). Si "reset" no tiene una lógica alta, entonces es la señal "clk" que ha experimentado un flanco ascendente y la salida DFF debe obtener el valor de entrada (q <= d).
Tenga en cuenta que utilizamos la asignación no bloqueante (<=) al inferir flip-flops. Como se explicó en otro artículo, el uso incorrecto de las asignaciones de bloqueo (=) y no bloqueante (<=) puede llevar a una funcionalidad no deseada. Sin embargo, para el propósito de este artículo introductorio, podemos simplemente separar la parte combinatoria del sistema de sus elementos de memoria y seguir estas dos pautas:
Ahora, veamos el código Verilog de un contador bidireccional para aclarar aún más nuestra discusión.
Escribiremos el código para un contador bidireccional que puede ejecutar cuatro funciones como se indica en la siguiente tabla:
Cuando se afirma la entrada de "carga", los datos de entrada (d) se cargan en el contador (q = d). Cuando tanto "carga" como "en" tienen una lógica baja, el contador mantiene su valor actual. Para "carga" = 0 y "en" = 1, el contador puede contar hacia arriba o hacia abajo según el valor de la entrada "up_downb".
El código de Verilog para un contador bidireccional de ocho bits se proporciona a continuación:
1 módulo bidirect_cnt8
2 (
3 hilos de entrada clk, reset,
4 cables de entrada en, carga, up_downb,
5 cables de entrada [7:0] re,
6 salidas reg [7:0] q
7);
8 reg [7:0] q_next;
9 // Los elementos de almacenamiento
10 siempre @ (mensaje de posición, reinicio de posición)
11 si (restablecer)
12 q
Las líneas 10 a 14 usan el código de plantilla descrito en la sección anterior para agregar ocho DFF al diseño. Estos son DFF de borde positivo y tienen un reinicio asíncrono.
Cuando "reset" tiene un valor lógico alto, el valor 8’h00 se asigna a "q". El término 8’h00 denota un número de ocho bits en la base hexadecimal (8’h). El valor de este número viene dado por los dos dígitos hexadecimales después de la letra "h". Por lo tanto, cuando "reset" tiene un nivel lógico alto, los ocho bits de "q" están configurados en un nivel lógico bajo.
Cuando "reset" tiene una lógica baja, "q_next" se asigna a "q". "Q_next" representa la salida de la "lógica de siguiente estado" en el modelo general de la Figura 1 y determina el valor que debe asignarse a "q" en el próximo flanco ascendente del reloj.
Excepto por las líneas 10 a 14 que describen los elementos de almacenamiento del contador, las otras líneas del código describen los circuitos combinacionales. No es obligatorio separar los elementos de almacenamiento de los circuitos combinacionales, pero puede ayudarnos a describir más fácilmente el sistema. Solo necesitamos determinar el valor apropiado de "q_next" para el próximo borde del reloj. Las líneas 16 a 24 implementan la lógica combinacional para esta parte del diseño, es decir, el bloque de "Lógica de estado siguiente" del modelo en la Figura 1. Utiliza una declaración "if" anidada para describir las diferentes funciones de la Tabla 1:
Cuando la entrada de "carga" tiene una lógica alta, los datos de entrada (d) se asignan a "q_next". Cuando "carga" tiene una lógica baja y el contador no está habilitado ("en" = 0), el contador debe mantener su valor actual ("q_next" debe ser igual a "q"). Para "carga" = 0 y "en" = 1, el contador puede contar hacia arriba o hacia abajo según el valor de la entrada "up_downb".
La figura 3 muestra una simulación ISE del código.
Como se mencionó anteriormente, no siempre tenemos que separar un sistema síncrono en elementos de almacenamiento y circuitos combinacionales, como se muestra en la Figura 1. Sin embargo, creo que esta práctica de diseño nos ayuda a tener un enfoque más sistemático al diseñar un sistema digital. De esta manera, podemos visualizar más fácilmente un diagrama de bloques para el diseño y encontrar su descripción HDL.
En este artículo, discutimos primero un modelo general para circuitos síncronos donde el sistema se divide en dos partes: elementos de almacenamiento y circuitos combinacionales. Luego, usamos este modelo para encontrar la descripción de Verilog de un contador bidireccional. Esta no es la única manera de describir un sistema síncrono; Sin embargo, la metodología discutida puede simplificar el proceso de diseño.
Para ver una lista completa de mis artículos, visite esta página.
ga('create', 'UA-1454132-1', 'auto'); ga('require', 'GTM-MMWSMVL'); ga('require', 'displayfeatures'); ga('set',{'dimension1':'eda,computing,memory,digital-ics,engineering-consulting'}); ga('set',{'contentGroup1':'eda,computing,memory,digital-ics,engineering-consulting'}); ga('send', 'pageview');
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1808435332737507'); // Insert your pixel ID here. fbq('track', 'PageView'); fbq('track', 'ViewContent', { content_ids: ['eda','computing','memory','digital-ics','engineering-consulting'], content_type: 'category'});
_linkedin_data_partner_id = "353081"; (function(){var s = document.getElementsByTagName("script")[0]; var b = document.createElement("script"); b.type = "text/javascript";b.async = true; b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js"; s.parentNode.insertBefore(b, s);})(); } if(jstz.determine().name().indexOf("Europe") === -1) { showSocialCode(); // NOT EU } else { showSocialCode(); window.addEventListener("load", function () { window.cookieconsent.initialise({ "palette": { "popup": { "background": "#252e39" }, "button": { "background": "#14a7d0" } }, "type": "opt-out", "content": { "message": "This website uses tracking cookies to ensure you get the best experience on our website.", "href": "https://www.allaboutcircuits.com/privacy-policy/", "dismiss": "OK, GOT IT" }, onInitialise: function (status) { var type = this.options.type; var didConsent = this.hasConsented(); if (type == 'opt-out' && didConsent) { console.log("eu"); //showSocialCode(); } },
onStatusChange: function (status, chosenBefore) { var type = this.options.type; var didConsent = this.hasConsented(); if (type == 'opt-out' && didConsent) { console.log("eu"); //showSocialCode(); } },
onRevokeChoice: function () { var type = this.options.type; if (type == 'opt-out') { console.log("eu"); //showSocialCode(); } },
}) }); }
Los días felices de la PDA y Blackberry han quedado definitivamente atrás, pero el factor…
Tutorial sobre cómo pronosticar usando un modelo autorregresivo en PythonFoto de Aron Visuals en UnsplashForecasting…
Si tienes un iPhone, los AirPods Pro son la opción obvia para escuchar música, ¡aunque…
Ilustración de Alex Castro / The Verge Plus nuevos rumores sobre el quinto Galaxy Fold.…
Se rumorea que los auriculares premium de próxima generación de Apple, los AirPods Max 2,…
El desarrollador Motive Studio y el editor EA han lanzado un nuevo tráiler de la…