标签:
这两天一直在搞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是并行执行的。
之后,需要把这代码移植到真正的板子上,还有许多地方需要改,否则通信的速度可能提不上去。希望可以成功!!!
标签:
原文地址:http://www.cnblogs.com/wyc199288/p/4539540.html