¿Cuál es la motivación para usar Verilog o VHDL sobre C?

Vengo de un entorno de programación y no me he metido demasiado con el hardware o el firmware (como mucho un poco de electrónica y Arduino).

¿Cuál es la motivación para usar lenguajes de descripción de hardware (HDL) como Verilog y VHDL sobre un lenguaje de programación como C o lenguaje ensamblador?

¿Es esto una cuestión de elección?

Leí que el hardware, que tiene su firmware escrito en un HDL, tiene una clara ventaja al ejecutar instrucciones en paralelo. Sin embargo, me sorprendió ver debates que expresaban dudas sobre si escribir firmware en C o ensamblado (¿cómo es apropiado ensamblar si no necesariamente tiene una CPU?), Pero concluí que también es una opción.

Por lo tanto, tengo algunas preguntas (no dude en explicar cualquier cosa):

  1. ¿Se puede realmente escribir un firmware en HDL o en un lenguaje de programación de software, o es solo otra forma de lograr la misma misión? Me encantaría tener algunos ejemplos del mundo real. ¿Qué restricciones resultan de cada opción?

  2. Sé que un uso común del firmware sobre el software es en los aceleradores de hardware (como GPU, adaptadores de red, aceleradores SSL, etc.). Según tengo entendido, esta aceleración no siempre es necesaria, sino solo recomendable (por ejemplo, en el caso de SSL y aceleración de algoritmos complejos). ¿Se puede elegir entre firmware y software en todos los casos? Si no, me encantaría saber los casos en los que el firmware es clara e inequívocamente apropiado.

  3. He leído que el firmware se graba principalmente en ROM o flash. ¿Cómo se representa allí? En bits, como software? Si es así, ¿cuál es la profunda diferencia? ¿Es la disponibilidad de circuitos adaptados en el caso del firmware?

Supongo que cometí un error aquí y allá en algunas suposiciones, por favor, perdónenme. ¡Gracias!

Los lenguajes de programación son para describir software, los lenguajes de descripción de hardware son para describir hardware.
No escribe firmware con Verilog o VHDL: usa Verilog o VHDL para diseñar chips, programar FPGA y diseñar placas base. Utiliza C o ensamblaje para escribir firmware. También puede usar C/C++ para diseñar placas base: hay una biblioteca llamada SystemC que puede compilarse con un compilador de C para crear un programa que simule su diseño, pero también puede compilarse con un compilador de SystemC en circuitos.
FWIW, dado que tiene experiencia con Arduino, escribir software para un Arduino se llama escribir firmware. El firmware puede ser un sistema operativo completo: Linux, por ejemplo, se usa en el firmware de la mayoría de los enrutadores y Windows se usa en el firmware de la mayoría de los cajeros automáticos.
¿Por qué escribimos libros en inglés y no en C? ¿Por qué escribimos programas en C y no en inglés? ¿Por qué los telégrafos no usaban el inglés en lugar del código morse?
La parte sintetizable (lo que realmente se implementa) de VHDL/Verilog/Systemverilog no es más que una forma abstracta de "dibujar" circuitos lógicos digitales usando lenguaje. ¡Tú NO programas! Dibujas circuitos - con palabras.

Respuestas (7)

¿Cuál es la motivación para usar lenguajes de descripción de hardware (HDL) como Verilog y VHDL sobre lenguajes de programación como C o algún ensamblador?

C y ensamblador son buenos lenguajes para decirle a una CPU qué hacer. Describen acciones que debe realizar secuencialmente una sola máquina de estado.

Los HDL son buenos lenguajes para describir o definir una colección arbitraria de circuitos digitales. Pueden expresar operaciones realizadas en paralelo de formas que los lenguajes de programación no pueden. También pueden describir limitaciones de tiempo para las interfaces entre bloques de formas que los lenguajes de programación no pueden.

Me sorprendió ver discusiones expresando dudas sobre si escribir firmware en C o ensamblado (¿cómo es apropiado ensamblar si no necesariamente tiene una CPU?)

En esa pregunta, lo que se pregunta es: "Si está escribiendo código para un microcontrolador, ¿existe una diferencia real si escribe en ensamblador o C o algún otro lenguaje de alto nivel?".

Dado que está preguntando específicamente acerca de los sistemas con un microcontrolador (una CPU con periféricos), C o ensamblaje son opciones razonables para el desarrollo de firwmare, y los HDL no lo son.

¿Un firmware realmente se puede escribir en HDL o en un lenguaje de programación de software, o es solo otra forma de realizar la misma misión?

Depende del tipo de hardware que tengas. Si tiene una CPU, use un lenguaje de programación. Si tiene un FPGA o está diseñando un ASIC, use un HDL. Si está diseñando una gran cantidad de lógica digital, puede buscar uno de los lenguajes intermedios como SystemVerilog.

He leído que el firmware se quema principalmente en ROM o flash. ¿Cómo se representa allí? En bits, como software? Si es así, ¿cuál es la profunda diferencia? ¿Es la disponibilidad de circuitos adaptados en el caso del firmware?

Creo que te estás obsesionando con el término "firmware". Esta palabra originalmente significaba que el código se ejecutaría en un sistema integrado, que no era accesible para que el usuario final lo cambiara. Si le vende a alguien una PC, existe una gran posibilidad de que el usuario cambie el software que se ejecuta en ella. Si les vendiera un osciloscopio, no querría que cambiaran el código que se ejecuta en el microprocesador interno, por lo que lo llamó firmware.

Los usuarios de FPGA se apropiaron de la palabra "firmware" para la salida de sus diseños, porque es más cambiante que el hardware (cosas que se sueldan entre sí). Pero realmente el "firmware" que configura una FPGA es diferente del "firmware" que corre en una uC. El firmware del uC dirige el uC a través de una serie de estados para realizar su función. El firmware de FPGA define un conjunto de interconexiones entre elementos lógicos y valores que se almacenarán en tablas de búsqueda.

En cualquier caso, el firmware generalmente se almacena como bits en una eeprom (o en un disco en una máquina host que lo descargará cada vez que se reinicie el sistema integrado). Pero eso no los hace similares entre sí.

Cuando escribe en VHDL/Verilog, es mucho más fácil visualizar la lógica que se implementará y, por lo tanto, optimizar. No se puede decir lo mismo de C. Incluso SystemC todavía está lo suficientemente divorciado de la implementación física real como para que se produzcan resultados de síntesis inesperados.
@JonRB, si está codificando para uC o uP, en realidad no conozco ninguna forma de hacerlo con un HDL. Estoy de acuerdo en que cuando se codifica la lógica, SystemVerilog o SystemC son para sistemas que son tan grandes que simplemente no es práctico intentar diseñar todo en el nivel de puerta individual.
Tenga en cuenta que VHDL y Verilog también se usan cuando no tiene ningún hardware. Se pueden compilar directamente en circuitos en lugar de flujo de bits FPGA. Apple, por ejemplo, solía diseñar sus placas base usando Verilog en lugar de la captura esquemática de GUI, ya que hay un mejor soporte para el control de versiones, grepping y simplemente analizar usando scripts cuando su diseño es texto sin formato en lugar de dibujos binarios propietarios.
@slebetman, las placas base suelen ser PCB en las que importa la dimensión de los componentes. No puedo ver cómo un HDL puede capturar estas dimensiones.
Se capturan de la forma normal en que lo hacen sus programas CAD. En el nivel de diseño de la placa o al seleccionar un componente de la biblioteca de componentes. Solo que, en lugar de un cuadro de selección de GUI, la selección de componentes es simplemente escribir el texto correcto. Con un buen IDE, puede obtener ayuda de autocompletado al seleccionar componentes al igual que hacerlo en GUI, solo que inserta texto en lugar de gráficos. Para los diseños de circuitos integrados, de donde se originan estos lenguajes, las dimensiones de la capa n, la capa p y las trazas de metal son incluso más importantes que las dimensiones de los componentes simples en el diseño de PCB o el transistor previsto ni siquiera funcionará.

Para la primera parte de su pregunta, sobre las motivaciones de usar uno u otro: hay una diferencia fundamental entre C y HDL (VHDL/Verilog) . C es un lenguaje de programación de software (como lo es ensamblador), VHDL/Verilog son lenguajes de descripción de hardware . No están destinados al mismo propósito.

C se traduce a código ensamblador (en su forma binaria, es decir, lenguaje de máquina) cuando se compila . Este código es una serie de instrucciones que le indican a la CPU que realice una serie de operaciones básicas (cambiar el valor de un registro, realizar una suma, etc.).

Por otro lado, un HDL se sintetiza en hardware. En VHDL podría, por ejemplo, escribir algo como:

output <= input1 + input2;

(ver también un ejemplo más completo aquí ). Esto se sintetizaría en un sumador (de hardware). Si el código se sintetiza para un FPGA , esto significaría un flujo de bits que puede configurar el FPGA específico para implementar un sumador (como lógica combinacional ).

En realidad, podría diseñar una CPU en VHDL (ver Procesadores de núcleo blando VS Procesadores de núcleo duro ) y escribir el software en C...

Sobre el firmware: en realidad todo depende de cómo definas la palabra. Un firmware puede ser un programa (software) que se ejecuta en un microcontrolador (por ejemplo, escrito en C o ensamblador), o puede ser un flujo de bits para configurar un dispositivo lógico programable (hardware) (CPLD o FPGA). A veces puede ser un paquete que contiene ambos: si toma el firmware de algunos modelos de FritzBox (un módem ADSL), en realidad contienen un sistema Linux completo (escrito en ensamblador, C y muchos otros lenguajes de programación) y un flujo de bits para configurar un FPGA (probablemente sintetizado de VHDL o Verilog).

VHDL y Verilog son más adecuados para describir la concurrencia de hardware

Los electrones pueden fluir al mismo tiempo en cables paralelos, por lo que queremos tener eso en cuenta al diseñar el hardware.

En VHDL, si escribe algo como:

x <= a or b;
y <= a and b;
z <= x xor y;

(fuera de a processo function, que lo marca explícitamente como secuencial), entonces ha codificado el hecho de que:

  • x, y, zy son acablesb
  • ay bson señales de entrada
  • xestá conectado a la salida de un orcircuito, que toma ay bcomo entrada
  • y así sucesivamente para las otras líneas

Es fácil ver cómo se sintetizará en hardware real xy yse evaluará al mismo tiempo.

        +-----+
A--+----+     |  X
   |    | OR  +-----+
B----+--+     |     |  +-----+
   | |  +-----+     +--+     |
   | |                 | XOR +-- Z
   | |  +-----+     +--+     |
   | +--+     |  Y  |  +-----+
   |    | AND +-----+
   +----+     |
        +-----+

Luego, cuando llega el momento de simular el circuito, el simulador (que suele ser un programa secuencial) simula la física del circuito de la siguiente manera:

  • ha ao ha bcambiado? ¿Sí? Hola, xdepende de a. Actualicemos x_
  • ytambién depende de a. Actualiza eso también.
  • zdepende xde Actualízalo porque xse actualizó.
  • ¿Se ha actualizado algo que xdependa de ( ao )? b¿No? Lo mismo para yy z. OK, hemos terminado con este paso.

Esto conduce a posibles resultados "interesantes" que no tienen un análogo secuencial, pero que representan posibles situaciones físicas:

  • x <= not xconduciría a una recursión infinita de la simulación. Los simuladores pueden simplemente cortarse después de cierta profundidad.
  • x <= 0; x <= 1conduce a un error (cortocircuito). Esta es una de las razones por las que std_logicexiste.

Aún así, a pesar de que VHDL modela el hardware más de cerca que C, no es en sí mismo una descripción perfectamente detallada del mismo:

Al final, VHDL proporciona un buen equilibrio entre la funcionalidad del circuito comprensible por humanos de nivel superior y la capacidad de síntesis de nivel inferior.

C, por otro lado, está más enfocado en hablar con la CPU secuencialmente.

Por supuesto, podría codificar un circuito con estructuras C, enumeraciones y matrices, y luego simularlo como lo hace VHDL (esto se parece más o menos a lo que hace el Sistema C , pero nunca lo he probado).

Pero esencialmente estaría reimplementando un simulador VHDL y con un lenguaje más detallado. La herramienta correcta para el trabajo correcto, supongo.

También hay herramientas que convierten C a VHDL https://stackoverflow.com/questions/8988629/can-you-program-fpgas-in-c-like-languages ​​pero esperan un rendimiento más bajo ya que son conversiones difíciles de nivel superior.

  1. Depende de tu arquitectura. Si tiene una CPU (o, por lo general, un microcontrolador), debe escribir el firmware en un lenguaje de programación normal (incluido el ensamblaje). Si tiene algo como un FPGA, su firmware debe estar escrito en un HDL. Los HDL no pueden (que yo sepa) generar programas que puedan ser ejecutados eficientemente por una CPU convencional, y un FPGA no ejecuta programas convencionales listos para usar. Sin embargo, podría configurar su FPGA como una CPU y luego ejecutar un programa convencional con eso. Esto requeriría dos capas de firmware, la capa inferior escrita en un HDL para construir la CPU y la capa superior escrita en un lenguaje de programación convencional para ejecutarse en esa CPU.
  2. No hay una distinción clara entre firmware y software. En muchos dispositivos, el firmware se almacenaría, por ejemplo, en la memoria flash, pero en un teléfono moderno, casi todo se almacena en la memoria flash, y la distinción entre firmware y software no está clara (la mayoría de la gente probablemente consideraría el código para programar el firmware del procesador de banda base). , y la mayoría de la gente consideraría software de programas de aplicación, pero ¿dónde está el límite exacto?).
  3. Como dije en 2, no hay una distinción clara, aparte de la idea de que el firmware es un poco más permanente.

Los HDL se utilizan para describir (sintetizar) el hardware, mientras que el lenguaje de programación se utiliza para programar el hardware ya sintetizado, es decir, la CPU.

Puede obtener versiones de núcleo suave de cpus como VHDL o flujo de bits para sintetizar esa cpu en un FPGA.

Vale la pena mencionar un poco de historia. En las décadas de 1970 y 1980, los microcontroladores todavía eran algo raros y muchos sistemas digitales se diseñaron con circuitos integrados de lógica digital (74HC, etc.). Para ahorrar espacio y costos, se desarrollaron los lenguajes HDL. Se le ocurriría una función lógica y la piratearía en VHDL, luego grabaría un "PLD" con algún tipo de PROM a bordo. Con esto podrías reemplazar todos los circuitos integrados por uno solo.

Luego, en la década de 1990, los microcontroladores EPROM se volvieron más comunes y mucho más asequibles, lo que hizo que el uso de PLD de lógica digital se volviera cada vez más obsoleto. En la década de 2000, las MCU venían con memorias flash en chip que podían reprogramarse fácilmente (borrarse electrónicamente) y esto puso fin en su mayoría al uso de PLD.

El uso de lenguajes HDL se mantuvo, pero se trasladó a proyectos con FPGA especializados, que se usaban principalmente cuando tenía una producción de gran volumen o requisitos de consumo actuales o en tiempo real muy ajustados, por ejemplo, en dispositivos de telecomunicaciones. Sigue siendo así hoy, usará un FPGA cuando tenga requisitos especializados y no espere que la funcionalidad del producto cambie con el tiempo.

Hoy en día, los microcontroladores son ridículamente baratos y más potentes que nunca, por lo que los argumentos en tiempo real para usar FPGA se están volviendo cada vez más irrelevantes. También los SoC/ASIC que combinan núcleos de CPU programables con lógica digital en el mismo chip también son algo comunes, por lo que puede elegir lo que quiera de ambos mundos.

También en particular, la programación en el lenguaje C de "nivel alto" es mucho más compleja que el ensamblador o VHDL, por lo que requiere mucha más educación y experiencia del programador. Esta es una de las razones por las que muchas empresas se mantuvieron alejadas de C en la década de 1990: simplemente era difícil encontrar programadores de C que supieran lo que estaban haciendo y los compiladores de C eran de calidad muy diversa.

No estoy de acuerdo con el último párrafo: si bien los conceptos del subconjunto sintetizable de HDL son simples, ya que se trata de funciones primitivas, construir algo de complejidad significativa es muy difícil y altamente especializado. La abstracción y todo eso...
@awjlogan Bueno, sí... del mismo modo, es muy difícil hacer programas grandes y complejos en ensamblador. C es simplemente más adecuado cuando necesita introducir capas de abstracción para lidiar con la complejidad y/o la portabilidad. Las clases de C de nivel intermedio generalmente abordan la abstracción, el diseño de programas y la portabilidad en cierta medida.
Sin embargo, el rendimiento solía ser un argumento importante para seguir con ensamblador o VHDL. Y eso se debió principalmente a la mala calidad de los compiladores de C en la década de 1990.
Sí, estuvo de acuerdo con la abstracción y la calidad del compilador (también un factor al escribir HDL, por cierto). Específicamente, no estoy de acuerdo con la afirmación de que se education and experiencerequiere más para escribir en C; anecdóticamente, diría que lleva mucho más tiempo volverse lo suficientemente "habilidad" para hacer cosas útiles en HDL, e incluso más para hacer cosas realmente útiles :)

Un procesador usa una cantidad modesta de circuitos para realizar una gran cantidad de operaciones, secuencialmente, al permitir que la mayoría de los componentes se usen para realizar diferentes operaciones en diferentes momentos.

Un FPGA contiene una serie de circuitos que no pueden, al menos individualmente, realizar operaciones particularmente sofisticadas, pero todos son capaces de actuar de forma simultánea e independiente.

Supongamos que uno quiere tener un chip que realice una serie de tareas, entre las que se encuentra monitorear 15 entradas y:

  • Establecer una salida alta cada vez que todas las entradas han sido estables durante al menos 21 ms y el número de entradas que son altas es un múltiplo de tres
  • Establecer la salida baja cada vez que todas las entradas hayan estado estables durante al menos 21 ms y el número de entradas que son altas no sea un múltiplo de tres
  • Cambiar la salida de manera arbitraria entre el momento en que cambia cualquier entrada y el momento en que todas las entradas se han mantenido estables durante al menos 20 ms.

Si uno tiene un microcontrolador que está haciendo otras cosas, pero puede dedicar algunos microsegundos cada 20 ms para examinar esas entradas y configurar la salida, entonces la mayoría de los circuitos que usa el microcontrolador para realizar otras tareas también se podrán usar para realizar la tarea indicada. anterior, por lo que será necesario dedicar muy pocos circuitos (aparte de algo de ROM y quizás RAM) a esa tarea. Por otro lado, puede pasar un tiempo entre el momento en que cambia una entrada y el momento en que la salida lo refleja correctamente.

Usando Verilog o VHDL, se podría construir un circuito de hardware que pudiera monitorear continuamente las 15 entradas y realizar el cálculo indicado. Tal dispositivo probablemente podría hacer que la salida produzca una indicación correcta dentro de los 100 ns, órdenes de magnitud más rápido que el microcontrolador, pero la cantidad de circuitos dedicados a esa tarea e inutilizables para cualquier otro propósito sería mucho mayor.

Este no parece ser un ejemplo particularmente claro para ilustrar una distinción: hay suficientes puntos discutibles en sus detalles que realmente pueden no ayudar a familiarizar a cualquiera que no esté familiarizado. Alguien que se enfrente de manera realista a este problema probablemente elegiría una MCU moderna con una palabra de datos amplia y buenas interrupciones de cambio de pin. Decidir qué solución está consumiendo más lógica requeriría decidir si cuenta los numerosos periféricos no utilizados en la MCU o los segmentos intactos en la FPGA. El primero será bastante más barato.
@ChrisStratton: ¿Quizás debería haber sugerido que las cosas pueden cambiar si los requisitos de tiempo se vuelven más estrictos? Requerir que una CPU tenga algunos microsegundos disponibles cada 20 ms puede no requerir ningún cambio en un sistema subyacente, pero si el tiempo de respuesta necesita ser de 200 us, tal requisito podría requerir una CPU más rápida de lo que se necesitaría de otro modo, si fuera necesario. por debajo de 20us, puede ser necesario agregar una CPU adicional solo para manejarlo, y si es menor de 200ns, puede ser imposible lograrlo con una CPU.
Eso es porque no estás aprovechando las capacidades de la MCU. En la interrupción de cambio de pin, inicie un bloque de temporizador de hardware que establecerá la salida 20 ms después. Luego, decida con calma si eso está realmente justificado y, si no, cancélelo. Realmente no es un gran ejemplo para resaltar su punto FPGA porque hay mucha interdependencia: la única parte que realmente se ejecuta en paralelo es la detección de eventos, y una MCU moderna ya le brinda eso en hardware en gran parte paralelo. Mientras tanto, el resto es efectivamente secuencial, ¿así que construyes una máquina de estado ultrarrápida que observa un reloj muy lento?
@ChrisStratton: si existe una función de interrupción de cambio de pin adecuada y no se está utilizando para otra cosa, eso puede evitar la necesidad de un sondeo constante, pero si suceden muchas cosas a la vez, deberán procesarse secuencialmente a cualquier velocidad la CPU puede manejarlos.
El procesamiento secuencial no es un problema dada la gran demora que impone la declaración de su problema entre la entrada y la respuesta. E incluso si la MCU actual estuviera demasiado ocupada, agregar una para este propósito sería una fracción del costo de agregar una FPGA. Siendo realistas, la única forma en que este problema se resuelve en un FPGA es porque ya hay uno con cortes de repuesto y las señales enrutadas hacia él, o como un proyecto artificial en un contexto educativo o de pasatiempo.
@ChrisStratton: Si uno necesita un tiempo de respuesta de 10 us, un micro relativamente ordinario dedicado a ese propósito podría manejarlo. Si uno necesita un tiempo de respuesta de 100 ns, encontrar una CPU que pueda manejarlo puede ser difícil, pero incluso un FPGA lento no tendría ningún problema. Si uno reduce el tiempo a 10 ns, algunos FPGA no serían lo suficientemente rápidos para manejarlo, pero los FPGA que son lo suficientemente rápidos no son raros.
Hay muchos procesadores que pueden manejar 100 ns, pero mi principal crítica a su problema falso es que el retraso de filtrado de 20 o 21 milisegundos que impone no es realmente una tarea de FPGA, incluso si desea una precisión de 100 ns además de su retraso de 21 ms. Hay muchos problemas que realmente apuntan a los FPGA, pero este no es uno de ellos, por lo tanto, tratar de usarlo sirve para confundir en lugar de educar.
@ChrisStratton: mi intención era dar un ejemplo de una tarea fácil de describir que podría realizarse fácilmente con un microprogramado en C o un FPGA programado en Verilog/VHDL, pero donde habría una diferencia de velocidad entre los dos enfoques . Haga que la restricción de tiempo sea lo suficientemente relajada y el trabajo puede ser manejado por una CPU que también está haciendo otras cosas. A medida que la restricción se vuelve más estricta, manejarla con una CPU se vuelve más difícil, pero VHDL sigue siendo simple. Creo que 100us estaría empujando el límite de lo que una CPU puede manejar debido a los retrasos en la canalización. Un bucle en el ARM de 70 MHz que he usado para esas cosas...
Fundamentalmente, elegiste un mal ejemplo.
...no podría cumplir con el requisito, y lo que he visto de piezas más rápidas sugiere que tienen demoras más largas en la tubería.
@ChrisStratton: ¿Qué sugeriría como mejor?
Intente ver cómo se usan realmente los FPGA. Mientras tanto, es posible que también desee obtener más información sobre cómo usar los periféricos de una MCU moderna para evitar la latencia del núcleo de la CPU.