📄 spi_control.v
字号:
//----------------------------------------------------------------------------
// Project : SCP1 - Standard Communication Platform Version 1
//----------------------------------------------------------------------------
// Source : $Source: /db1/Razor_db/RAZOR_UNIVERSE/DOMAIN_01/SCP/Archive/RZ_VCS/scp1/design/arm_periph/spi/rtl/spi_control.v,v $
// Revision : $Revision: 1.3 $
// Date : $Date: 1999/09/08 07:30:34 $
// Author : $Author: coste_e $
//
//-Description----------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
module spi_control (
nreset,
clk,
operation,
start,
end_bitcnt,
end_bytecnt,
end_waitcnt,
wait_en,
fifo_full,
fifo_empty,
break,
load,
busy,
ns_rst_bitcnt,
ns_rst_bytecnt,
ns_rst_waitcnt,
stop_clk,
nwr_spi_fifo,
nrd_spi_fifo,
field,
spi_oen,
shift_ena,
stop_clkgen,
halt_clk
);
input nreset;
input clk;
input [2:0] operation;
input start;
input end_bitcnt;
input end_bytecnt;
input end_waitcnt;
input wait_en;
input fifo_full;
input fifo_empty;
input break;
output load;
output busy;
output ns_rst_bitcnt;
output ns_rst_bytecnt;
output ns_rst_waitcnt;
output stop_clk;
output nwr_spi_fifo;
output nrd_spi_fifo;
output [1:0] field;
output spi_oen;
output shift_ena;
output stop_clkgen;
output halt_clk;
reg load;
reg busy;
reg ns_rst_bitcnt;
reg ns_rst_bytecnt;
reg ns_rst_waitcnt;
reg stop_vlk;
reg nwr_spi_fifo;
reg nrd_spi_fifo;
reg [1:0] field;
reg spi_oen;
reg shift_ena;
reg stop_clk;
reg stop_clkgen;
reg halt_clk;
reg [3:0] current_state;
reg [3:0] next_state;
// PARAMETERS DEFINITION
parameter
opcode_sel = 2'b01,
addr_sel =2'b10,
data_sel =2'b11;
parameter tQ = 1; // clock to Q delay
//state machine state definition
`define RESET_STATE 4'h0
`define OPCODE_LOAD 4'h1
`define OPCODE_SHIFT 4'h2
`define ADDR_LOAD 4'h3
`define ADDR_SHIFT 4'h4
`define WAIT_STATE 4'h5
`define LOAD_DATA 4'h6
`define SHIFT_DATA_OUT 4'h7
`define WAIT_FIFO_REFIL 4'h8
`define DEPHASE 4'h9
`define SHIFT_DATA_IN 4'ha
`define UNLOAD_DATA 4'hb
`define WAIT_FIFO_UNLOAD 4'hc
`define SHIFT_DATA_IN_MSB 4'hd
`define FINISH 4'he
// glue logic used to determine next state and to
// generate the commands
always @( current_state or
start or
operation or
end_bitcnt or
wait_en or
fifo_empty or
fifo_full or
break or
end_bytecnt or
end_waitcnt
)
begin
//default value for the outputs of the state machine
load=0;
busy=1;
ns_rst_bitcnt=0;
ns_rst_waitcnt=0;
ns_rst_bytecnt=0;
stop_clk=0;
nwr_spi_fifo=1;
nrd_spi_fifo=1;
field=2'h0;
spi_oen=0;
shift_ena=0;
stop_clkgen=0;
halt_clk=0;
case(current_state)
`RESET_STATE :
begin
busy=0;
if(start)
begin
case (operation)
3'h5 : next_state=`DEPHASE;
3'h6 :
if (!fifo_empty)
next_state=`LOAD_DATA;
else
next_state=`RESET_STATE;
default : next_state=`OPCODE_LOAD;
endcase // case(operation)
end // if (start)
else
next_state=`RESET_STATE;
end // case: `RESET_STATE
`OPCODE_LOAD :
begin
load=1;
field=opcode_sel;
next_state=`OPCODE_SHIFT;
end // case: `OPCODE_LOAD
`OPCODE_SHIFT :
begin
shift_ena=1;
ns_rst_bitcnt=1;
field=opcode_sel;
if (end_bitcnt)
begin
casex ({wait_en,operation})
4'h3 : next_state=`DEPHASE;
4'h4 :
if (!fifo_empty)
next_state=`LOAD_DATA;
else
next_state=`WAIT_FIFO_REFIL;
4'bx00x : next_state=`ADDR_LOAD;
4'bx010 : next_state=`FINISH;
default : next_state=`WAIT_STATE;
endcase // case(operation)
end // if (end_bitcnt)
else
next_state=`OPCODE_SHIFT; //continue shifting not enough bit sent
end // case: `OPCODE_SHIFT
`ADDR_LOAD :
begin
load=1;
field=addr_sel;
next_state=`ADDR_SHIFT;
end // case: `ADDR_LOAD
`ADDR_SHIFT :
begin
shift_ena=1;
field=addr_sel;
ns_rst_bitcnt=1;
if (end_bitcnt)
if(wait_en)
next_state=`WAIT_STATE;
else
if (operation==3'h0)
next_state=`DEPHASE; //Read data
else
if(!fifo_empty)
next_state=`LOAD_DATA; //write data to spi device
else
next_state=`WAIT_FIFO_REFIL; //need to write data to spi device but none available
else
next_state=`ADDR_SHIFT; //continue shifting not enough bit sent
end // case: `ADDR_SHIFT
`WAIT_STATE :
begin
ns_rst_waitcnt=1;
stop_clk=1; //PAUSE SPI_CLock
if(end_waitcnt)
begin
if((operation==3'h4)||(operation==3'h1))
if(!fifo_empty)
next_state=`LOAD_DATA; //write data to spi device
else
next_state=`WAIT_FIFO_REFIL; //need to write data to spi device but none available
else
next_state=`DEPHASE;
end // if (end_waitcnt)
else
next_state=`WAIT_STATE;
end // case: `WAIT_STATE
`LOAD_DATA :
begin
load=1;
field=data_sel;
ns_rst_bytecnt=1;
nrd_spi_fifo=0;
if(!end_bytecnt)
next_state=`SHIFT_DATA_OUT;
else
next_state=`FINISH;
end // case: `LOAD_DATA
`SHIFT_DATA_OUT :
begin
field=data_sel;
ns_rst_bitcnt=1;
ns_rst_bytecnt=1;
shift_ena=1;
if (end_bitcnt)
//if(!end_bytecnt) //not finished to write the page
if(!fifo_empty) //more data to read in fifo => no need to wait for data
next_state=`LOAD_DATA;
else //fifo is empty need to wait for new data
next_state=`WAIT_FIFO_REFIL;
//else //page as been completely sent => finish
// next_state=`FINISH;
else //current byte transfer is not over
next_state=`SHIFT_DATA_OUT;
end // case: `SHIFT_DATA_OUT
`WAIT_FIFO_REFIL :
begin
field=data_sel; //added
ns_rst_bytecnt=1; //if not assereted then we loose track of how many byte sent
stop_clk=1; //PAUSE SPI_CLock
if(!break&!end_bytecnt) //user want to have "wait state" insterd during fifo refill
if(!fifo_empty) //more data to read in fifo => no need to wait for data
next_state=`LOAD_DATA;
else //fifo is empty need to wait for new data
next_state=`WAIT_FIFO_REFIL;
else
next_state=`FINISH; //communication finished due to no more data available
end // case: `WAIT_FIFO_REFIL
`DEPHASE :
begin
next_state=`SHIFT_DATA_IN;
end // case: `DEPHASE
`SHIFT_DATA_IN_MSB :
begin
spi_oen=1;
shift_ena=1;
field=data_sel;
ns_rst_bytecnt=1;
next_state=`SHIFT_DATA_IN;
end // case: `SHIFT_DATA_IN_MSB
`SHIFT_DATA_IN :
begin
spi_oen=1;
ns_rst_bytecnt=1;
field=data_sel;
ns_rst_bitcnt=1;
shift_ena=1;
if (end_bitcnt)
if(!fifo_full)
next_state=`UNLOAD_DATA;
else //fifo is full => cannot add data otherwise data loss
next_state=`WAIT_FIFO_UNLOAD;
else
next_state=`SHIFT_DATA_IN;
end // case: `SHIFT_DATA_IN
`UNLOAD_DATA :
begin
field=data_sel; //just added
spi_oen=1;
shift_ena=1;
ns_rst_bytecnt=1;
nwr_spi_fifo=0;
if(!end_bytecnt)
next_state=`SHIFT_DATA_IN;
else
next_state=`FINISH;
end // case: `UNLOAD_DATA
`WAIT_FIFO_UNLOAD :
begin
field=data_sel; //added
spi_oen=1;
ns_rst_bytecnt=1;
stop_clk=1;
if(!fifo_full)
next_state=`UNLOAD_DATA;
else
if(break)
next_state=`FINISH;
else
next_state=`WAIT_FIFO_UNLOAD;
end // case: `WAIT_FIFO_UNLOAD
`FINISH :
begin
halt_clk=1;
stop_clkgen=1;
next_state=`RESET_STATE;
end // case: `FINISH_EVEN
default : next_state = `RESET_STATE;
endcase // case(current_state)
end // always (current_state)
// sequential part of the state machine
// hopefully the synthesyser can optimize this and the
// combinational logic above to reduce the number of states
always @(negedge nreset or posedge clk)
begin
if(!nreset)
current_state <= `RESET_STATE;
else
current_state <= next_state;
end // always @ (negedge nreset or posedge clk)
endmodule // spi_contro
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -