Guest User

spimaster

a guest
Aug 23rd, 2025
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module SPI_Master(
  2.     (* keep = "true", mark_debug = "true" *) input logic [47:0] cmd_from_accel,   //Master **IN**: Data to send on MOSI
  3.     input logic fpga_reset,      // Reset Pin from FPGA Board
  4.     input logic fpga_clk,        // FPGA Clock
  5.     input logic [5:0] init_bit_count,
  6.     input logic [5:0] data_bit_count,
  7.     (* keep = "true", mark_debug = "true" *) input logic miso,                 // Transfer TX data one bit at a time
  8.     (* keep = "true", mark_debug = "true" *) input logic start_transaction,    // Comes from accelerometer
  9.     input logic fifo_full,
  10.     (* keep = "true", mark_debug = "true" *) input logic data_read,
  11.     (* keep = "true", mark_debug = "true" *) input logic init_instruct,
  12.  
  13.     (* keep = "true", mark_debug = "true" *) output logic [47:0] data_to_fifo,    //Master **OUT**: Data received from MISO
  14.     (* keep = "true", mark_debug = "true" *) output logic mosi,             // Transfer RX data one bit at a time to mosi
  15.     (* keep = "true", mark_debug = "true" *) output logic cs,               // Chip Select Pin
  16.     (* keep = "true", mark_debug = "true" *) output logic spi_clk,          // SPI Clock
  17.     (* keep = "true", mark_debug = "true" *) output logic end_transaction
  18.     );
  19.  
  20.     typedef enum logic [3:0] {
  21.         IDLE,
  22.         LOAD,
  23.         CS_SETUP,
  24.         CS_HOLD,
  25.         INIT_TRANSFER,
  26.         DATA_TRANSFER,
  27.         CS_FINISH,
  28.         FINISH
  29.        
  30.     } e_state;
  31.    
  32.  
  33.     (* keep = "true", mark_debug = "true" *) logic [5:0] init_spi_clk_counter;
  34.     (* keep = "true", mark_debug = "true" *) logic [5:0] data_spi_clk_counter;
  35.     logic [5:0] div_counter;
  36.     logic [7:0] cs_setup_counter;
  37.     (* keep = "true", mark_debug = "true" *) e_state state;
  38.  
  39.     logic sclk_q;
  40.     (* keep = "true", mark_debug = "true" *) wire  lead =  (spi_clk & ~sclk_q);   // rising edge
  41.     (* keep = "true", mark_debug = "true" *) wire  trail = (~spi_clk &  sclk_q);  // falling edge
  42.    
  43.  
  44.     always_ff @(posedge fpga_clk) begin
  45.         if (fpga_reset)
  46.             sclk_q <= 0;
  47.         else
  48.             sclk_q <= spi_clk;
  49.     end
  50.     // CLOCK DIVIDER from 100MHz to 2.5MHz
  51.     always_ff @(posedge fpga_clk) begin
  52.         if (fpga_reset) begin
  53.             div_counter <= 0;
  54.             spi_clk <= 0;
  55.         end else if (state == IDLE || state == FINISH || state == CS_SETUP || state == CS_HOLD || state == CS_FINISH) begin
  56.             spi_clk <= 0;
  57.             div_counter <= 0;
  58.         end else begin
  59.             div_counter <= div_counter + 1;
  60.             if (div_counter == 19) begin
  61.                 div_counter <= 0;
  62.                 spi_clk <= ~spi_clk;
  63.             end else begin
  64.             end
  65.         end
  66.     end
  67.  
  68.  
  69.     always_ff @(posedge fpga_clk) begin
  70.         if (fpga_reset) begin
  71.             init_spi_clk_counter <= 0;
  72.             data_spi_clk_counter <= 0;
  73.         end else begin
  74.             case (state)
  75.                 IDLE: begin
  76.                     if (fifo_full) begin
  77.                         init_spi_clk_counter <= 0;
  78.                         data_spi_clk_counter <= 0;
  79.                     end else if (start_transaction) begin
  80.                         init_spi_clk_counter <= init_bit_count - 1;
  81.                         data_spi_clk_counter <= data_bit_count - 1;
  82.                     end
  83.                 end
  84.    
  85.             INIT_TRANSFER: if (init_instruct && trail) begin
  86.                 if (init_spi_clk_counter != 0)
  87.                     init_spi_clk_counter <= init_spi_clk_counter - 1;
  88.             end
  89.             DATA_TRANSFER: if (data_read && trail) begin
  90.                 if (data_spi_clk_counter != 0)
  91.                     data_spi_clk_counter <= data_spi_clk_counter - 1;
  92.             end
  93.             default: ;
  94.             endcase
  95.         end
  96.     end
  97.  
  98.     always_ff @(posedge fpga_clk) begin
  99.         if (fpga_reset)
  100.             state <= IDLE;
  101.         else begin
  102.             case (state)
  103.                 IDLE: if (start_transaction) state <= LOAD;
  104.                 LOAD: begin
  105.                     cs_setup_counter <= 0;
  106.                     state <= CS_SETUP;
  107.                 end
  108.                 CS_SETUP: begin
  109.                     cs_setup_counter <= cs_setup_counter + 1;
  110.                     if (cs_setup_counter == 32) begin
  111.                         state <= INIT_TRANSFER;
  112.                     end
  113.                 end
  114.                 INIT_TRANSFER: begin
  115.                 if (lead && init_spi_clk_counter == 0)
  116.                     state <= (data_read ? DATA_TRANSFER : CS_HOLD);
  117.                 end
  118.                 DATA_TRANSFER: begin
  119.                 if (lead && data_spi_clk_counter == 0)
  120.                     state <= CS_HOLD;
  121.                 end                
  122.                 CS_HOLD: begin
  123.                     cs_setup_counter <= cs_setup_counter + 1;
  124.                     if (cs_setup_counter == 32) begin
  125.                         cs_setup_counter <= 0;
  126.                         state <= CS_FINISH;
  127.                     end
  128.                 end
  129.                 CS_FINISH: begin
  130.                     cs_setup_counter <= cs_setup_counter + 1;
  131.                     if (cs_setup_counter == 64) begin
  132.                         state <= FINISH;
  133.                     end
  134.                 end
  135.                 FINISH: state <= IDLE;
  136.  
  137.                 default: state <= IDLE;
  138.             endcase
  139.         end
  140.     end
  141.  
  142.     always_ff @(posedge fpga_clk) begin
  143.         if (fpga_reset) begin
  144.             cs <= 1;
  145.             end_transaction <= 0;
  146.         end else begin
  147.             cs              <= (state == IDLE || state == FINISH || state == CS_FINISH) ? 1 : 0;
  148.             end_transaction <= (state == FINISH);
  149.         end
  150.     end
  151.  
  152.     always_ff @(negedge fpga_clk) begin
  153.         if (fpga_reset) begin
  154.             mosi <= 1'b0;
  155.         end else if (state == INIT_TRANSFER && trail) begin
  156.             if (init_spi_clk_counter > 0)
  157.                 mosi <= cmd_from_accel[init_spi_clk_counter];
  158.         end
  159.     end
  160.  
  161.     always_ff @(posedge fpga_clk) begin
  162.         if (fpga_reset) begin
  163.             data_to_fifo <= 0;
  164.         end else if (state == IDLE) begin
  165.             data_to_fifo <= 0;  
  166.         end else if (state == DATA_TRANSFER && lead) begin
  167.             data_to_fifo[data_spi_clk_counter] <= miso;
  168.         end
  169.     end
  170.  
  171. endmodule
  172.  
  173. //master selects a slave by pulling CS low.
Advertisement
Add Comment
Please, Sign In to add comment