EazyChange

导航

 

这两天一直在搞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是并行执行的。

 

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

posted on 2015-05-29 22:29  EazyChange  阅读(268)  评论(0编辑  收藏  举报