• 已绑定课时
  • 工程师可点评

实验报告 · 09 | 项目仿真:SPI接口代码仿真 课程:初级 | FPGA工程师基础启航(含板卡+证书) · 第三节 基础逻辑电路设计篇 发布自课程云笔记 · FPGA 实验证据骨架 【同步·课后作业】 【作业要求】 1、简述SPI的特点 1).传输速率快(一般都能达到几十M的速率)。 2).通信方式简单,采用一般采用4根线进行通信,也有一些设备采用3线通信。 3).采用边沿采样,上升沿采样或…

吕在裕
111 0

实验报告 · 09 | 项目仿真:SPI接口代码仿真

课程:初级 | FPGA工程师基础启航(含板卡+证书) · 第三节 基础逻辑电路设计篇

发布自课程云笔记 · FPGA 实验证据骨架

1、简述SPI的特点

1).传输速率快(一般都能达到几十M的速率)。

2).通信方式简单,采用一般采用4根线进行通信,也有一些设备采用3线通信。

3).采用边沿采样,上升沿采样或者下降沿采样。

4).由于没有应答机制,缺乏一定的稳定性。

5). SPI通信支持一主一从的通信方式,也支持一主多从的通信方式。

2、请写出SPI接收端的详细代码?

`timescale 1ns / 1ps
module rx#(
parameter CPOL = 0,
parameter CPHA = 0

)(

input sysclk,
input rst_n,
input [7:0] data_in,        //输入数据
input SCK,
input MOSI,
input CS,
output reg MISO,
output reg [7:0] data_out,  //输出接收到的数据
output reg byte_done,       //接收完一个字节的标志
output spi_done
);
//--------------内部信号声明----------------
reg [2:0] cnt_bit ;//bit为计数器,计传输了多少个bit数
reg [7:0] data_out_reg;//输入数据缓存
reg [7:0] data_in_reg;//输出数据缓存
//-----------------边沿检测-----------------
//sck边沿
reg sck_d0, sck_d1;//SCK二级缓存
wire sck_rise, sck_fall;//上升沿和下降沿标志
always @(posedge sysclk or negedge rst_n)
begin
if(!rst_n)
  begin
sck_d0 <= 1'b0;
sck_d1 <= 1'b0;
end
else
  begin
sck_d0 <= SCK;
sck_d1 <= sck_d0;
end
end
assign sck_rise = sck_d0 & ~sck_d1;//SCK上升沿标志
assign sck_fall = ~sck_d0 & sck_d1;//SCK下降沿标志
//CS边沿
reg cs_d0, cs_d1;
wire cs_rise, cs_fall;
always @(posedge sysclk or negedge rst_n)
begin
if (!rst_n)
  begin
cs_d0 <= 1'b0;
cs_d1 <= 1'b0;
end
else
  begin
cs_d0 <= CS;
cs_d1 <= cs_d0;
end
end
assign cs_rise = cs_d0 & ~cs_d1;//CS上升沿标志
assign cs_fall = ~cs_d0 & cs_d1;//CS下降沿标志
assign spi_done = cs_rise;      //CS上升沿作为结束标志
//数据采集更新点设置
wire sck_smp_flag;
wire sck_upd_flag;
assign sck_smp_flag = (CPHA == CPOL) ? sck_rise : sck_fall ;//模式0和模式3上升沿采样
assign sck_upd_flag = (CPHA == CPOL) ? sck_fall : sck_rise ;//模式0和模式3下降沿更新
//data_in_reg----输入数据缓存--打一拍,将数据同步到当前时钟域下
always @(posedge sysclk or negedge rst_n)
begin
if(!rst_n)
data_in_reg <= 0;
else if(cs_d0 && !CS)       //早一拍更新缓存
data_in_reg <= data_in; //数据缓存
else
data_in_reg <= data_in_reg; //保持
end
//---------------bit计数器-----------------
always @(posedge sysclk or negedge rst_n)
begin
if (!rst_n)
cnt_bit <= 3'd0;
else if (!CS)
  begin
if (sck_smp_flag == 1)begin
if (cnt_bit == 7)
cnt_bit <= 3'd0;
else
cnt_bit <= cnt_bit + 1;
end
else
cnt_bit <= cnt_bit;
end
else
cnt_bit <= 3'd0;
end
//采集MOSI线上的数据
always @(posedge sysclk or negedge rst_n)
begin
if (!rst_n)
  begin
data_out_reg <= 8'd0;
end
else if(!CS)begin
if (sck_smp_flag)
  begin          //采集点 SCK 上升沿采集
if(cnt_bit == 3'd7)
data_out_reg <= 8'd0;
else
data_out_reg <= {data_out_reg[6:0], MOSI};
end
else
data_out_reg <= data_out_reg;
end
else
data_out_reg <= data_out_reg;
end
//数据输出
always @(posedge sysclk or negedge rst_n)
begin
if (!rst_n)
  begin
data_out <= 8'd0;
byte_done <= 1'b0;
end
else if(!CS && sck_smp_flag == 1 && cnt_bit == 7)begin
data_out <= {data_out_reg[6:0], MOSI};
byte_done <= 1'b1;
end
else
  begin
data_out <= data_out;
byte_done <= 1'b0;
end
end
//数据发送
always @(posedge sysclk or negedge rst_n)
begin
if (!rst_n)
MISO <= 1'bz;
else if (!CS)
  begin
if ((CPHA == 0 && cs_fall) || (CPHA == 1 && sck_upd_flag && cnt_bit == 0) || sck_upd_flag)  //不同模式第一个数据可能会丢失,加入限制条件
MISO <= data_in_reg[7 - cnt_bit];
else
MISO <= MISO;
end
else
MISO <= 1'bz;
end
endmodule

本节要验证什么?预期现象是什么?

用工具栏插入波形图、仿真界面或示波器照片

粘贴关键仿真输出或报错原文

板卡现象、按键/数码管/接口实测结果

结论、坑点与下一步修改

学习上下文

产出状态

工程师已阅111 位工程师