Diseño de SPI y problema de diseño secuencial general

1

Estoy tratando de describir el siguiente comportamiento de MCP4921 DAC.

Estoy utilizando la placa FPGA Basys 2 como maestra.

He escrito el siguiente código. Lo que funciona de alguna manera.

module SPI_DAC_MCP4921(
input [11:0] Data ,
input Clk,
output SCK,     
output reg CS_L, //chip select low signal
output reg SPI   // serial data
);

assign SCK = Clk;
reg [4:0] counter=0;    //20 tick counter
parameter [3:0] write_command = 4'b0111; // Anot=0 BUF=1? GAnot=1 SHDNnot=1? 
//reg [15:0] write_command_register = {write_command, Data}; // 16 bit write register
always @ (posedge Clk) begin    
        if (counter==0 | counter < 4) begin   // first 4 bits
         CS_L <= 1'b0;                        // set CS_L active
         SPI <= write_command[3-counter];     // send 4 bit write command
         counter <= counter+1;            
        end else if (counter >=4 & counter <=15) begin  //12 bits
         SPI <= Data[15-counter];       //send data bits, starting with MSB
         counter <= counter+1;
        end else if (counter > 15 & counter <=18) begin    //deactivate CS_L
         CS_L <= 1'b1;
         counter <= counter+1; 
        end else if (counter ==19) counter <= 1'b0; // 20th tick reset counter
        //counter <= counter+1;
    end
endmodule

El problema es que, mientras escribo en HDL, no pienso en el hardware real. No tengo una metodología. ¿Debo esbozar un diagrama de estado? ¿Cómo debo dibujar el flujo? Quiero decir que entiendo los bloques combinacionales; muxes, sumadores, comparadores, etc. y elementos de memoria ff.s, registros. Combinar estos bloques para un diseño más complejo me resulta difícil. Estoy buscando mejoras en mi código, consejos generales de estilo. Cualquier ayuda es apreciada.

    
pregunta zeb

1 respuesta

0

Lo que más me asusta no es el código sino el remake " que funciona de alguna manera. ". Lo que tienes es un protocolo de datos en serie. Eso solo grita por un registro de turnos. En su lugar, está instalando multiplexores por todo el lugar utilizando un índice con un operador matemático como:

SPI <= write_command[3-counter]; 
                     ^^^^^^^^^

He construido varias interfaces SPI tanto en FPGA como en ASIC. Yo siempre empiezo con una máquina de estadísticas. Los estados obvios son: IDLE, SHIFT y quizás STOP. Desde IDLE hasta SHIFT, se carga el registro de desplazamiento y se establece el CS bajo. en SHIFT usted cambia esos datos. Normalmente volvería al estado inactivo, pero puede agregar un estado de DETENER para establecer nuevamente el CS alto.
Lo que también podría necesitar es un divisor de reloj. Un SPI funciona, por ejemplo, en 1MHz pero el código a menudo se ejecuta en 10-300MHz.
Podría encontrar el código que tengo en mi archivo, pero me abstengo de hacerlo porque la mejor manera de aprender es escribirlo usted mismo. Aquí hay algunos fragmentos de código (todos escritos a medida que avanzo, no marcados)

localparam STATE_IDLE  = 2'b00,               
           STATE_SHIFT = 2'b01,
           STATE_STOP  = 2'b10;


case (state)
STATE_IDLE : // Here you need a signal that new data has arrived
    if (new_data)
    begin
       shift_out <= {write_command, Data}; 
       CS_L      <= 1'b0;
       count     <= 5'd0;  
       state     <= STATE_SHIFT;
    end // case IDLE

STATE_SHIFT: // Shift a bit out every second count
    begin
        count <= count + 5'd1;
        SCK   <= ~count[0]; // High after first count
        if (count==5'd31) // or 30? 32? Check in simulation! 
        begin
            state <= STATE_STOP;
            SCK   <= 1'b0;
        end
        if (count[0]) // Second tick: output another bit
           shift_out <= {shift_out[14:0],1'b0};
    end // case SHIFT
STATE_STOP : 
    begin
        state <= STATE_IDLE;
        CS_L <= 1'b1
    end

encase

Tenga en cuenta que en el recuento no estoy seguro de qué valor debo detener. Puedo pensarlo mucho y mucho tiempo y aún así se me ocurre una respuesta incorrecta, así que prefiero hacer lo que se muestra aquí: pongo un comentario en el código para mí mismo y necesito verificarlo. Si está mal, a menudo está mal por uno. Esto suena extraño pero no es importante poner la cantidad correcta desde el principio. Para mí es una distracción del trabajo principal que es construir la estructura correcta.

    
respondido por el Oldfart

Lea otras preguntas en las etiquetas