📄 cus_spi.vhd
字号:
-- File Name : CUS_SPI.Vhd
-- Autor : lin
-- CopyRight : 2411 Communication Engineering of CQ University
-- Date : 2006-3-9
-- Description : Hardware description of SPI interface module in language of VHDL.
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CUS_SPI IS
GENERIC(S_NUM:INTEGER:=1);--指定从选线数
PORT(
--INPUT
SYS_CLK :IN STD_LOGIC;--模块时钟
WR_N :IN STD_LOGIC;--写信号
RD_N :IN STD_LOGIC;--读信号
CS :IN STD_LOGIC;--片选
ADDR :IN STD_LOGIC_VECTOR(2 DOWNTO 0);
DATAIN :IN STD_LOGIC_VECTOR(7 DOWNTO 0);
--OUTPUT
INT_SPIF :OUT STD_LOGIC;--传输结束中断
DATAOUT :OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
--INOUT
MISO :INOUT STD_LOGIC;
MOSI :INOUT STD_LOGIC;
SCK :INOUT STD_LOGIC;
SS_NP :INOUT STD_LOGIC_VECTOR(S_NUM-1 DOWNTO 0));--从选
END;
ARCHITECTURE LIN OF CUS_SPI IS
SIGNAL SPIBR :STD_LOGIC_VECTOR(7 DOWNTO 0);--波特率寄存器
SIGNAL DIVIDER :STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL DIV_COUNT :STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL SPPR :STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL SPPR1 :STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SPR :STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL CLK_TEMP :STD_LOGIC;
SIGNAL BAUD_CLK :STD_LOGIC; --生成的波特时钟
-------------------------------------------------------------------
SIGNAL SLAVE_SELECT:INTEGER RANGE 0 TO 8;--从选寄存器
SIGNAL SS_N1 :STD_LOGIC;
SIGNAL SS_N :STD_LOGIC; --内部使用的从选端
SIGNAL CLK_SCK :STD_LOGIC; --内部使用的波特时钟
SIGNAL CLK_MID :STD_LOGIC; --中转时钟
SIGNAL CLK_MASK :STD_LOGIC; --CPHA='1'时空闲时钟屏蔽
SIGNAL SPTEF_A :STD_LOGIC;
SIGNAL SPTEF_B :STD_LOGIC;
SIGNAL SPIF_A :STD_LOGIC;
SIGNAL SPIF_B :STD_LOGIC;
SIGNAL XXXX :STD_LOGIC; --消除系统启动时从选为低信号
SIGNAL XXXX_A :STD_LOGIC;
SIGNAL XXXX_B :STD_LOGIC;
SIGNAL DDDD :STD_LOGIC; --防止系统启动时移位寄存器工作
SIGNAL DDDD_A :STD_LOGIC;
SIGNAL DDDD_B :STD_LOGIC;
SIGNAL SHIFTOUT_EMPTY :STD_LOGIC;
SIGNAL SHIFTOUT_EMPTY_A:STD_LOGIC;
SIGNAL SHIFTOUT_EMPTY_B:STD_LOGIC;
SIGNAL SHIFTIN_FULL :STD_LOGIC;
SIGNAL SHIFTIN_FULL_A:STD_LOGIC;
SIGNAL SHIFTIN_FULL_B:STD_LOGIC;
SIGNAL M_COUNT_EN:STD_LOGIC;
SIGNAL BAUD_CLK_CPHA:STD_LOGIC;
SIGNAL BAUD_CLK_CPHA_L:STD_LOGIC;
SIGNAL BAUD_CLK_CPHA_C:STD_LOGIC;
SIGNAL BAUD_CLK_CPHA_FALLEDGE:STD_LOGIC;
SIGNAL BAUD_CLK_CPHA_RISINGEDGE:STD_LOGIC;
SIGNAL BAUD_CLK_L:STD_LOGIC;
SIGNAL BAUD_CLK_C:STD_LOGIC;
SIGNAL BAUD_CLK_FALLEDGE:STD_LOGIC;
SIGNAL BAUD_CLK_RISINGEDGE:STD_LOGIC;
SIGNAL CLK_SCK_CPHA:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_L:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_C:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_FALLEDGE:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_RISINGEDGE:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_SS_N:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_SS_N_L:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_SS_N_C:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_SS_N_FALLEDGE:STD_LOGIC;
SIGNAL CLK_SCK_CPHA_SS_N_RISINGEDGE:STD_LOGIC;
SIGNAL BITIN :STD_LOGIC;
SIGNAL BITOUT :STD_LOGIC;
SIGNAL M_COUNT :STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SHIFT_COUNT:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SHIFT_IN :STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL SHIFT_OUT :STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL DATAIN_BUF :STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL DATAOUT_BUF :STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL SPICR1 :STD_LOGIC_VECTOR(7 DOWNTO 0);--控制寄存器1
SIGNAL SPICR2 :STD_LOGIC_VECTOR(7 DOWNTO 0);--控制寄存器2
SIGNAL SPISR :STD_LOGIC_VECTOR(7 DOWNTO 0);--状态寄存器
--位信号定义-------------------------------------------------------
SIGNAL SPIF :STD_LOGIC;--字节传输结束标志
SIGNAL SPTEF :STD_LOGIC;--数据缓冲有空间中断标志
SIGNAL MODF :STD_LOGIC;--模式错误标志
SIGNAL SPIE :STD_LOGIC;--中断允许
SIGNAL SPE :STD_LOGIC;--系统使能
SIGNAL SPTIE :STD_LOGIC;--传输中断使能
SIGNAL MSTR :STD_LOGIC;--主/从模式选择
SIGNAL CPOL :STD_LOGIC;--时钟极性选择
SIGNAL CPHA :STD_LOGIC;--时钟相位选择
SIGNAL SSOE :STD_LOGIC;--从选输出使能
SIGNAL LSBFE :STD_LOGIC;--低位先出势使能
SIGNAL MODFEN :STD_LOGIC;--模式错误使能
SIGNAL BIDIROE :STD_LOGIC;--双向模式输出使能
SIGNAL SPISWAI :STD_LOGIC;--等待模式下停止位
SIGNAL SPC0 :STD_LOGIC;--串行端口控制位(双向输出选择)
BEGIN
-----位信号分配-----------------------------------------------------
SPIE <=SPICR1(7);
SPE <=SPICR1(6);
SPTIE<=SPICR1(5);
MSTR <=SPICR1(4);
CPOL <=SPICR1(3);
CPHA <=SPICR1(2);
SSOE <=SPICR1(1);
LSBFE<=SPICR1(0);
MODFEN <=SPICR2(4);
BIDIROE<=SPICR2(3);
SPISWAI<=SPICR2(1);
SPC0 <=SPICR2(0);
SPISR<=(SPIF&'0'&SPTEF&MODF&'0'&'0'&'0'&'0');
-----时钟生成-----------------------------------------------------
SPPR <=SPIBR(6 DOWNTO 4);
SPPR1 <=('0'&SPPR)+"0001";
SPR <=SPIBR(2 DOWNTO 0);
BAUD_CLK<=CLK_TEMP;
PROCESS(SPPR1,SPR)
BEGIN
CASE SPR IS
WHEN "000"=>DIVIDER<=("00000000"&SPPR1);
WHEN "001"=>DIVIDER<=("0000000"&SPPR1&'0');
WHEN "010"=>DIVIDER<=("000000"&SPPR1&"00");
WHEN "011"=>DIVIDER<=("00000"&SPPR1&"000");
WHEN "100"=>DIVIDER<=("0000"&SPPR1&"0000");
WHEN "101"=>DIVIDER<=("000"&SPPR1&"00000");
WHEN "110"=>DIVIDER<=("00"&SPPR1&"000000");
WHEN "111"=>DIVIDER<=('0'&SPPR1&"0000000");
WHEN OTHERS=>DIVIDER<="XXXXXXXXXXXX";
END CASE;
END PROCESS;
PROCESS(SYS_CLK,DIV_COUNT,DIVIDER,CLK_TEMP)
BEGIN
IF SYS_CLK'EVENT AND SYS_CLK='1' THEN
IF DIV_COUNT>=DIVIDER-1 THEN
DIV_COUNT<="000000000000";
CLK_TEMP<=NOT CLK_TEMP;
ELSE
DIV_COUNT<=DIV_COUNT+1;
END IF;
END IF;
END PROCESS;
----内部寄存器写入/读出----------------------------------------------
PROCESS(CS,SYS_CLK,ADDR,DATAIN,SPICR1,SPICR2,SPIBR,SPISR,DATAIN_BUF,SHIFTOUT_EMPTY_B,SPTEF_A,SPIF_A)
BEGIN
IF CS='1' THEN
IF SYS_CLK'EVENT AND SYS_CLK='1' THEN
IF WR_N='0' THEN
CASE ADDR IS
WHEN "000"=>SPICR1<=DATAIN;XXXX_A<=XXXX_B;DDDD_A<=DDDD_B;
WHEN "001"=>SPICR2<=DATAIN AND "00011011";
WHEN "010"=>SPIBR<=DATAIN AND "01110111";
WHEN "100"=>SLAVE_SELECT<=CONV_INTEGER(DATAIN);
SHIFTOUT_EMPTY_A<=NOT SHIFTOUT_EMPTY_B;SHIFTIN_FULL_B<=SHIFTIN_FULL_A;
WHEN "101"=>DATAOUT_BUF<=DATAIN;SPTEF_A<=SPTEF_B;
WHEN OTHERS=>NULL;
END CASE;
ELSIF RD_N='0' THEN
CASE ADDR IS
WHEN "000"=>DATAOUT<=SPICR1;
WHEN "001"=>DATAOUT<=SPICR2;
WHEN "010"=>DATAOUT<=SPIBR;
WHEN "011"=>DATAOUT<=SPISR;
WHEN "100"=>DATAOUT<=CONV_STD_LOGIC_VECTOR(SLAVE_SELECT,8);
WHEN "101"=>DATAOUT<=DATAOUT_BUF;
WHEN "110"=>DATAOUT<=DATAIN_BUF;SPIF_B<=SPIF_A;
WHEN "111"=>DATAOUT<="00000000";
WHEN OTHERS=>NULL;
END CASE;
END IF;
END IF;
END IF;
END PROCESS;
----端口控制---------------------------------------------------------
MOSI<=BITOUT WHEN SPE='1' AND MSTR='1' ELSE
'Z';
MISO<=BITOUT WHEN SPE='1' AND MSTR='0' ELSE
'Z';
BITIN<=MOSI WHEN SPE='1' AND MSTR='0' ELSE
MISO WHEN SPE='1' AND MSTR='1' ELSE
'Z';
SS_NP<=(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=1 ELSE
(S_NUM-2=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=2 ELSE
(S_NUM-3=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=3 ELSE
(S_NUM-4=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=4 ELSE
(S_NUM-5=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=5 ELSE
(S_NUM-6=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=6 ELSE
(S_NUM-7=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=7 ELSE
(S_NUM-8=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=1 AND S_NUM=8 ELSE
(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=2 AND S_NUM=2 ELSE
(S_NUM-2=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=2 AND S_NUM=3 ELSE
(S_NUM-3=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=2 AND S_NUM=4 ELSE
(S_NUM-4=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=2 AND S_NUM=5 ELSE
(S_NUM-5=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=2 AND S_NUM=6 ELSE
(S_NUM-6=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=2 AND S_NUM=7 ELSE
(S_NUM-7=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=2 AND S_NUM=8 ELSE
(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=3 AND S_NUM=3 ELSE
(S_NUM-2=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=3 AND S_NUM=4 ELSE
(S_NUM-3=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=3 AND S_NUM=5 ELSE
(S_NUM-4=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=3 AND S_NUM=6 ELSE
(S_NUM-5=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=3 AND S_NUM=7 ELSE
(S_NUM-6=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=3 AND S_NUM=8 ELSE
(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=4 AND S_NUM=4 ELSE
(S_NUM-2=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=4 AND S_NUM=5 ELSE
(S_NUM-3=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=4 AND S_NUM=6 ELSE
(S_NUM-4=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=4 AND S_NUM=7 ELSE
(S_NUM-5=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=4 AND S_NUM=8 ELSE
(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=5 AND S_NUM=5 ELSE
(S_NUM-2=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=5 AND S_NUM=6 ELSE
(S_NUM-3=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=5 AND S_NUM=7 ELSE
(S_NUM-4=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=5 AND S_NUM=8 ELSE
(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=6 AND S_NUM=6 ELSE
(S_NUM-2=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=6 AND S_NUM=7 ELSE
(S_NUM-3=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=6 AND S_NUM=8 ELSE
(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=7 AND S_NUM=7 ELSE
(S_NUM-2=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=7 AND S_NUM=8 ELSE
(S_NUM-1=>SS_N,OTHERS=>'1') WHEN SSOE='1' AND MSTR='1' AND SLAVE_SELECT=8 AND S_NUM=8 ELSE
(OTHERS=>'Z');
SCK<=CLK_MID WHEN SSOE='1' AND MSTR='1' ELSE
'Z';
PROCESS(SPIE,SPIF)
BEGIN
IF SPIE='1' THEN
INT_SPIF<=SPIF; ------中断
ELSE
INT_SPIF<='0';
END IF;
END PROCESS;
--从选生成------------------------------------------------------------
PROCESS(MSTR,SYS_CLK,BAUD_CLK,SS_N,M_COUNT,BAUD_CLK_C,BAUD_CLK_L)
BEGIN
IF MSTR='1' THEN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -