基于FPGA的SPI串行方式自动发送技术设计

一、摘要: spi 接口应用十分广泛,在很多情况下,人们会用软件模拟的方法来产生spi 时序或是采用带spi 功能模块的mcu。但随着可编程逻辑技术的发展,人们往往需要自己设计简单的spi 发送模块。本文介绍一种基于fpga 的将并行数据以spi 串行方式自动发送出去的方法。
二、关键字: vhdl、fpga、spi、串行数据输出选择模块、移位脉冲产生模块、spi 时钟采集信号和无相移的spi 基准时钟产生模块、spi 时钟输出选择模块、8bit spi 时钟采集生成模块、16bit spi 时钟采集生成模块、24bit spi 时钟采集生成模块、8bit 数据移位模块、16bit 数据移位模块、24bit 数据移位模块。
三、功能框图: spi_modes 为输入模式选择端口:
--01is 8bit 传输模式
--10is 16bit 传输模式
--11is 24bit 传输模式
clks 为整个模块的基准时钟
dbinouts 为并行数据输入端口:
--8bit 模式为dbinouts(7 downto 0)
--16bit 模式为dbinouts(15 downto 0)
--24bit 模式为dbinouts(23 downto 0)
spi_wr 为启动spi 传输的信号
整个功能模块可工作在 8bit、16bit、24bit spi 猝发传输状态。对其进行软件操作的步骤相当简单:
--此模块软件操作流程如下
--1、spi_modes=xx 设定串口操作模式
--2、dbinouts=xxxxxxxxxxxxxxxxxxxxxxxx 输入要发射的数据
--3、spi_wr='0'
--4、spi_wr='1'
--5、spi_wr='0'
--8bit 模式延时2*8*4*clks
--16bit 模式延时2*16*4*clks
--24bit 模式延时2*24*4*clks
--6、dbinouts=xxxxxxxxxxxxxxxxxxxxxxxx 输入下一个要发射的数据
四、vhdl 描述解读 --以下描述的是一个spi 自动发射模块
--在很多情况下,人们会用软件模拟的方法来产生spi 时序
--这里采用硬件的方法,即使软件操作更为简单,有提高了传输的速度
--------------------------------------------------------------
--此模块软件操作流程如下
--1、spi_modes=xx 设定串口操作模式
--2、dbinouts=xxxxxxxxxxxxxxxxxxxxxxxx 输入要发射的数据
--3、spi_wr='0'
--4、spi_wr='1'
--5、spi_wr='0'
--8bit 模式延时2*8*4*clks
--16bit 模式延时2*16*4*clks
--24bit 模式延时2*24*4*clks
--6、dbinouts=xxxxxxxxxxxxxxxxxxxxxxxx 输入下一个要发射的数据
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity spi_interface is
port(clks :in std_logic; --基准时钟
lcd_scls :out std_logic;--spi 发射时钟,上升沿有效
lcd_sdis :out std_logic;--spi 数据串行输出口
spi_modes :in std_logic_vector(1 downto 0);
--串口操作模式选择
--01is 8bit trans mode
--10is 16bit trans mode
--11is 24bit trans mode
spi_wr :in std_logic; --启动串口发送信号
dbinouts :in std_logic_vector(23 downto 0));
--背发送数据的并行输入口
--8bit mode use dbinouts(7 downto 0)
--16bit mode use dbinouts(15 downto 0)
--24bit mode use dbinouts(23 downto 0)
end;
architecture spi_interface_behav of spi_interface is
signal db8bit_reg :std_logic_vector(7 downto 0); --8bit 数据移位寄存器
signal db16bit_reg :std_logic_vector(15 downto 0);--16bit 数据移位寄存器
signal db24bit_reg :std_logic_vector(23 downto 0);--24bit 数据移位寄存器
signal counter4 :std_logic_vector(3 downto 0); --移位脉冲产生计数器
signal counter4s :std_logic_vector(1 downto 0); --spi 时钟生成计数器
signal counter8 :std_logic_vector(4 downto 0); --8bit spi 时钟控制计数器
signal counter16 :std_logic_vector(5 downto 0); --16bit spi 时钟控制计数器
signal counter24 :std_logic_vector(5 downto 0); --24bit spi 时钟控制计数器
signal shift :std_logic;--移位时钟脉冲
signal lcd_sclss :std_logic;--spi 时钟采集信号
signal lcd_sclsss :std_logic;--无相移的spi 基准时钟
signal lcd_sclss8 :std_logic;--8bit spi 时钟信号
signal lcd_sclss16 :std_logic;--16bit spi 时钟信号
signal lcd_sclss24 :std_logic;--24bit spi 时钟信号
signal lcd_sdis_8bit :std_logic;--8bit spi 数据信号
signal lcd_sdis_16bit :std_logic;--16bit spi 数据信号
signal lcd_sdis_24bit :std_logic;--24bit spi 数据信号
begin
--串行数据输出选择模块
u1:process(lcd_sdis_8bit,lcd_sdis_16bit,lcd_sdis_24bit,spi_modes)
begin
if spi_modes=01 then --选择8bit 串行数据输出
lcd_sdis<=lcd_sdis_8bit;
elsif spi_modes=10 then --选择16bit 串行数据输出
lcd_sdis<=lcd_sdis_16bit;
elsif spi_modes=11 then --选择24bit 串行数据输出
lcd_sdis<=lcd_sdis_24bit;
else lcd_sdis<='1';
end if;
end process;
--移位脉冲产生模块
u2:process(clks)
begin
if clks='1' and clks'event then
if counter4=0011 then
counter4<=0000;
shift <='1';
else counter4<=counter4+1;
shift <='0';
end if;
end if;
end process;
--spi 时钟采集信号和无相移的spi 基准时钟产生模块
u3:process(clks)
begin
if clks='1' and clks'event then
if counter4s<11 then
counter4s<=counter4s+1;
else counter4s<=00;
end if;
end if;
lcd_sclss<=counter4s(0); --spi 时钟采集信号
lcd_sclsss<=counter4s(1); --无相移的spi 基准时钟
end process;
--spi 时钟输出选择模块
u4:process(lcd_sclss8,lcd_sclss16,lcd_sclss24,spi_modes)
begin
if spi_modes=01 then
lcd_scls<=lcd_sclss8; --选择8bit spi 时钟模式
elsif spi_modes=10 then
lcd_scls<=lcd_sclss16; --选择16bit spi 时钟模式
elsif spi_modes=11 then
lcd_scls<=lcd_sclss24; --选择24bit spi 时钟模式
else lcd_scls<='1';
end if;
end process;
--8bit spi 时钟采集生成模块
counter8_u:process(lcd_sclss)
begin
if spi_wr='1' then
counter80 then
counter8<=counter8-1;
lcd_sclss8<=lcd_sclsss;
end if;
end if;
end process;
--16bit spi 时钟采集生成模块
counter16_u:process(lcd_sclss)
begin
if spi_wr='1' then
counter160 then
counter16<=counter16-1;
lcd_sclss16<=lcd_sclsss;
end if;
end if;
end process;
--24bit spi 时钟采集生成模块
counter24_u:process(lcd_sclss)
begin
if spi_wr='1' then
counter240 then
counter24<=counter24-1;
if (counter24=000000)or(counter24=000001)or
(counter24=110011)or(counter24=000010)then
lcd_sclss24<='0';
else
lcd_sclss24<=lcd_sclsss;
end if;
end if;
end if;
end process;
--8bit 数据移位模块
db8bit_u:process(shift,spi_wr,dbinouts)
begin
if spi_wr='1' then
db8bit_reg<=dbinouts(7 downto 0);
else
if shift='1' and shift'event then
lcd_sdis_8bit<=db8bit_reg(0);
db8bit_reg(6 downto 0)<=db8bit_reg(7 downto 1);
end if;
end if;
end process;
--16bit 数据移位模块
db16bit_u:process(shift,spi_wr,dbinouts)
begin
if spi_wr='1' then
db16bit_reg(15 downto 0)<=dbinouts(15 downto 0);
else
if shift='1' and shift'event then
lcd_sdis_16bit<=db16bit_reg(0);
db16bit_reg(14 downto 0)<=db16bit_reg(15 downto 1);
end if;
end if;
end process;
--24bit 数据移位模块
db24bit_u:process(shift,spi_wr,dbinouts)
begin
if spi_wr='1' then
db24bit_reg(23 downto 0)<=dbinouts(23 downto 0);
else
if shift='1' and shift'event then
lcd_sdis_24bit<=db24bit_reg(0);
db24bit_reg(22 downto 0)<=db24bit_reg(23 downto 1);
end if;
end if;
end process;
end;
五、仿真波形图
六、编译后资源占用情况
七、结束语 本文旨在给学习可编程技术的人们提供一个参考,起到抛砖引玉的作用。望阅读过此文的读者提供更好的方法,与所有的学习者共享,共勉!

华为p10评测:华为p10与三星s8对比评测,韩国三星S8剑指中国华为P10 你将为谁买单?
智能制造的“神经”——物联网
首块激光器和光栅集成新型硅芯片
联想Z6真机曝光背部采用了玻璃后盖设计将可能搭载骁龙730处理器
五大网络攻击方法深度分析及应对法则
基于FPGA的SPI串行方式自动发送技术设计
iPhone X面板有优势 TFT LCD阵营可望加速赶上
工业安全是什么,应用场景有哪些
人脸识别与虹膜识别两者之间的区别是什么
首尔半导体LED路灯在欧洲市场获得好评
因AIGC失业的人已经出现,Adobe Firefly 能否在职场力挽狂澜?
cbb81电容在电路中怎么应用?让你更了解CBB81高压谐振电容
华信多层全极化抑制高精度定位天线产品深度赋能“聪明的车”
电压电平转换器RS0102概述/特点/功能/应用
连接器行业2024年预测
哪些是影响铅酸蓄电池寿命的因素
5v手机充电器原理图(三款充电器电路原理图详细)
西门子EDA通过创新推进硅光子物理验证
变频器的三种电磁干扰问题及解决方法
荣耀8X和小米8哪个好