请选择 进入手机版 | 继续访问电脑版

硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2303|回复: 1
收起左侧

Verilog SPI Master和Slave

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105914
QQ
发表于 2020-3-9 10:01:38 | 显示全部楼层 |阅读模式
https://alchitry.com/blogs/tutorials/serial-peripheral-interface-spi

QQ截图20200309095954.png

slave

  1. module spi_slave(
  2.     input clk,
  3.     input rst,
  4.     input ss,
  5.     input mosi,
  6.     output miso,
  7.     input sck,
  8.     output done,
  9.     input [7:0] din,
  10.     output [7:0] dout
  11.   );

  12.   reg mosi_d, mosi_q;
  13.   reg ss_d, ss_q;
  14.   reg sck_d, sck_q;
  15.   reg sck_old_d, sck_old_q;
  16.   reg [7:0] data_d, data_q;
  17.   reg done_d, done_q;
  18.   reg [2:0] bit_ct_d, bit_ct_q;
  19.   reg [7:0] dout_d, dout_q;
  20.   reg miso_d, miso_q;

  21.   assign miso = miso_q;
  22.   assign done = done_q;
  23.   assign dout = dout_q;

  24.   always @(*) begin
  25.     ss_d = ss;
  26.     mosi_d = mosi;
  27.     miso_d = miso_q;
  28.     sck_d = sck;
  29.     sck_old_d = sck_q;
  30.     data_d = data_q;
  31.     done_d = 1'b0;
  32.     bit_ct_d = bit_ct_q;
  33.     dout_d = dout_q;

  34.     if (ss_q) begin                           // if slave select is high (deselcted)
  35.       bit_ct_d = 3'b0;                        // reset bit counter
  36.       data_d = din;                           // read in data
  37.       miso_d = data_q[7];                     // output MSB
  38.     end else begin                            // else slave select is low (selected)
  39.       if (!sck_old_q && sck_q) begin          // rising edge
  40.         data_d = {data_q[6:0], mosi_q};       // read data in and shift
  41.         bit_ct_d = bit_ct_q + 1'b1;           // increment the bit counter
  42.         if (bit_ct_q == 3'b111) begin         // if we are on the last bit
  43.           dout_d = {data_q[6:0], mosi_q};     // output the byte
  44.           done_d = 1'b1;                      // set transfer done flag
  45.           data_d = din;                       // read in new byte
  46.         end
  47.       end else if (sck_old_q && !sck_q) begin // falling edge
  48.         miso_d = data_q[7];                   // output MSB
  49.       end
  50.     end
  51.   end

  52.   always @(posedge clk) begin
  53.     if (rst) begin
  54.       done_q <= 1'b0;
  55.       bit_ct_q <= 3'b0;
  56.       dout_q <= 8'b0;
  57.       miso_q <= 1'b1;
  58.     end else begin
  59.       done_q <= done_d;
  60.       bit_ct_q <= bit_ct_d;
  61.       dout_q <= dout_d;
  62.       miso_q <= miso_d;
  63.     end

  64.     sck_q <= sck_d;
  65.     mosi_q <= mosi_d;
  66.     ss_q <= ss_d;
  67.     data_q <= data_d;
  68.     sck_old_q <= sck_old_d;

  69.   end

  70. endmodule
复制代码


Master

  1. module spi #(parameter CLK_DIV = 2)(
  2.     input clk,
  3.     input rst,
  4.     input miso,
  5.     output mosi,
  6.     output sck,
  7.     input start,
  8.     input[7:0] data_in,
  9.     output[7:0] data_out,
  10.     output busy,
  11.     output new_data
  12.   );

  13.   localparam STATE_SIZE = 2;
  14.   localparam IDLE = 2'd0,
  15.     WAIT_HALF = 2'd1,
  16.     TRANSFER = 2'd2;

  17.   reg [STATE_SIZE-1:0] state_d, state_q;

  18.   reg [7:0] data_d, data_q;
  19.   reg [CLK_DIV-1:0] sck_d, sck_q;
  20.   reg mosi_d, mosi_q;
  21.   reg [2:0] ctr_d, ctr_q;
  22.   reg new_data_d, new_data_q;
  23.   reg [7:0] data_out_d, data_out_q;

  24.   assign mosi = mosi_q;
  25.   assign sck = (~sck_q[CLK_DIV-1]) & (state_q == TRANSFER);
  26.   assign busy = state_q != IDLE;
  27.   assign data_out = data_out_q;
  28.   assign new_data = new_data_q;

  29.   always @(*) begin
  30.     sck_d = sck_q;
  31.     data_d = data_q;
  32.     mosi_d = mosi_q;
  33.     ctr_d = ctr_q;
  34.     new_data_d = 1'b0;
  35.     data_out_d = data_out_q;
  36.     state_d = state_q;

  37.     case (state_q)
  38.       IDLE: begin
  39.         sck_d = 4'b0;              // reset clock counter
  40.         ctr_d = 3'b0;              // reset bit counter
  41.         if (start == 1'b1) begin   // if start command
  42.           data_d = data_in;        // copy data to send
  43.           state_d = WAIT_HALF;     // change state
  44.         end
  45.       end
  46.       WAIT_HALF: begin
  47.         sck_d = sck_q + 1'b1;                  // increment clock counter
  48.         if (sck_q == {CLK_DIV-1{1'b1}}) begin  // if clock is half full (about to fall)
  49.           sck_d = 1'b0;                        // reset to 0
  50.           state_d = TRANSFER;                  // change state
  51.         end
  52.       end
  53.       TRANSFER: begin
  54.         sck_d = sck_q + 1'b1;                           // increment clock counter
  55.         if (sck_q == 4'b0000) begin                     // if clock counter is 0
  56.           mosi_d = data_q[7];                           // output the MSB of data
  57.         end else if (sck_q == {CLK_DIV-1{1'b1}}) begin  // else if it's half full (about to fall)
  58.           data_d = {data_q[6:0], miso};                 // read in data (shift in)
  59.         end else if (sck_q == {CLK_DIV{1'b1}}) begin    // else if it's full (about to rise)
  60.           ctr_d = ctr_q + 1'b1;                         // increment bit counter
  61.           if (ctr_q == 3'b111) begin                    // if we are on the last bit
  62.             state_d = IDLE;                             // change state
  63.             data_out_d = data_q;                        // output data
  64.             new_data_d = 1'b1;                          // signal data is valid
  65.           end
  66.         end
  67.       end
  68.     endcase
  69.   end

  70.   always @(posedge clk) begin
  71.     if (rst) begin
  72.       ctr_q <= 3'b0;
  73.       data_q <= 8'b0;
  74.       sck_q <= 4'b0;
  75.       mosi_q <= 1'b0;
  76.       state_q <= IDLE;
  77.       data_out_q <= 8'b0;
  78.       new_data_q <= 1'b0;
  79.     end else begin
  80.       ctr_q <= ctr_d;
  81.       data_q <= data_d;
  82.       sck_q <= sck_d;
  83.       mosi_q <= mosi_d;
  84.       state_q <= state_d;
  85.       data_out_q <= data_out_d;
  86.       new_data_q <= new_data_d;
  87.     end
  88.   end

  89. endmodule
复制代码


回复

使用道具 举报

10

主题

244

回帖

279

积分

高级会员

积分
279
发表于 2021-1-11 22:54:24 | 显示全部楼层
&#9996;,太好了,我正在发愁CPLD上的SPI呢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-3-28 22:51 , Processed in 0.209138 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表