SPI接口的verilog实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
SPI接口的verilog实现
项目中使用的许多器件需要SPI接口进行配置,比如PLL:ADF4350,AD:AD9627,VGA:AD8372等,根据SPI协议,站长编写了一个简单的SPI读写程序,可以进行32为数据的读写(读者可以修改程序中数字使其变成16位或8位读写,也可以将读写位数参数化),可以设置SPI SCLK相对于主时钟的分频比。
【SPI程序】
/* SPI interface module V1.0 一些语句做了简单的英文注释*/
module spi_master(addr, in_data, out_data, rd, wr, cs, clk, miso, mosi, sclk);
input wire [1:0] addr;
input wire [31:0] in_data;
output reg [31:0] out_data;
input wire rd;
input wire wr;
input wire cs;
input wire clk;
inout miso;
inout mosi;
inout sclk;
reg sclk_buffer = 0;
reg mosi_buffer = 0;
reg busy = 0;
reg [31:0] in_buffer = 0;
reg [31:0] out_buffer = 0;
reg [7:0] clkcount = 0;
reg [7:0] clkdiv = 0;
reg [6:0] count = 0;
always@(cs or rd or addr or out_buffer or busy or clkdiv)
begin
out_data = 32'bx;
if(cs && rd)//selected and read
begin
case(addr)
2'b00: begin out_data = out_buffer; end // read data received by SPI interface
2'b01: begin out_data = {31'b0, busy}; end // read 'busy' flag of SPI interface
2'b10: begin out_data = clkdiv; end // read 'clkdiv' number of SPI
endcase
end
end
always@(posedge clk)
begin
if(!busy) //SPI interface is not busy
begin
if(cs && wr) //selected and write
begin
case(addr)
2'b00: begin in_buffer = in_data; busy = 1'b1; end //write in_data to SPI Buffer and let 'busy' flag on 2'b10: begin clkdiv = in_data; end //write 'clkdiv' number to SPI
endcase
end
end
else
begin
clkcount = clkcount + 1;
if(clkcount >= clkdiv) //every clkdiv*period(clk) time send one bit by SPI
begin
clkcount = 0;
if((count % 2) == 0) // change data in negtive sclk
begin
mosi_buffer = in_buffer[31];
in_buffer = in_buffer << 1;
end
if(count > 0 && count < 65) //32 periods
begin
sclk_buffer = ~sclk_buffer;
end
count = count + 1;
if(count > 65)
begin
count = 0;
busy = 1'b0;
end
end
end
end
always@(posedge sclk_buffer)
begin
out_buffer = out_buffer << 1;
out_buffer[0] = miso; //read data from pin 'miso'
end
assign sclk = sclk_buffer;
assign mosi = mosi_buffer;
endmodule
【SPI程序testbench】
/*
SPI module testbench V1.0
Loujianquan
2009.7.20
*/`timescale 1ns/1ns
module spi_master_tb();
reg [1:0] addr;
reg [31:0] in_data;
wire [31:0] out_data;
reg rd;
reg wr;
reg cs;
reg clk;
tri1 miso;
wire mosi;
wire sclk;
spi_master uut(addr, in_data, out_data, rd, wr, cs, clk, miso, mosi, sclk); integer counter = 0;
initial
begin
// Init
addr = 0;
in_data = 0;
rd = 0;
wr = 0;
cs = 0;
clk = 0;