Spi RTL
Spi RTL
////////////////////////////////////////////////////////////////////////////////
//// ////
//// Project Name: SPI (Verilog) ////
//// ////
//// Module Name: spi_master ////
//// ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://opencores.com/project,spi_verilog_master_slave ////
//// ////
//// Author(s): ////
//// Santhosh G ([email protected]) ////
//// ////
//// Refer to Readme.txt for more information ////
//// ////
////////////////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2014, 2015 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
////////////////////////////////////////////////////////////////////////////////
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SPI MODE 3
CHANGE DATA @ NEGEDGE
read data @posedge
RSTB-active low asyn reset, CLK-clock, T_RB=0-rx 1-TX, mlb=0-LSB 1st 1-msb 1st
START=1- starts data transmission cdiv 0=clk/4 1=/8 2=/16 3=/32
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
module spi_master(rstb,clk,mlb,start,tdat,cdiv,din, ss,sclk,dout,done,rdata);
input rstb,clk,mlb,start;
input [7:0] tdat; //transmit data
input [1:0] cdiv; //clock divider
input din;
output reg ss;
output reg sclk;
output reg dout;
output reg done;
output reg [7:0] rdata; //received data
parameter idle=2'b00;
parameter send=2'b10;
parameter finish=2'b11;
reg [1:0] cur,nxt;
//FSM i/o
always @(start or cur or nbit or cdiv or rreg) begin
nxt=cur;
clr=0;
shift=0;//ss=0;
case(cur)
idle:begin
if(start==1)
begin
case (cdiv)
2'b00: mid=2;
2'b01: mid=4;
2'b10: mid=8;
2'b11: mid=16;
endcase
shift=1;
done=1'b0;
nxt=send;
end
end //idle
send:begin
ss=0;
if(nbit!=8)
begin shift=1;
// $display("%0d m_Design rdata=%0h din=%d",$time,rreg,din);
end
else begin
rdata=rreg;done=1'b1;
nxt=finish;
// $display("%0d m_Design rdata=%0h ss=%0d",$time,rreg,ss);
end
end//send
finish:begin
shift=0;
ss=1;
clr=1;
nxt=idle;
end
default: nxt=finish;
endcase
end//always
//state transistion
always@(negedge clk or negedge rstb) begin
if(rstb==0)
cur<=finish;
else
cur<=nxt;
end
//setup falling edge (shift dout) sample rising edge (read din)
always@(negedge clk or posedge clr) begin
if(clr==1)
begin
cnt=0;
sclk=1;
end
else begin
if(shift==1) begin
cnt=cnt+1;
if(cnt==mid) begin
sclk=~sclk;
cnt=0;
end //mid
end //shift
end //rst
end //always
endmodule
////////////////////////////////////////////////////////////////////////////////
//// ////
//// Project Name: SPI (Verilog) ////
//// ////
//// Module Name: spi_slave ////
//// ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://opencores.com/project,spi_verilog_master_slave ////
//// ////
//// Author(s): ////
//// Santhosh G ([email protected]) ////
//// ////
//// Refer to Readme.txt for more information ////
//// ////
////////////////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2014, 2015 Authors ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
////////////////////////////////////////////////////////////////////////////////
/* SPI MODE 3
CHANGE DATA (sdout) @ NEGEDGE SCK
read data (sdin) @posedge SCK
*/
module spi_slave (rstb,ten,tdata,mlb,ss,sclk,sdin, sdout,done,rdata);
input rstb,ss,sclk,sdin,ten,mlb;
input [7:0] tdata;
output sdout; //slave out master in
output reg done;
output reg [7:0] rdata;
assign sout=mlb?treg[7]:treg[0];
assign sdout=( (!ss)&&ten )?sout:1'bz; //if 1=> send data else TRI-STATE sdout
//send to sdout
always @(negedge sclk or negedge rstb)
begin
if (rstb==0)
begin treg = 8'hFF; end
else begin
if(!ss) begin
if(nb==0)
begin
treg=tdata;
//$display("%0d treg=%h",$time,tdata);
end
else begin
if(mlb==0) //LSB first, out=lsb -> right shift
begin treg = {1'b1,treg[7:1]}; end
else //MSB first, out=msb -> left shift
begin treg = {treg[6:0],1'b1};
// $display("%0d sdout=%h",$time,treg[7]);
end
end
end //!ss
end //rstb
end //always
endmodule
/*
if(mlb==0) //LSB first, out=lsb -> right shift
begin treg = {treg[7],treg[7:1]}; end
else //MSB first, out=msb -> left shift
begin treg = {treg[6:0],treg[0]}; end
*/
/*
force -freeze sim:/SPI_slave/sck 0 0, 1 {25 ns} -r 50 -can 410
run 405ns
noforce sim:/SPI_slave/sck
force -freeze sim:/SPI_slave/sck 1 0
*/