AVR Timing Digrams / Simulation Model

Post your suggestions for new tutorials or anything here!
Post Reply
otzen42
Posts: 46
Joined: March 1st, 2014, 2:37 pm

AVR Timing Digrams / Simulation Model

Post by otzen42 » January 3rd, 2016, 7:07 pm

Hi,

I really like the Mojo, but I was wondering if there was a good reference for the timing of the various FGPA to/from AVR signals?

Additionally, a simulation model for the AVR would be really nice. I have one that I built, but having just updated to the latest AVR firmware it is no longer functional (TX Busy signal appears to have changed behavior).

embmicro
Site Admin
Posts: 834
Joined: March 24th, 2013, 12:45 pm

Re: AVR Timing Digrams / Simulation Model

Post by embmicro » January 7th, 2016, 4:10 pm

The new tx busy behavior is that it toggles each time a new byte is received instead of going high when the buffer is full. This was done to ensure the last byte received is read by the interrupt handler before another byte overwrites it.

The only signals shared between the AVR and FPGA are an UART bus (USB to serial), an SPI port (ADC), and some flags. The timing of the flags isn't really defined as they're just flags. The other buses are standard implementations of them.

I hope this helps. Let me know if you have any questions.

Justin

otzen42
Posts: 46
Joined: March 1st, 2014, 2:37 pm

Re: AVR Timing Digrams / Simulation Model

Post by otzen42 » April 10th, 2016, 4:05 pm

It isn't super elegant, but here is a model I put together. I am just using the UART and SPI blocks from the Mojo base project (Let me know if it has issues, I did do a little cleanup on the SPI and UART modules, but I believe they are still functionally the same as the ones in the base project).

Code: Select all

////////////////////////////////////////////////////////////////////////////////
//
// Author           : Marty Otzenberger
// Creation Date    : 02/23/2014
// Project Name     : Mojo
// Top Level Module : mojo_tb.v
// Target Device    : xc6slx9-tqg144-2
// Tool Version     : 14.7
//
// Description: Simulation model of AVR for Mojo Testbench.
//
////////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps

module avr_emu (
  // Clock/Reset
  input             clk,          // System Clock
  output            cclk,         // Configuration Clock Output (650KHz, 16% Duty Cycle)
  input             rst,          // Active High Reset
  // Serial Data
  input             rx,           // Serial Data From FPGA
  output            tx,           // Serial Data To FPGA
  output reg        busy,         // AVR Serial Busy
  // SPI Interface
  output            sck,          // Serial Clock
  output            mosi,         // Master Out, Slave In
  input             miso,         // Master In, Slave Out
  output            ssf,          // Active Low Chip Select
  // ADC Channel Select
  input       [3:0] adc_channel,  // ADC Channel Select From FPGA
  // Serial Interface Data Bus
  input       [7:0] serial_tx,    // Parallel Data To Send To FPGA
  input             tx_rdy,       // New Parallel Data To Send
  output            tx_busy,      // Emulator Serial TX Busy
  output      [7:0] serial_rx,    // Parallel Data Received From FPGA
  output            rx_vld,       // New Parallel Data Received
  // ADC Inputs
  input       [9:0] adc_0,        // ADC Value For Channel 0
  input       [9:0] adc_1,        // ADC Value For Channel 1
  input       [9:0] adc_4,        // ADC Value For Channel 4
  input       [9:0] adc_5,        // ADC Value For Channel 5
  input       [9:0] adc_6,        // ADC Value For Channel 6
  input       [9:0] adc_7,        // ADC Value For Channel 7
  input       [9:0] adc_8,        // ADC Value For Channel 8
  input       [9:0] adc_9         // ADC Value For Channel 9
);

  //////////////////////////////////////////////////////////////////////////////
  // Declare Variables And Signals
  //////////////////////////////////////////////////////////////////////////////
  // Config Clock
  reg        cclk_osc     = 1'b0;
  reg        cclk_running = 1'b1;
  // ADC Interface
  wire       spi_busy;
  reg  [7:0] spi_data     = 8'h00;
  reg        spi_start    = 1'b0;
  reg        msbyte       = 1'b0;

  assign ssf = ~spi_busy;

  //////////////////////////////////////////////////////////////////////////////
  // Generate Configuration Clock
  //////////////////////////////////////////////////////////////////////////////
  // Generate Waveform
  always #1300 begin
    cclk_osc = 1'b1;
    #200
    cclk_osc = 1'b0;
  end

  // Disable CCLK After Reset
  always @(negedge rst) begin
    #10_000
    cclk_running <= 1'b0;
  end

  // Drive Output
  assign cclk = cclk_running ? cclk_osc : 1'b1;

  //////////////////////////////////////////////////////////////////////////////
  // Generate Busy Back To FPGA
  //////////////////////////////////////////////////////////////////////////////
  always @(posedge clk) begin
    // Toggle Output
    if (rst == 1'b1) begin
      busy <= 1'b0;
    end
    else begin
      if (rx_vld == 1'b1) begin
        busy <= ~busy;
      end
    end
  end

  //////////////////////////////////////////////////////////////////////////////
  // Instantiate Sub-Modules
  //////////////////////////////////////////////////////////////////////////////
  // Serial RX
  serial_rx #(
    // Baud Rate Control
    .CLK_PER_BIT  (100)  // fclk/baud
  ) avr_emu_rx_i (
    // Clock/Reset
    .clk          (clk),
    .rst          (rst),
    // Serial Input Data
    .rx           (rx),
    // User Outputs
    .data         (serial_rx),
    .new_data     (rx_vld)
  );

  // Serial TX
  serial_tx #(
    // Baud Rate Control
    .CLK_PER_BIT  (100)  // fclk/baud
  ) avr_emu_tx_i (
    // Clock/Reset
    .clk          (clk),
    .rst          (rst),
    // Serial Output Data
    .tx           (tx),
    // Destination Busy Signal
    .block        (1'b0),  // Unused
    // User Interface
    .busy         (tx_busy),
    .data         (serial_tx),
    .new_data     (tx_rdy)
  );

  // SPI Master
  spi_master #(
    .CLK_DIV   (5)
  ) avr_emu_spi_mstr_i (
    // Clock/Reset
    .clk       (clk),
    .rst       (rst),
    // SPI Signals
    .miso      (miso),
    .mosi      (mosi),
    .sck       (sck),
    // User Interface
    .start     (spi_start),
    .data_in   (spi_data),
    .data_out  (),
    .busy      (spi_busy),
    .new_data  ()
  );

  //////////////////////////////////////////////////////////////////////////////
  // ADC Interface
  //////////////////////////////////////////////////////////////////////////////
  always @(posedge clk) begin
    // Default Values
    spi_start    <= 1'b0;  // Pulse Only

    // Arbitrate ADC Channels
    case (adc_channel)
      4'h0: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_0[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_0[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      4'h1: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_1[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_1[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      4'h4: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_4[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_4[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      4'h5: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_5[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_5[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      4'h6: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_6[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_6[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      4'h7: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_7[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_7[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      4'h8: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_8[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_8[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      4'h9: begin
        // Byte-Select Data
        if (spi_start == 1'b0 && spi_busy == 1'b0) begin
          if (msbyte == 1'b0) begin
            spi_data <= adc_9[7:0];
            msbyte   <= 1'b1;
          end
          else begin
            spi_data <= {adc_channel,2'b00,adc_9[9:8]};
            msbyte   <= 1'b0;
          end
        end
        // Start Transfer
        if (spi_busy == 1'b0) begin
          spi_start <= 1'b1;
        end
      end
      default: begin
        msbyte <= 1'b0;
      end
    endcase
  end

endmodule

Post Reply