📄 spi_clock_gen.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_clock_gen.v,v $
// Revision : $Revision: 1.3 $
// Date : $Date: 1999/09/08 06:59:28 $
// Author : $Author: coste_e $
//
//-Description----------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
module spi_clock_gen(
nreset, //async system reset
clk, //system clock
start, //start transmition signal
spi_mode, //spi mode
stop_clk, //used to assert wait state or stop the clock.
end_communication, //from main state machine when comm is over
spi_clk, //spi clock to be sent to device only
base_cs, //Chip select used to generate all devices chip selects
halt_clk,
fifo_empty,
transfer_type,
time_ext,
cs_gen_busy,
cs_done
);
`define IDLE 3'h0
`define ENA_CLK 3'h1
`define TEMPO 3'h2
`define STOP_CLK 3'h3
`define STOP_CS 3'h4
`define CS_SETUPADD 3'h5
`define CS_HOLDADD 3'h6
`define CS_IDLEADD 3'h7
input nreset;
input clk;
input start;
input [1:0] spi_mode;
input stop_clk;
input end_communication;
output spi_clk;
output base_cs;
input halt_clk;
input fifo_empty;
input [2:0] transfer_type;
input [2:0] time_ext;
output cs_gen_busy;
output cs_done;
reg spi_clk;
reg base_cs;
reg cs_gen_busy;
wire cs_done;
reg start_able;
//-----------------------------------------------------------------------------
// Parameters and constants
//-----------------------------------------------------------------------------
// All flip-flops are modeled (in RTL) with a (cp->q) delay: tcQ.
// This is to prevent potential problems with gated clocks.
parameter tcQ=1;
// wires and registers inaciation
reg spi_clk_ena;
wire inactive_level; //inactive level of spi_clk
reg [2:0] next_state;
reg [2:0] current_state;
wire tci_c;
reg load;
assign cs_done= (time_ext==3'b000)?start:tci_c&start_able;
// state machine controling the start of spi clk
// the goal of this stae machine is to have the active edge of
// spi always at the same place in time whatever the mode
// selected. Therefore for mode 1 and 3 it is nescessary to
// start the clock for mode 1 and 3 ealier than for mode 0 and 2.
// In addition we need to have the Chip select to move one spi_clock
// period (2 clk period) before the first active edge of spi_clock
// thus upon detecting the start signal we need to assert the
// base_cs signal regardless of the spi mode (thanks to the
// fact that all the active edge will be at the same point in time.
// NB. * marks the active edge
//TEMPO state is here to have all the active edge alligned in time
//whatever the given mode
//TEMPO2 is here to ensure that Chip select will remain active for
//1 spi_clk clock period (0.5 clock period due to sync between control SM
// and 0.5 due to TEMPO2)
/*
__ __ __ __ __ __
clk _| |__| |__| |__| |_| |__| |_
_____
start _/ \__________________________
__________________________
base_cs ________/
_____ ____
mode0_clk ____________________* \____*
_____ ____
mode1_clk ______________/ *_____/ *____
____________________ ____
mode2_clk *_____/ *
______________ _____ ____
mode3_clk \_____* \____*
*/
//state machine combinatioanl part
always @ (current_state or spi_mode or end_communication or
start or fifo_empty or transfer_type or tci_c)
begin
//default value of the output signals
base_cs=1;
spi_clk_ena=0;
cs_gen_busy=1;
load=0;
start_able=0;
case(current_state)
`IDLE :
begin
base_cs=0;
cs_gen_busy=0;
load=1;
if(start&((transfer_type==3'h6)&(!fifo_empty)|transfer_type!=3'h6))
begin
if(tci_c)
if((spi_mode==2'h0)||(spi_mode==2'h2))
next_state=`TEMPO;
else
next_state=`ENA_CLK;
else
next_state=`CS_SETUPADD;
end // else: !if(transfer_type==3'h6)
else
next_state=`IDLE;
end // case: `STOP_CLK
`TEMPO : next_state=`ENA_CLK;
`CS_SETUPADD :
begin
start_able=1;
if(tci_c)
if((spi_mode==2'h0)||(spi_mode==2'h2))
next_state=`TEMPO;
else
next_state=`ENA_CLK;
else
next_state=`CS_SETUPADD;
end // case: `SETUPADD
`ENA_CLK :
begin
spi_clk_ena=1;
load=1;
if(end_communication)
if((spi_mode==2'h1)|(spi_mode==2'h2))
next_state=`STOP_CLK;
else
next_state=`STOP_CLK;
else
next_state=`ENA_CLK;
end // case: `ENA_CLK
`STOP_CLK :
begin
load=1;
if (tci_c)
next_state=`STOP_CS;
else
next_state=`CS_HOLDADD;
end // case: `STOP_CLK
`CS_HOLDADD :
if (tci_c)
next_state=`STOP_CS;
else
next_state=`CS_HOLDADD;
`STOP_CS :
begin
base_cs=0;
load=1;
if(tci_c)
next_state=`IDLE;
else
next_state=`CS_IDLEADD;
end // case: `STOP_CS
`CS_IDLEADD :
begin
base_cs=0;
if(tci_c)
next_state=`IDLE;
else
next_state=`CS_IDLEADD;
end // case: `CS_IDLEADD
default : next_state=`IDLE;
endcase // case(current_state)
end // always @ (spi_mode or stop_clk or start)
//sequential part of the Sate Machine
always @(posedge clk or negedge nreset)
if(!nreset)
current_state<=`IDLE;
else
current_state<=next_state;
// acording to spi mode the inactive level of the clock should be eithe
// '0' for mode 0 and 2 and '1' for mode 1 and 3.
// inactive means the clock is not pulsing and SPI_CS inactive.
assign inactive_level = spi_mode[1];
// ff to generate glitch free spi_clk at a frequency of clk/2.
// the pause_clk signal is used to add the wait states.
// when pause_clk is asserted spi_clk is stoppped at
// - '0' level for spi mode 1 and 2
// - '1' level for spi mode 0 and 3
// this is to say on the level folowing the active edge for
// a given mode
always @(negedge nreset or posedge clk)
begin
if (~nreset)
spi_clk <= 0;
else
begin
if((~spi_clk_ena) || halt_clk)
spi_clk <= inactive_level;
else
if(stop_clk)
spi_clk <= spi_clk;
else
spi_clk <= !spi_clk;
end // else: !if(!nreset)
end // always @ (posedge clk)
spi_cs_cnt u1 (.clk(clk), // Clock Input
.cdn(nreset), // Clear Direct Not Input
.load(load), // Load Control Input
.datain(time_ext), // Data Input
.q(), // 3 bit Result
.tci(tci)); // Terminal Count Indicator
assign tci_c=tci | (time_ext==3'b000);
endmodule // spi_clock_gen
/*
spi_clock_gen(
.nreset(), //async system reset
.clk(), //system clock
.start(), //start transmition signal
.spi_mode(), //spi mode
.stop_clk(), //used to asser wait state or stop the clock
.end_communication(), //from main state machine when comm is over
.spi_clk(), // spi clock to be sent to device only
.base_cs(), //Chip select used to generate all devices chip selects
.halt_clk(),
.fifo_empty(),
.transfer_type(),
.cs_gen_busy() //block is busy cannot start a new transfer yet
);
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -