四线标准SPI主机驱动Verilog

学FPGA没多久,希望看到的有缘人可以一起讨论学习 0.o

代码:https://gitee.com/hywhj34343453/spi-host-driver

1.总体说明

这是一个四线标准SPI主机驱动。

可以通过设置参数CPOL和CPHA来控制SPI传输模式。可以通过修改spi_settings.v来自定义指令,地址,写数据,读数据位宽。接口如图所示:

2.接口说明

(1)系统时钟和复位:i_clk , i_rst

(2)用于指示要与哪个从机通讯的指示信号: [1:0]  i_slave_mem

(3)用户指令接口,包括:

①用于指示当前指令类型的指示信号:[1:0]  i_user_op_type,目前支持3种指令类型:

OP_INS = 2'd0;

OP_READ = 2'd1;

OP_WRITE = 2'd2;

其中:

INS为纯指令型,当指令输入完毕后,片选信号就会拉高。

READ为读指令类型,当指令输入完毕后,还要接收地址。当地址接收完毕后,主机会采集MISO线上的数据作为读数据。

WRITE为写指令类型,当指令输入完毕后,还要接收地址,地址接收完毕后,还要接收写数据。

②接收的指令,地址信号 : i_user_op_ins , i_user_op_addr

③用户指令和SPI主机的握手信号: i_user_op_valid , o_user_op_ready

  1. 用户数据接口,包括:

①写数据相关的:

i_user_wr_len : 写数据长度信号,用于控制主机将接收的写数据个数。

i_user_wr_data: 写数据

o_user_data_req:写数据请求信号,当写请求拉高后,用户需要向主机发送数据。即当写请求拉高后的一个周期的i_user_wr_data会被作为输入信号,写入MOSI。

②读数据相关:

i_user_rd_len:读数据长度,用户控制将要从MISO线上读取的数据个数。

i_user_rd_data:从MISO线上读取的数据

o_user_rd_data_valid:读取数据有效信号

  1. SPI接口

四线标准SPI接口,SPI_CLK,MISO,MOSI,SS

3.内部实现逻辑

状态机

基本逻辑是:当用户模块与SPI主机驱动模块指令握手成功后,进入START状态,START状态下,作为指示SPI主机驱动开始工作的running信号被拉高。这个running信号将控制:

①片选信号的拉低。

②spi_clk_cnt的跳变。后者是用来对SPI_CLK的边沿进行监测的信号。SPI_CLK将在片选信号拉低后,开始跳变。

③MOSI将在running有效的情况下,按照传输时序开始采样,发送数据。

START状态仅仅一个周期,状态机自动跳转到INS状态,寄存的指令数据将要按照传输模式的需求,利用spi_clk_cnt信号移位。MOSI也利用spi_clk_cnt信号,在特定的时刻采样。期间引入r_bit_cnt信号,作为采样数据的计数器,每采样1bit加1,当在INS状态下,r_bit_cnt等于INS_WIDTH - 1时,则说明指令输入完毕。根据传输模式的不同,在不同时刻进入下一状态。如果当前指令类型是纯指令类型,则状态跳转到FINISH,如果是读写指令,则跳转到ADDR。ADDR状态下,需要传输的是地址信息,这个工程目前默认只有一个地址。它的传输逻辑和指令类似。当地址传输完成后,会判断当前指令类型是读还是写。如果是写,就进入DATA,如果是读,就进入READ。对于这两个状态,引入新的计数器:r_byte_cnt.当状态是DATA时,在状态跳转前,先会拉高一次写请求,之后会在每次r_bit_cnt等于DATA_WIDTH - 1的时候,根据传输模式在不同周期拉高一次。DATA状态将持续到r_byte_cnt达到最大值i_user_wr_len - 1,且r_bit_cnt也计数到最大值时,跳转到FINISH状态。READ状态同理,不同的是,读数据是根据不同传输模式,对MISO移位拼接而成,当成功组成位宽为RD_WIDTH - 1的数据后,拉高o_user_rd_data_valid。当读取数据的r_byte_cnt计数到最大值i_user_rd_len - 1后,状态进入到FINISH。

FINISH状态下,running信号被拉低。相关联的,片选信号拉高,SPI_CLK,SPI_CLK_CNT恢复默认值。主机驱动准备信号拉高。

4.功能仿真

写了一个回环测试,用另一个相同的主机驱动来临时充当一下从机。

先看回环读写是否正确:

下图是作为主机的写操作,可以看到,当req拉高后,数据一次是1,2,3,4,5,6

然后下图是作为从机的读操作,可以看到,读取数据也是1,2,3,4,5.....

然后看具体的主机驱动时序是否合规,以写数据为例:

测试指令和地址如下图,分别是8’b10101010   9’b111001100

测试写数据就是回环读写用的自增数据。

下面是CPOL=0,CPHA=0的写指令下的功能时序图:

这张图是指令和地址,可以看到,在第一个时钟沿,采样数据是:10101010111001100,和测试用指令和地址是一样的。

这是数据部分,采样的数据是:0000000001_0000000010(因为我测试用数据位宽是10)也就是1和2,数据写正确。

接着看CPOL = 0,CPHA=1是否正确。

可以看到结果也是正确的。

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值