Simulación de firmware en el entorno ModelSim utilizando modelos en el lenguaje SystemC

En el último artículo, nos familiarizamos con el proceso de modelado de "firmware" en el entorno ModelSim, donde tanto el código de destino como el generador de acciones de prueba están escritos en el lenguaje Verilog. Es una pena, pero esto no es suficiente para el objetivo resuelto en el ciclo. En repetidas ocasiones he promovido la idea de que el desarrollo del complejo Redd debería realizarse con el mínimo esfuerzo. Si el modelo del dispositivo se escribe rápidamente, se puede escribir desde cero. La última vez hicimos un modelo de bus mediante el cual escribimos bytes en el sumador. Pero ULPI es algo muy complejo. Escribir su modelo desde cero, oh, qué difícil es. Si puede encontrar uno ya hecho, es mejor hacerlo. Y encontré ... Ay y oh, resultó estar en el lenguaje SystemC. Ahora consideraremos cómo empezar a trabajar con este lenguaje.











En realidad, este artículo apareció como un archivo DOC en junio. Luego se escribió un bloque de cinco artículos simultáneamente. Pero cargar un archivo DOC en Habr es otra tarea. Por lo tanto, sucedió que el tiempo apareció solo ahora (y dos más están languideciendo en anticipación). Al subir, noté que si no entras en el espíritu de los artículos anteriores, este parece un poco aburrido. Por tanto, si existe tal deseo, actualice al menos el último artículo de su memoria, o mejor estos dos ( "Haciendo la cabeza de un analizador de bus USB ..." y "Modelando el comportamiento de un proyecto Quartus ..." ).



Introducción



Entonces, el modelo terminado, ¿dónde puedo conseguirlo? Hay un proyecto que resuelve exactamente el mismo problema que el analizador que estamos desarrollando, pero tiene un par de características. La primera característica es para FPGA Xilinx. En segundo lugar, está completamente indocumentado. Funciona de alguna manera. Incluso puede comprar una placa de pruebas ya preparada, llenarla con un código binario ya preparado ... Y obtener algunas funciones. Cualquiera que necesite un dispositivo a cualquier precio puede simplemente seguir este camino. Pero nadie sabe cómo desarrollarlo. Ese proyecto está aquí . En el directorio \ ulpi_wrapper \ testbenchhay un conjunto de archivos para probar el subsistema de envoltura alrededor de ULPI. Recomiendan modelar en el entorno Icarus Verilog, pero hurgué y no encontré ninguna descripción sensata en la superficie de cómo hacer esto en el lenguaje SystemC. Por eso, decidí seguir trabajando en el entorno ModelSim. Si supiera cómo terminaría ... Pero no lo sabía. Por lo tanto, comencé a investigar. En el transcurso de la presentación, se mostrarán tanto los éxitos como los fracasos. Empecemos por los fracasos para que todos vean cómo no hacerlo.



Intento fallido de hacer todo "de frente"



Al principio, decidí tomar un ejemplo listo para usar y ejecutarlo en el modelado. Con el movimiento habitual de mi mano (y metimos nuestra mano en el último artículo ), creé un conjunto de pruebas que contiene archivos en Verilog y SystemC. Resultó algo como esto:







lanzo ModelSim y no veo nada en el grupo de trabajo que esté relacionado con SystemC. Veo el código de Verilogo, pero el código de Sishny no.







Si observa los registros, puede ver que no intentaron recolectarlo. ¿Qué pasa?







Información útil sobre la configuración del archivo * .do



Se sabe que el archivo * .do se usa para ejecutar ModelSim. Pero como amante de hacer todo con un "ratón", nunca miré dentro de él. ¡Busquemos y abramos! Solo hay uno de esos archivos en el directorio del proyecto. Probablemente esto es lo que necesitamos.







Lo abrimos. Al principio, el montaje de todo tipo de elementos de servicio y archivos incluidos en el proyecto.

Mira el texto
transcript on
if ![file isdirectory verilog_libs] {
	file mkdir verilog_libs
}

if ![file isdirectory vhdl_libs] {
	file mkdir vhdl_libs
}

vlib verilog_libs/altera_ver
vmap altera_ver ./verilog_libs/altera_ver
vlog -vlog01compat -work altera_ver {c:/intelfpga_lite/17.1/quartus/eda/sim_lib/altera_primitives.v}

vlib verilog_libs/lpm_ver
vmap lpm_ver ./verilog_libs/lpm_ver
vlog -vlog01compat -work lpm_ver {c:/intelfpga_lite/17.1/quartus/eda/sim_lib/220model.v}

vlib verilog_libs/sgate_ver
vmap sgate_ver ./verilog_libs/sgate_ver
vlog -vlog01compat -work sgate_ver {c:/intelfpga_lite/17.1/quartus/eda/sim_lib/sgate.v}




Pero al final, claramente el ensamblaje de las cosas que necesitamos, juzgo esto por el nombre del archivo ulpi_wrapper.v :

vlog -vlog01compat -work work +incdir+C:/Work/UsbHead1/SystemCPlay {C:/Work/UsbHead1/SystemCPlay/ulpi_wrapper.v}

vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L cycloneive_ver -L rtl_work -L work -L UsbHead1 -voptargs="+acc"  lalala

add wave *
view structure
view signals
run 10 us


De Verdad. Hay un ensamblaje de un módulo Verilog y no hay indicios de ensamblaje de módulos en SystemC. La única lástima es que este archivo DO se crea automáticamente cada vez que inicia la simulación, por lo que no puede simplemente tomarlo y editarlo. Está creado por un script TCL muy complejo. No hay ningún deseo de gobernarlo. Pero después del artículo sobre el barrio alegre , probablemente esté claro que tal nimiedad no es motivo para rendirse. Seguro que todo ya está ahí. La única lástima es que la documentación dice que "puedes hacer el script de esta manera, o puedes hacer esto", y no hay sugerencias para ejemplos. Bueno, deduzcamos todo experimentalmente. Cree un archivo C: \ Work \ UsbHead1 \ SystemCPlay \ myrun.do e intente transferirle el control. Primero, intentamos hacerlo así:







El archivo DO principal aún se continúa generando, pero su final se vuelve así:

vlog -sv -work UsbHead1 +incdir+C:/Work/UsbHead1/UsbHead1/synthesis/submodules {C:/Work/UsbHead1/UsbHead1/synthesis/submodules/UsbHead1_master_0_b2p_adapter.sv}
vlog -sv -work UsbHead1 +incdir+C:/Work/UsbHead1/UsbHead1/synthesis/submodules {C:/Work/UsbHead1/UsbHead1/synthesis/submodules/UsbHead1_master_0_timing_adt.sv}

vlog -vlog01compat -work work +incdir+C:/Work/UsbHead1/SystemCPlay {C:/Work/UsbHead1/SystemCPlay/ulpi_wrapper.v}

vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L cycloneive_ver -L rtl_work -L work -L UsbHead1 -voptargs="+acc"  lalala

do C:/Work/UsbHead1/SystemCPlay/myrun.do


Vemos que el archivo Verilog todavía está compilado, luego el proceso de modelado aún se inicia (aunque vi esto durante las ejecuciones de prueba, pero ahora puedo decir con seguridad que el comando vsim inicia este proceso), después de lo cual el control se transfiere a nuestro guión. Este script debe controlar el proceso de visualización. Pero todavía no podemos gestionar el montaje. Si los archivos recopilados no son suficientes, el sistema se caerá por error antes de que podamos hacer algo. Bueno, genial, probemos la última configuración.







Y aquí comienza la diversión. Es tan importante que lo enmarcaré.



Selecciono un guión, pero no está seleccionado. Entro en la configuración (tengo la opción seleccionada anteriormente). Yo elijo, no elegido. Y así, incluso azul en la cara. Hasta que me di cuenta, hasta que encontré cómo ganar, ¡maté a la noche! Resultó que si solo selecciona un archivo, el botón Aplicar permanecerá gris. Y los cambios no se recordarán. Es imperativo hacer que el botón Aplicar se vuelva negro mediante la edición de otros parámetros de diálogo. En la imagen de arriba, es exactamente negro. Si permanece atenuado, los cambios no se guardarán y no se volverá a configurar todo para usar el script.




El guión aún se está formando, pero su final se ha vuelto más conveniente para nosotros.

vlog -sv -work UsbHead1 +incdir+C:/Work/UsbHead1/UsbHead1/synthesis/submodules {C:/Work/UsbHead1/UsbHead1/synthesis/submodules/UsbHead1_master_0_timing_adt.sv}

do "C:/Work/UsbHead1/SystemCPlay/myrun.do"


Finalmente, ¡el proceso de construcción de fuentes para el proyecto está completamente a nuestra merced! ¡Maravilloso! En ese momento, solo pude encontrar el documento SystemC Verification con ModelSim escrito para Xilinx. Pero ModelSim está en África ModelSim. Utilizando los ejemplos de este documento y las muestras del archivo DO creado en experimentos anteriores, hice el siguiente texto de script (no se alarme por la abundancia de claves, a continuación descartaremos casi todo, luego también reemplazaremos las rutas absolutas con las relativas, en esta etapa solo saqué todo de los ejemplos y muestras generadas automáticamente).

vlog -vlog01compat -work work +incdir+C:/Work/UsbHead1/SystemCPlay {C:/Work/UsbHead1/SystemCPlay/ulpi_wrapper.v}

vlib sc_work
sccom –g –I C:/intelFPGA_lite/17.1/quartus/cusp/systemc/include –work sc_work C:/Work/UsbHead1/SystemCPlay/ulpi_driver.cpp


Redoble de tambores ... Y ModelSim nos declara:







Si omitimos todas las palabras obscenas, entonces no tengo nada que decir ... ¡Pero ese camino se ha pasado! ¿Y dónde puedo conseguir otro modelo ULPI? Por supuesto, estuve de acuerdo con amigos extranjeros que están involucrados profesionalmente en proyectos serios para FPGA. Especialmente para mí, abrieron el acceso remoto a una máquina con un ModelSim con licencia para el fin de semana. El segundo panqueque también resultó ser irregular: la versión de 64 bits, incluso en la forma con licencia, no funciona con SystemC. Pero al final, pude jugar con la versión de 32 bits del ModelSim con licencia. Por tanto, continuamos la historia ...



Algunas palabras sobre documentación



Entonces. Ahora que tengo acceso al software con licencia, es hora de hablar sobre dónde buscar información y dónde encontrar inspiración. En la web, la información sobre el idioma es bastante incompleta. Pero en la entrega del sistema, existen los siguientes directorios útiles:



C: \ modeltech_10.2c \ docs \ pdfdocs - documentación, incluidos archivos en formato PDF. Me gustaron los archivos modelsim_se_ref.pdf (ModelSim SE Command Reference Manual), modelsim_se_user.pdf (ModelSim SE User's Manual) y modelsim_se_tut.pdf (ModelSim SE Tutorial). No hay mucho sobre el idioma en sí, sino sobre cómo conectar archivos y cómo resolver problemas de dialectos, bastante.



A continuación, directorio útil C: \ modeltech_10.2c \ examples... Hay ejemplos de archivos * .do listos para usar y archivos cpp y h listos para usar. El ejemplo más útil para nosotros es C: \ modeltech_10.2c \ examples \ systemc \ vlog_sc . Le muestra cómo acceder al código SystemC desde el código Verilog. Nosotros, al final, iremos exactamente de esta manera.



El directorio C: \ modeltech_10.2c \ include \ systemc contiene el código fuente de la biblioteca de tipos de idioma. No es un mal libro de referencia. Como dicen, hay peces para la ausencia de peces y el cáncer.



Todo, desde catálogos. Ahora el título de un libro maravilloso, del que puedes aprender mucho tanto sobre el lenguaje como sobre los métodos de programación en él. SystemC: desde cero, segunda edición. Por David C. Black, Jack Donovan, Bill Bunton, Anna Keist.



Dialectos SystemC



Entonces. Habiendo obtenido acceso al sistema de trabajo, monté alegremente el proyecto, de acuerdo con el guión creado anteriormente. ¡Se montó sin errores! ¡El primer modelo de GitHub aceptó trabajar con nosotros! Queriendo ejecutar el punto de referencia, agregué el archivo ulpi_wrapper_tb.cpp del mismo directorio al proyecto y obtuve toneladas de errores. Digamos que hay un error en la línea:

m_vpi_handle = vpi_handle_by_name ((const char *) name, NULL);

difícil de arreglar, pero aún posible. Pero la linea

        // Update systemC TB
        if(sc_pending_activity())
            sc_start((int)(time_value-m_last_time),SC_NS);


evocó malos pensamientos. No hay ninguna sc_pending_activity () la función de las bibliotecas. Hay una función sc_pending_activity_at_current_time () , pero ni siquiera me molesté en ocuparme de ella. En lugar de mil palabras de explicación, daré un volcado:







Y había 44 archivos con este texto (* .exe, * .dll, etc.).



Podrías intentar reescribirlo todo ... ¿Pero es necesario? Permítanme recordarles que en realidad comencé todo esto, porque quería usar todo lo que estaba listo. Puedo desarrollar todo en un entorno libre en un SystemVerilog puro, si realmente pierdo mucho tiempo ... ¡Fui aquí para no perder el tiempo, sino para ahorrar! Pero en realidad ... Lo principal es no olvidar lo que estamos haciendo. Queremos utilizar el modelo de bus ULPI. Ella se recompuso. Surgieron problemas al intentar construir un sistema de prueba completo a partir del ejemplo ... ¿Por qué? Bueno, el sistema completo no funciona y está bien. Dominaremos un modelo, sin mirar el funcionamiento del sistema, por ensayo y error.



Eliminando malentendidos basados ​​en dialectos



Entonces. Haremos un sistema mixto. El módulo con el modelo estará escrito en el lenguaje SystemC, y le enviaré las acciones de prueba y el módulo que se está desarrollando en el lenguaje Verilog. Es decir, necesitas hacer que el módulo ulpi_driver aparezca en el grupo de trabajo .



Al examinar los archivos * .do de ejemplo de la entrega de ModelSim, simplifiqué enormemente el script y, al final, hice esto:

vlog +../../SystemCPlay {../../MyCores/ULPIhead.sv}

sccom -g ../../SystemCPlay/ulpi_driver.cpp
sccom -link


No hay errores, pero el módulo tampoco apareció en el grupo. Al examinar los archivos de ejemplo (recuerde, el mejor ejemplo que implementa exactamente esta mezcla de idiomas está en el directorio C: \ modeltech_10.2c \ examples \ systemc \ vlog_sc ), me di cuenta de que la siguiente línea debería agregarse al final del archivo ulpi_driver.cpp :

SC_MODULE_EXPORT(ulpi_driver);


La documentación de ModelSim dice que estas son características de dialecto. ¡Y voilá! Aquí está, nuestro módulo:







Cierto, el menú Crear Wave (discutimos este menú en el último artículo ) no está disponible para él. Y no tiene puertos. Históricamente, primero me ocupé de los puertos, pero metódicamente: pospondré la historia sobre ellos para más adelante. De lo contrario, debe editar el código dos veces. Para evitar esto, primero hagamos una pequeña preparación.



Hacer un generador de reloj



Resultó que el modelo tiene un par de diferencias con el ULPI real. La primera diferencia es que el chip debe generar el reloj de 66 MHz. ¿Qué vemos en el modelo?

    sc_in<bool>             clk_i;


¡Trastorno! ¡Empecemos la reelaboración! Todo el trabajo, a menos que se indique lo contrario, se realiza en el archivo ulpi_driver.h.

Cambie el tipo de puerto. Era:

    sc_in<bool>             clk_i;


se convirtió (también cambié el nombre del puerto):

    sc_inout<bool>             clk;


Aprendí del libro que un generador real se inserta agregando una variable:

    sc_clock oscillator;


Establecemos los parámetros en el constructor. Como resultado, el constructor toma la forma:

    //-------------------------------------------------------------
    // Constructor
    //-------------------------------------------------------------
    SC_HAS_PROCESS(ulpi_driver);
    ulpi_driver(sc_module_name name): sc_module(name),
                                      m_tx_fifo(1024), 
                                      m_rx_fifo(1024),
                                      oscillator ("clk66",sc_time(15,SC_NS))
    {


La última línea es solo para esto. Si lo desea, puede incluso iniciar la simulación, haga doble clic en el módulo usb_driver , luego tire de clk66 a la cabaña temporal y ejecute un poco el proceso de simulación . Ya vemos cómo funciona el generador:







No olvidemos cambiar el nombre de la señal del reloj en el lugar donde comienza el hilo principal. Era:

        SC_CTHREAD(drive, clk_i.pos());


Convirtió:

        SC_CTHREAD(drive, clk.pos());




Se han reemplazado los enlaces internos. Pero lo hermoso que es llevar la señal al exterior, no lo encontré. Quizás simplemente carezco de calificaciones. Pero de una forma u otra, todos los intentos de sacar el puerto no tuvieron éxito. Siempre había algo en el camino. Incluso encontré una discusión en un foro donde el autor necesitaba hacer lo mismo. El equipo decidió que solo se puede reenviar a los puertos de entrada. ¡Pero tenemos que salir! Por lo tanto, hacemos esto.



Agregue una función de flujo debajo del constructor:

    void clkThread(void) 
    {
       while (true)
       {
           wait(oscillator.posedge_event());
           clk.write (true);
           wait(oscillator.negedge_event());
           clk.write (false);
       }
    }


Y agregue un enlace en el constructor de la clase:

        SC_THREAD(clkThread);


Permítanme mostrar el área del constructor actual para dar una vista holística del resultado actual:

    SC_HAS_PROCESS(ulpi_driver);
    ulpi_driver(sc_module_name name): sc_module(name),
                                      m_tx_fifo(1024), 
                                      m_rx_fifo(1024),
                                      oscillator ("clk66",sc_time(15,SC_NS))
    {
        SC_CTHREAD(drive,clk.pos());
        SC_THREAD(clkThread);

        m_reg[ULPI_REG_VIDL]    = 0x24;
        m_reg[ULPI_REG_VIDH]    = 0x04;
        m_reg[ULPI_REG_PIDL]    = 0x04;
        m_reg[ULPI_REG_PIDH]    = 0x00;
        m_reg[ULPI_REG_FUNC]    = 0x41;
        m_reg[ULPI_REG_OTG]     = 0x06;
        m_reg[ULPI_REG_SCRATCH] = 0x00;
    }

    void clkThread(void) 
    {
       while (true)
       {
           wait(oscillator.posedge_event());
           clk.write (true);
           wait(oscillator.negedge_event());
           clk.write (false);
       }
    }


Todos. La primera edición está completa.



Hacer un bus de datos bidireccional



ULPI tiene un bus de datos bidireccional. Y en el modelo vemos la siguiente descripción del mismo:

    sc_out <sc_uint<8> >    ulpi_data_o;
    sc_in  <sc_uint<8> >    ulpi_data_i;


¡Trastorno! Primero haremos un espacio en blanco basado en el bus de salida, y luego lo cambiaremos todo. ¿Dónde empezar? Desde el hecho de que el bus debe poder pasar al tercer estado, y el tipo sc_uint <8> solo funciona con datos binarios. El tipo sc_lv <8> nos ayudará . Por lo tanto, cambiamos la declaración del neumático a:

    sc_inout <sc_lv<8> >    ulpi_data_o;


Ahora vaya al archivo ulpi_driver.cpp y busque todas las llamadas al bus ulpi_data_o allí . Intuitivamente, me di cuenta de que solo había un lugar para arreglar:





El mismo texto.
void ulpi_driver::drive_input(void)
{
    // Turnaround
    ulpi_dir_o.write(false);
    ulpi_nxt_o.write(false);
    ulpi_data_o.write(0x00);

    wait(oscillator.posedge_event());
}






Cambiar la línea seleccionada a

    ulpi_data_o.write("ZZZZZZZZ");


Todos. Ahora puedes en lugar de dos líneas:

    sc_inout <sc_lv<8> >    ulpi_data_o;
    sc_in  <sc_uint<8> >    ulpi_data_i;


escribe uno:

    sc_inout <sc_lv<8> >    ulpi_data;


y reemplace todas las referencias a las variables antiguas tanto en el h-nick como en el cpp-shnik por referencias a la variable ulpi_data .



Agregar alias de puerto



Entonces. Después de una larga búsqueda, llegué a la conclusión (posiblemente errónea) de que en el entorno ModelSim es fácil tomar y ver los puertos para un módulo separado en SystemC usando la GUI, sin suerte. Sin embargo, si este módulo se inserta en el sistema de prueba, aparecerán. Pero mientras hurgaba en la teoría, descubrí cómo establecer maravillosamente alias para los nombres de los puertos. El constructor de la clase final ahora se ve así:

    SC_HAS_PROCESS(ulpi_driver);
    ulpi_driver(sc_module_name name): sc_module(name),
                                      m_tx_fifo(1024), 
                                      m_rx_fifo(1024),
                                      oscillator ("clk66",sc_time(15,SC_NS)),
                                      rst_i ("rst"),     
                                      ulpi_data ("data"),
                                      ulpi_dir_o ("dir"),
                                      ulpi_nxt_o ("nxt"),
                                      ulpi_stp_i ("stp")
    {
        SC_CTHREAD(drive,clk.pos());
        SC_THREAD(clkThread);

        m_reg[ULPI_REG_VIDL]    = 0x24;
        m_reg[ULPI_REG_VIDH]    = 0x04;
        m_reg[ULPI_REG_PIDL]    = 0x04;
        m_reg[ULPI_REG_PIDH]    = 0x00;
        m_reg[ULPI_REG_FUNC]    = 0x41;
        m_reg[ULPI_REG_OTG]     = 0x06;
        m_reg[ULPI_REG_SCRATCH] = 0x00;
    }


Hacer un sistema de prueba



Bien entonces. No logré hacer todo automáticamente, por lo que dos módulos depurados (el cabezal del analizador y el modelo de bus ULPI) saltaron al archivo de prueba. Pero hagamos al menos una prueba de la cabeza y luego agreguemos ULPI. Utilizando la técnica del último artículo , hice un sistema de prueba para el archivo ULPIhead.sv . Tengo un archivo llamado sim1.v e inmediatamente se le cambió el nombre sim1.sv .



Luego agregué el módulo ulpi_driver con las manijas . El script resultante myrun.do se ve así:

vlog +../../SystemCPlay {../../MyCores/ULPIhead.sv}

sccom -g ../../SystemCPlay/ulpi_driver.cpp
sccom -link

vlog +../../SystemCPlay {../../SystemCPlay/sim1.sv}
vsim -voptargs="+acc" sim1


La última línea está torturada. Sin él, el código Verilog no tenía puertos. Al cambiar los parámetros de optimización, eliminamos este problema. Lo vi en ese archivo * .do que fue creado para simular nuestro sistema desde el principio, cuando todo estaba hecho en la máquina. Es cierto que hay una larga fila. Encontré la clave que resuelve el problema y la copié. Y entonces, no me gustan las filas largas, tiré todo lo innecesario.



Ahora agregamos el bloque ULPI al sistema de prueba y hacemos una prueba ficticia. Solo para asegurarse de que todas las señales del reloj estén funcionando y que los buses estén configurados con los valores correctos.



Me hice esta prueba.

Mira el texto.
`timescale 1ns / 1ns
module sim1  ; 
 
  reg    ulpi_dir   ; 
  wire   source_valid   ; 
  wire    ulpi_stp   ; 
  reg    ulpi_clk   ; 
  reg    ulpi_nxt   ; 
  reg    reset_n   ; 
  reg    read   ; 
  reg  [31:0]  writedata   ; 
  wire    ulpi_rst   ; 
  reg    clk   ; 
  wire  [7:0]  source_data   ; 
  reg    write   ; 
  wire  [7:0]  ulpi_data   ; 
  reg    source_ready   ; 
  reg  [1:0]  address   ; 
  wire  [31:0]  readdata   ; 

  always 
  begin
     clk = 1;
     #5;
     clk = 0;
     #5;
  end

  ULPIhead  DUT  
  ( 
      .ulpi_dir (ulpi_dir ) ,
      .source_valid (source_valid ) ,
      .ulpi_stp (ulpi_stp ) ,
      .ulpi_clk (ulpi_clk ) ,
      .ulpi_nxt (ulpi_nxt ) ,
      .reset_n (reset_n ) ,
      .read (read ) ,
      .writedata (writedata ) ,
      .ulpi_rst (ulpi_rst ) ,
      .clk (clk ) ,
      .source_data (source_data ) ,
      .write (write ) ,
      .ulpi_data (ulpi_data ) ,
      .source_ready (source_ready ) ,
      .address (address ) ,
      .readdata (readdata ) ); 


  ulpi_driver ULPI
  (
      .clk (ulpi_clk),
      .rst (ulpi_rst),
      .data (ulpi_data),
      .dir (ulpi_dir),
      .nxt (ulpi_nxt),
      .stp (ulpi_stp)

  );

  initial
  begin
     reset_n  = 1'b0;
     source_ready = 1;
     writedata = 0;
     address = 0;
     read = 0;
     write = 0;
     #20
     reset_n  = 1'b1;
  end

endmodule










Conclusión



Como mínimo, dominamos el modelado en el lenguaje SystemC utilizando el sistema ModelSim. Sin embargo, resultó que esto requiere acceso a la versión con licencia de 32 bits. La versión gratuita y la versión con licencia de 64 bits no brindan esa oportunidad. Según tengo entendido, todo se puede hacer de forma completamente gratuita en el sistema Icarus Verilog, pero no descubrí exactamente cómo lograrlo. Resultó ser más fácil para mí acceder al ModelSim requerido. En el próximo artículo, usaremos este conocimiento para modelar nuestra cabeza.



En el transcurso del trabajo, se realizaron modificaciones bastante complejas de los modelos. Los archivos resultantes se pueden descargar aquí .



All Articles