zoukankan      html  css  js  c++  java
  • 傻瓜的SPI的通信

    这两天一直在搞spi通信,我坚持没看任何参考例程,凭借自己的理解,闭门造车,编出来一段代码,实现spi功能,并仿真一小下。

    `timescale 1 ps/ 1 ps
    module try(
    input clk,
    input rst,
    output [7:0]data
    );
    //reg f_clk;
    reg flag;
    reg [7:0] cmd; 
    generate_clk generate_clk(clk,rst,f_clk);
      
    always @ (posedge clk or negedge rst)
    begin
      if(!rst)
      begin
        cmd=8'h44;
        flag=1;
      end
    end
    spi_send spi_send(f_clk,rst,cmd,flag,data);
    spi_receive spi_receive(f_clk,rst,flag,);
    endmodule
    
    //////////////////////////////////////////////////////spi_send
    module spi_send(
    input f_clk,
    input rst,
    input [7:0] cmd,         //输入的发送命令
    input en_send,           //发送使能
    output reg flag_send,    //发送完成标志位,完成=1
    output [7:0] data        //发送数据线
    );
    reg [3:0] num;
    reg [7:0] temp_data;
    
    always @ (posedge f_clk or negedge rst)
    begin
       if(!rst)
       begin
            num<=4'b0111;
             temp_data<=8'h00;
             flag_send<=0;
       end
       else
       begin
          if(en_send==1)
          begin
             if(num==4'b1111)
               begin
                num<=4'b0111;
                flag_send<=1;
               end
             else
               begin
                 flag_send<=0;
                 num<=num-4'b0001; 
                   temp_data[num]<=cmd[num];
                 end
            end
         end
    end
    assign data=temp_data;
    endmodule
    
    /////////////////////////////////////////////////////////////spi_receive
    module spi_receive(
    input f_clk,
    input rst,
    input en_receive,      //接受使能端
    input [23:0] d_in,     //外部芯片的数据输入口
    output reg flag_receive,//接收完成标志位
    output reg[23:0] d_out, //对外部芯片的输出
    output [23:0] data   //模块间的数据传递,等价于d_in
    );
    reg [7:0] num;
    reg[23:0] temp_data;
    always @ (posedge f_clk or negedge rst)
    begin
       if(!rst)
       begin
            num<=8'd23;
            temp_data<=24'd0;
            flag_receive<=0;
         end
         else
         begin
            if(en_receive==1)
            begin
              if(num==8'hff)
                begin
                  num<=8'd23;
                  flag_receive<=1;
                end
              else
                begin
                  flag_receive<=0;
                num<=num-8'd1; 
                  d_out[num]<=1;temp_data[num]<=d_in[num];
                end
             end
          end
    end
    assign data=temp_data;
    endmodule
    //////////////////////////////////////////////////////////////clk module
    module generate_clk(
    input clk,
    input rst,
    output reg f_clk
    );
    reg[31:0] temp;
    always @ (posedge clk or negedge rst)
    begin
       if(!rst)
           temp<=0;
        else       
           temp<=temp+32'h5A3D_70A4;
    end
    always @ (posedge clk or negedge rst)
    begin
       if(!rst)
           f_clk<=0;
        else
        begin
           if(temp>=32'h7fff_ffff)
               f_clk<=1;
            else
               f_clk<=0;
        end
    end
    endmodule

    try为顶层模块,但是没有怎么丰富它。主要还是generate_clk,spi_send,spi_receive三个模块。分别是分频模块,发送和接受模块。

    分频的不多说了,使用了32位数字分频原理。

    发送模块,设置了使能位,完成标志位,命令,数据位等。

    其仿真结果如下:接收端:

    发送端:

    最后说下,testbench代买,这是让我最头疼的,有好几次都是测试代码写错了,导致仿真不成功。现在贴上来,来警示下自己:

    `timescale 1 ps/ 1 ps
    module try_vlg_tst();
    // constants                                           
    // general purpose registers
    // test vector input registers
    reg clk;
    reg rst;
    // wires                                               
    wire [7:0]  data_s;
    wire [7:0]  data_r;
    wire f_clk;
    wire flag;
    // assign statements (if any)                          
    
    reg [23:0] d_in;
    wire [23:0] d_out;
    reg en_receive;
    spi_receive spi_receive(
     clk,
     rst,
     en_receive,
     d_in,
     flag,
     d_out,
     data_r
    );
    reg [7:0] cmd;
    reg en_send;
    spi_send spi_send(
     clk,
     rst,
     cmd,
     en_send,
     flag,
     data_s
    );
    //////////////////////////////////////////
    initial                                                
    begin 
      cmd<=8'h44;
      d_in<=24'haaaaaa; 
                                                    
      clk=0;                                          
      rst=0;
      #2 rst=1;
      forever #2 clk=~clk;  
    
      //#20 en_send<=0;                   
    end                                                    
    initial                                                
    begin
      en_send=0;en_receive=0;
      #200 en_send=1;en_receive=1;
       
    end                                                
    endmodule

    需要注意的是:

    1.module中所有的input信号都为reg形,output为reg形。所有的input的变量必须给予说明赋值!!!!!!!(其中的时钟和rst就是最重要的。通过rst的赋值,使得模块中的许多内部变量初始化。)

    2.如果有需要延时的信号,就用两个initial,否则会影响都其他信号。反正initial是并行执行的。

    之后,需要把这代码移植到真正的板子上,还有许多地方需要改,否则通信的速度可能提不上去。希望可以成功!!!

  • 相关阅读:
    springmvc 处理静态资源
    springmvc jsp 获取 上下文
    springmvc 如何设置首页
    servlet-mapping url-pattern / 和 /*区别
    nginx支持php
    openresty 变量
    git tag用法
    python 导入模块,__init__.py 的作用
    python 转码问题
    python装饰器
  • 原文地址:https://www.cnblogs.com/wyc199288/p/4539540.html
Copyright © 2011-2022 走看看