码迷,mamicode.com
首页 > 其他好文 > 详细

傻瓜的SPI的通信

时间:2015-05-29 22:58:50      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:

这两天一直在搞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=8h44;
    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<=4b0111;
         temp_data<=8h00;
         flag_send<=0;
   end
   else
   begin
      if(en_send==1)
      begin
         if(num==4b1111)
           begin
            num<=4b0111;
            flag_send<=1;
           end
         else
           begin
             flag_send<=0;
             num<=num-4b0001; 
               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<=8d23;
        temp_data<=24d0;
        flag_receive<=0;
     end
     else
     begin
        if(en_receive==1)
        begin
          if(num==8hff)
            begin
              num<=8d23;
              flag_receive<=1;
            end
          else
            begin
              flag_receive<=0;
            num<=num-8d1; 
              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+32h5A3D_70A4;
end
always @ (posedge clk or negedge rst)
begin
   if(!rst)
       f_clk<=0;
    else
    begin
       if(temp>=32h7fff_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<=8h44;
  d_in<=24haaaaaa; 
                                                
  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是并行执行的。

 

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

傻瓜的SPI的通信

标签:

原文地址:http://www.cnblogs.com/wyc199288/p/4539540.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!