// author: jiajia.pi
// version: v1.1
// last modify date: 2014/08/19 change ready assert timing
// clk_div range: 4~255 divsion of clk
// only mode 0 and mode 3 support
// MSB send first and LSB send last
module spi_master(
clk,// global clock
reset_n, // global async low reset
clk_div, // spi clock divider
wr,// spi write
wrdata,// spi write data, 8bit
rddata,// spi recieve data, 8bit, valid when ready assert
sck,// spi master clock out
sdi,// spi master data in (MISO)
sdo,// spi master data out (MOSI)
ready// spi master ready (idle)
)
input clk
input reset_n
input [7:0]clk_div
input wr
input [7:0]wrdata
output [7:0]rddata
output sck
output sdo
output ready
input sdi
parameter clock_polarity = 1 // '0': mode 0, sck=0 when idle'1': mode 3, sck=1 when idle
reg [7:0]dat
reg rsck
reg [7:0]cnt
reg busy
reg [3:0]state
reg [7:0]rddata
wire sdo = dat[7]
wire sck = busy? rsck:clock_polarity
wire sdi_tick = (cnt==clk_div>>1)/*synthesis keep*/
wire sdo_tick = (cnt==clk_div)/*synthesis keep*/
wire ready = !(wr||busy)
always @(posedge clk or negedge reset_n)
if(!reset_n)
cnt <= 0
else if(cnt<clk_div &&busy)
cnt <= cnt + 1
else
cnt <= 1
always @(posedge clk or negedge reset_n)
if(!reset_n)
rsck <= 0
else if(sdi_tick)
rsck <= 1
else if(sdo_tick)
rsck <= 0
always @(posedge clk or negedge reset_n)
if(!reset_n)
busy <= 0
else if(wr &&!busy)
busy <= 1
else if(state==8 &&sdo_tick)
busy <= 0
always@(posedge clk or negedge reset_n)
if(!reset_n)
state <= 0
else if(wr &&!busy)
state <= 1
else if(state==8 &&sdo_tick)
state <= 0
else if(sdo_tick)
state <= state + 1
always @(posedge clk or negedge reset_n)
if(!reset_n)
dat <= 0
else if(wr &&!busy)
dat <= wrdata
else if(sdo_tick &&busy &&state!=8)
dat <= dat<<1
always @(posedge clk or negedge reset_n)
if(!reset_n)
rddata <= 0
else if(sdi_tick &&busy)
rddata <= {rddata[6:0],sdi}
endmodule
1. FPGA与MCU,DSP,ARM等区别MCU等是属于软件编程,程序是顺序执行,即使像DSP有多级流水线,但是程序总体还是顺序的。
FPGA是属于硬件编程,程序是并行执行的,可以有多个进程,同时执行不同的功能。
2. FPGA实现UART,IIC,SPI。
如果是简单的应用(比如说不用校验等等),完全可以自己写,例如下面的程序,VHDL写的,既可以作为UART发送程序(改改就是接收),也可以做SPI发送或者接收(加一个时钟)。
如果需要较完善的功能的话,建议使用IP核,往上有很多免费的UART,IIC,SPI等接口的IP核,功能及代码都给你写好了的,提供输入输出接口,方便应用。
process(Clk)
variable temp : integer range 0 to 7
begin
if Clk'event and Clk='1' then
if Reset = '0' then
TxD <= '1'
BitCnt <= "00000"
SL<='1'
TReg<=(others=>'0')
temp:=0
elsif Load = '0' and temp=0 then
TxD <= '1'
SL<='1'
BitCnt <= "00000"
temp:=0
elsif Load='1' and temp=0 then
temp:=1
elsif temp=1 then
case BitCnt is
when "00000" =>
TReg <= Addr_Data
SL<='0'
TxD <= '0'
BitCnt <= BitCnt + 1
temp:=1
when "00001" | "00010" | "00011" |
"00100" | "00101" | "00110" |
"00111" | "01000" | "01001" |
"01010" | "01011" | "01100" |
"01101" | "01110" | "01111" =>
TxD <= TReg(0)
TReg <= '1' &TReg(14 downto 1)
BitCnt <= BitCnt + 1
temp:=1
when "10000" =>
SL<='1'
TxD <= '1'
TReg <= '1' &TReg(14 downto 1)
BitCnt <= "00000"
temp:=0
when others =>NULL
end case
ELSE
TXD<='1'
SL<='1'
end if
end if
end process
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)