El módulo Verilog SPI funciona de manera impredecible

1

Actualmente estoy intentando implementar un módulo simple SPI Master en Verilog utilizando Quartus Prime Lite V15.1.0 Build 185 para compilación y Simulation Waveform Editor como mi herramienta de simulación. El módulo ha sido diseñado para funcionar de manera ideal de manera que usted cargue un valor de 8 bits en un bus, alternar un bit de 'transmisión' que le dice al módulo que envíe el valor, y finalmente el módulo responde con un 'hecho' bit para notificar al módulo host que se envió el byte. El módulo SPI no controla las líneas CS, ya que se supone que serán controladas por el módulo maestro.

//CPOL 0, CPHA 0 RIC60 SPI Master module

module SPI (
output reg MOSI,                        // Map to external I/O pin that will act as MOSI for the spi interface
output wire SCLK,                   // Map to external I/O pin that will act as SCLK for the spi interface
output wire DATAEN,                 // Map to external I/O pin that will act as DATAEN for the spi interface

input wire [7:0] inData,// Data to be sent over SPI

input wire CLK,                     // System clock 
input wire datCLK,                  // Clock to be used for SPI
input wire transmit,            // Trigger for when to send out SPI command
output reg done,                        // signal to trigger finished SPI comm
input wire reset);                  // System reset input


    reg _moduleActive, _moduleActiveQue; 
    reg [7:0] _inData_INT;
    reg [7:0] _countDown;
    wire _shiftData;

    reg _DCLK2, _DCLK3;
    wire _DCLK_FALL, _DCLK_RISE;

    reg _Transmit2, _Transmit3;
    wire _Transmit_FALL, _Transmit_RISE;

//Initialize
    initial begin
        _moduleActive = 0;
        _moduleActiveQue = 0;
        //_countDown[7:0] = 8'b01001100;
        MOSI = 0;
    end

//SPI Clock catch edges
    always@(posedge CLK)
   begin
      _DCLK2 <= datCLK;
   end

   assign _DCLK_FALL = (_DCLK2)&(~datCLK);
   assign _DCLK_RISE = (~_DCLK2)&(datCLK);

//Transmit catch edges
    always@(posedge CLK)
   begin
      _Transmit2 <= transmit;
   end

   assign _Transmit_RISE = (!_Transmit2)&(transmit);

//que module start at next rising edge of SPI clock
    always @ (posedge CLK) begin
        if (_Transmit_RISE) begin
            _moduleActiveQue = 1;
        end else if (_moduleActive) begin
            _moduleActiveQue = 0;
        end
    end
//put module into 'active' state
    always @ (posedge CLK) begin
        if (_moduleActiveQue && _DCLK_FALL) begin
            _moduleActive = 1;
        end else if (_countDown == 0) begin
            _moduleActive = 0;
        end
    end
//set SPI clock
    assign SCLK = datCLK && _moduleActive;

//clock out data
    always @ (posedge CLK) begin
        if (_moduleActiveQue && _DCLK_FALL) begin
            _inData_INT = inData;
            _countDown = 8'b10101010;
        end else if (_moduleActive && _DCLK_RISE) begin
            MOSI <= _inData_INT[7];
            _inData_INT <= _inData_INT << 1;
            _countDown <= _countDown << 1;
        end
    end
    endmodule

El módulo funciona utilizando un 'contador' compuesto por un valor relleno de 1, y los cambios de bits en cada reloj hasta que se igualan a 0. Actualmente este bus de contador, denunciado _countDown, es lo que está demostrando proporcionar el mayor dolor de cabeza. Cuando se simula el código anterior, produce las formas de onda como se ve en la ventana de formas de onda a continuación.

Elbitmenossignificativode_countDownpareceestaratascadoaaltaimpedanciaynocuentaatráscomoesperaríadelcódigodado.Además,comohabránotado,enelbloquede"inicio inicial" se ha comentado la inicialización de _countDown. Si esta línea de código no tiene comentarios, encuentro que _countDown siempre permanece en un estado de alta impedancia. Soy relativamente inexperto con Verilog (que puede aparecer en el código), por lo que cualquier puntero sería muy apreciado.

    
pregunta beeedy

1 respuesta

1

Según nuestra discusión en el chat , aparece el problema estar abajo al simulador incorporado. Cuando comencé a usarlo por primera vez, también tuve algunos problemas extraños, por lo que rápidamente pasé a usar ModelSim (que viene con Quartus).

Creo que el problema se debe básicamente a cómo ingresas gráficamente las formas de onda en el simulador incorporado. Esto puede confundir al simulador, especialmente si tiene mezclas de asignaciones de no bloqueo / bloqueo, y está usando muchos bordes de reloj; básicamente, la causa-efecto parece mezclarse un poco.

Esto queda claro cuando se usa ModelSim para simular el mismo diseño. Obtenemos la siguiente forma de onda:

Loqueesmuydiferenteenmuchoslugares.

LosresultadosaquíprovienendelmóduloentupublicaciónqueestácontroladoporunbancodepruebasVerilogenlugardeuneditorgráficodeformasdeonda.Estonosolohacequelaedicióndelasformasdeondadelasimulaciónseamásfácil,sinoquetambiéngarantizaquesemantengalacausa-efectodelasseñales,yaquesepuedegarantizarquetodosehagacorrectamenteenlosbordesdelreloj.

ComovienedeXilinx/Vivadoylosbancosdepruebasonfamiliares,novoyaentrarenmuchosdetallessobreellos.Loqueharéencambioesseñalarunpardeenlacesútiles:

  1. Introducción a la simulación de Quartus II con el software ModelSim-Altera
  2. Simulación con el Función NativeLink en el software Quartus II

Básicamente, estas son migajas en la configuración de ModelSim para ejecutarse directamente desde Quartus. Esto le permitirá deshacerse del simulador gráfico y usar ModelSim. Digo breadcrumbs porque la información está muy dispersa / incompleta. He tenido éxito al usar bancos de prueba directamente de Quartus con algunas molestias menores. De hecho, me parece mucho más fácil simular directamente con ModelSim usando comandos simples para compilar y simular.

Un ejemplo de cómo cargar una simulación rápida (que es la secuencia de comandos load_sim.tcl que adjunté en nuestra discusión):

# Location of simulation files
set SIMDIR "../"

# Create a work library - lets call it "spi", but you could call it anything
vlib spi

# Map the library to "work"
vmap work ./spi

# Compile the the simulation files:
# vlog filename.v tells modelsim to compile a Verilog file. Add an entry for each file
vlog $SIMDIR/spi.v

# Compile the testbench
# I wrote a quick SystemVerilog called test_program.sv, so lets compile that using the -sv flag (to indicate the language is SV).
vlog -sv ./test_program.sv

# Elaborate top level design
# test_program is the name of the testbench module
eval vsim -t ns -L work -L spi test_program

# Load the waveform "do file" Tcl script
# This is an optional file which stores things like which waveforms you want to display
# and what radix they use. You can generate this after the first run by clicking in the
# wave view and pressing CTRL-S. This will save a .do file with the setup

do ./wave.do

# Run the simulation for 1000 ns. You could do "run -all" if you have a $stop command in
# your testbench.
run 1000ns

Con este script es bastante fácil configurar una simulación para ModelSim y usar un banco de pruebas de forma similar a como lo haría en Vivado. Simplemente cambia al directorio correcto en ModelSim, y luego ingresa en el indicador do load_sim.tcl y la simulación se ejecutará.

    
respondido por el Tom Carpenter

Lea otras preguntas en las etiquetas