Advertisement
Guest User

Untitled

a guest
Jan 12th, 2021
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module SPI_slave #(
  2.     parameter data_width = 16
  3.   )(
  4.     input wire clk,  // Тактовая частота, относительно высокочастотная.
  5.     input wire n_cs, // Выбор ведомого SPI
  6.     input wire mosi, // Вход данных SPI
  7.     output reg miso, // Выход данных SPI
  8.     input wire sclk, // Тактовый сигнал SPI
  9.    
  10.     input wire [data_width - 1:0] data_tx, // Это то что модуль будет выдавать в SPI.
  11.     output reg [data_width - 1:0] data_rx, // Это то что принялось SPI.
  12.     output reg data_valid = 1'b0 // Это сигнал того что принялось целое слово по SPI, импульс длительностью в 1 период.
  13.   );
  14.  
  15.   reg sclk_perv = 1'b0;
  16.   reg [$clog2(data_width) - 1:0] cnt = 'b0;
  17.  
  18.   always @(posedge clk) begin
  19.     if (n_cs) begin
  20.       sclk_perv <= 1'b0;
  21.       cnt <= 'b0;
  22.       data_valid <= 1'b0;
  23.     end else begin
  24.       sclk_perv <= sclk;
  25.       data_valid <= 1'b0;
  26.      
  27.       if (sclk_perv == 0 && sclk == 1) begin
  28.         miso <= data_tx[data_width - cnt - 1'b1];
  29.       end
  30.      
  31.       if (sclk_perv == 1 && sclk == 0) begin
  32.         data_rx <= {data_rx[data_width - 2:0], mosi};
  33.         if (cnt == data_width - 1) begin
  34.           cnt <= 'b0;
  35.           data_valid <= 1'b1;
  36.         end else begin
  37.           cnt <= cnt + 1'b1;
  38.         end
  39.       end
  40.     end
  41.   end
  42. endmodule
  43.  
  44. module SPI_addresable #(
  45.     parameter data_width = 16
  46.   )(
  47.     input wire clk, // Общий высокочастотный тактовый сигнал.
  48.     // SPI
  49.     input wire n_cs,
  50.     input wire mosi,
  51.     output wire miso,
  52.     input wire sclk,
  53.    
  54.     // А это для подключения к памяти.
  55.     input wire [data_width - 1:0] data_in,
  56.     output wire [data_width - 1:0] data_out,
  57.     output reg [data_width - 2:0] addr = 'b0,
  58.     output reg data_rd = 1'b0,
  59.     output reg data_we = 1'b0
  60.   );
  61.  
  62.   reg wr_enable = 1'b0;
  63.   reg status = 1'b0;
  64.  
  65.   wire data_valid;
  66.  
  67.   always @(posedge clk) begin
  68.     if (n_cs) begin
  69.       addr <= 'b0;
  70.       wr_enable <= 1'b0;
  71.       status <= 1'b0;
  72.     end else if (data_valid) begin
  73.       if (status) begin
  74.         data_rd <= 1'b1;
  75.         data_we <= 1'b1;
  76.         addr <= addr + 1'b1;
  77.       end else begin
  78.         status <= 1'b1;
  79.         addr <= data_out[data_width - 2:0];
  80.         wr_enable <= data_out[data_width - 1];
  81.         data_rd <= 1'b1;
  82.       end
  83.     end else begin
  84.       data_rd <= 1'b0;
  85.       data_we <= 1'b0;
  86.     end
  87.   end
  88.  
  89.   SPI_slave #(
  90.     .data_width(data_width)
  91.   ) SPI_slave_inst (
  92.     .clk(clk),
  93.     .n_cs(n_cs),
  94.     .mosi(mosi),
  95.     .miso(miso),
  96.     .sclk(sclk),
  97.     .data_tx(data_in),
  98.     .data_rx(data_out),
  99.     .data_valid(data_valid)
  100.   );
  101. endmodule
  102.  
  103. module SPI_addresable_tb;
  104.   reg clk = 1'b0;
  105.   reg n_cs = 1'b1;
  106.   reg mosi = 1'b0;
  107.   reg sclk = 1'b0;
  108.   wire [15:0] data_out;
  109.   wire [14:0] addr;
  110.   wire data_rd;
  111.   wire data_we;
  112.   integer i;
  113.  
  114.   always
  115.     #10 clk = !clk;
  116.  
  117.   task send_word(input [15:0] data);
  118.   begin
  119.     for (i = 15; i >= 0; i = i - 1) begin
  120.       mosi = data[i];
  121.       sclk = 1'b1;
  122.       #100 sclk = 1'b0;
  123.       #100;
  124.     end
  125.   end
  126.   endtask
  127.  
  128.   initial begin
  129.     #200;
  130.     n_cs = 1'b0;
  131.     send_word(16'b1000_0000_0000_0000); #200;
  132.     send_word(16'h1234); #200;
  133.     send_word(16'h5678); #200;
  134.     send_word(16'habcd); #200;
  135.     n_cs = 1'b1;
  136.   end
  137.  
  138.   SPI_addresable SPI_addresable_inst (
  139.     .clk(clk),
  140.     .n_cs(n_cs),
  141.     .mosi(mosi),
  142.     .miso(miso),
  143.     .sclk(sclk),
  144.  
  145.     .data_in(16'h3214),
  146.     .data_out(data_out),
  147.     .addr(addr),
  148.     .data_rd(data_rd),
  149.     .data_we(data_we)
  150.   );
  151. endmodule
  152.  
  153. module SPI_slave_tb;
  154.   reg clk = 1'b0;
  155.   reg n_cs = 1'b1;
  156.   reg mosi = 1'b0;
  157.   reg sclk = 1'b0;
  158.   wire [15:0] data_out;
  159.   wire data_valid;
  160.   integer i;
  161.  
  162.   always
  163.     #10 clk = !clk;
  164.  
  165.   task send_bit(input data);
  166.   begin
  167.     mosi = data;
  168.     sclk = 1'b1;
  169.     #100 sclk = 1'b0;
  170.     #100;
  171.   end
  172.   endtask
  173.  
  174.   task send_word(input [15:0] data);
  175.   begin
  176.     for (i = 15; i >= 0; i = i - 1) begin
  177.       send_bit(data[i]);
  178.     end
  179.   end
  180.   endtask
  181.  
  182.   initial begin
  183.     #200;
  184.     n_cs = 1'b0;
  185.     send_word(16'hF00F);
  186.     n_cs = 1'b1;
  187.   end
  188.  
  189.   SPI_slave SPI_slave_inst (
  190.     .clk(clk),
  191.     .n_cs(n_cs),
  192.     .mosi(mosi),
  193.     .miso(miso),
  194.     .sclk(sclk),
  195.     .data_tx(16'hF00F),
  196.     .data_rx(data_out),
  197.     .data_valid(data_valid)
  198.   );
  199. endmodule
  200.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement