【Verilog实例】第一篇--SPI串行总线

本文详细介绍了SPI串行总线的工作原理、设计实现以及在802.1lb无线局域网芯片中的应用。通过Vivado波形仿真,展示了如何使用Verilog编程生成SPI接口的时钟信号和数据转换。
摘要由CSDN通过智能技术生成

【Verilog实例】第一篇–SPI串行总线

1.SPI的简要介绍
SPI(Serial Parallel Bus)总线是Motorola公司提出的一个同步串行外设接口,允许CPU 与各种外围接口器件(包括模/数转换器、数/模转换器、液晶显示驱动器)以串行方式进行通信、交换信息。他使用4条线:串行时钟线(SCK)、主机输入/从机输出线(MISO)、主机输出/从机输入线(MOSI)、低电平有效的使能信号线(CS)。这样,仅需3~4根数据线和控制线即可扩展具有SPI接口的各种I/O器件,其典型结构如图所示:

*串行通信:“串行”数据传输方式指数据位按顺序依次传输,一个接一个地发送或接收。在串行通信中,数据被转换成位流,并通过单个通道(如电缆、光纤等)传输。在接收端,接收器将位流重新组装成数据。串行通信通常比并行通信需要更少的物理线路,因为它只需要一个通道来传输数据,而不是多个通道。这使得串行通信在一些情况下更加适用,特别是在长距离传输或高速传输的情况下。串行通信有许多不同的标准和协议,例如串行通信中常见的UART(通用异步收发传输器)、SPI(串行外围接口)、I2C(Inter-Integrated Circuit)和串行ATA(Advanced Technology Attachment)等。
在这里插入图片描述

2.SPI总线接口的设计与实现
该模块是802.1lb无线局域网芯片中的一子模块,其系统信号交互如下图所示:
在这里插入图片描述
其中base band(基带)为SPI的主控器(master),RF(射频)为SPI的受控器(slave)。该SPI接口需要完成以下工作:
1)将从base band接收到的16位的并行数据,转换为RF所能接收的串行数据,并将该数据根据SPI协议送给RF。
2) 产生RF所需的时钟信号SCLK,使能信号(也称:片选信号)CSB。
3) 接收从RF传回的串行数据,并将其转换为并行数据。
4) 将base band发送的数据,与RF返回的数据进行比较,并把比较结果传给base band。

以下为SPI数据传输的部分代码片段,主要功能为产生计数器以同步slave模块的时钟sclk,并且将串行数据转换为并行数据。

生成计数器:

always@(posedge clock or negedge reset)
begin
  if(!enable)
    counter<= 0;
  else if(enable)
  begin
    if(counter< 53)
    counter=counter + 1;
  end
end

生成使能信号csb:

//片选信号低位有效
always@ (posedge clock or negedge reset)
begin
  if(reset)
    csb <=1;
  else if(counter>= 1 && counter <= 50)
    csb = 0;
  else
    csb = 1;
end

生成RF模块使用的时钟信号sclk:

//每三个节拍,RF信号拉为高电平,使其可以接收数据
always@ (posedge clock or negedge reset)
begin
  case(counter)
    6'd02: sclk = 1;
    6'd05: sclk = 1;
    6'd08: sclk = 1;
    6'd11: sclk = 1;
    6'd14: sclk = 1;
    6'd17: sclk = 1;
    6'd20: sclk = 1;
    6'd23: sclk = 1;
    6'd26: sclk = 1;
    6'd29: sclk = 1;
    6'd32: sclk = 1;
    6'd35: sclk = 1;
    6'd38: sclk = 1;
    6'd41: sclk = 1;
    6'd44: sclk = 1;
    6'd47: sclk = 1;
    default sclk = 0;
endcase
end

RF端接收数据:

//每三个节拍,slave接受一位数据
always@ (counter or csb)
begin
  if(csb == 0)
  case(counter)
    6'h00,
    6'h01,
    6'h02,
    6'h03:mosi_index = 5'h00;
    6'h04,
    6'h05,
    6'h06:mosi_index = 5'h01;
    6'h07,
    6'h08,
    6'h09:mosi_index = 5'h02;
    6'h0A,
    6'h0B,
    6'h0C:mosi_index = 5'h03;
    6'h0D,
    6'h0E,
    6'h0F:mosi_index = 5'h04;
    6'h10,
    6'h11,
    6'h12:mosi_index = 5'h05;
    6'h13,
    6'h14,
    6'h15:mosi_index = 5'h06;
    6'h16,
    6'h17,
    6'h18:mosi_index = 5'h07;
    6'h19,
    6'h1A,
    6'h1B:mosi_index = 5'h08;
    6'h1C,
    6'h1D,
    6'hlE:mosi_index = 5'h09;
    6'h1F,
    6'h20,
    6'h21:mosi_index = 5'h0A ;
    6'h22,
    6'h23,
    6'h24:mosi_index = 5'h0B;
    6'h25,
    6'h26,
    6'h27:mosi_index = 5'h0C ;
    6'h28,
    6'h29,
    6'h2A:mosi_index = 5'h0D ;
    6'h2B,
    6'h2C,
    6'h2D:mosi_index = 5'h0E;
    6'h2E,
    6'h2F,
    6'h30:mosi_index = 5'h0F;
    default:mosi_index = 5'h00;
  endcase
  else
    mosi_index = 5'h00:
end
assign mosi=spi_data[mosi_index];

使用Vivado进行波形仿真:
在这里插入图片描述

附:一个简易的testbench文件为:

module SPI_test;

reg clock,reset;
reg [15:0] spi_data=16'haaaa;
reg enable;
wire [5:0] counter;
wire csb;
wire sclk;
wire mosi;
wire [4:0] mosi_index;

SPI spi(clock,reset,spi_data,enable,counter,csb,sclk,mosi,mosi_index);

always #5 clock=~clock;

initial begin

#0 clock=1'b0;
   reset=1'b1;
   enable=1'b0;
#10 reset=1'b0;
   enable=1'b1;
end

endmodule

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值