Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
V
vSPI
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
rasky
vSPI
Commits
2ecfb943
Commit
2ecfb943
authored
Mar 07, 2012
by
Mike Lyons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switching to sampled SPI_CLK solution dependent on fast system clock rather than two clock domains
parent
94c99edd
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
596 additions
and
596 deletions
+596
-596
spiifc.v
src/spi_base/spiifc.v
+114
-437
spiifc_fastclock.v
src/spi_base/spiifc_fastclock.v
+0
-159
spiifc_twoclock.v
src/spi_base/spiifc_twoclock.v
+482
-0
No files found.
src/spi_base/spiifc.v
View file @
2ecfb943
...
...
@@ -3,7 +3,7 @@
// Company:
// Engineer:
//
// Create Date: 1
9:24:33 10/18/2011
// Create Date: 1
6:46:12 03/02/2012
// Design Name:
// Module Name: spiifc
// Project Name:
...
...
@@ -31,452 +31,129 @@ module spiifc(
rcMemData
,
rcMemWE
,
debug_out
)
;
//
// Parameters
//
parameter
AddrBits
=
12
;
// Defines
`define
CMD_READ_START 8
'
d1
`define
CMD_READ_MORE 8
'
d2
`define
CMD_WRITE_START 8
'
d3
`define
STATE_GET_CMD 8
'
d0
`define
STATE_READING 8
'
d1
`define
STATE_WRITING 8
'
d2
//
// Input/Output defs
//
input
Reset
;
input
SysClk
;
input
SPI_CLK
;
output
SPI_MISO
;
input
SPI_MOSI
;
input
SPI_SS
;
output
[
AddrBits
-
1
:
0
]
txMemAddr
;
input
[
7
:
0
]
txMemData
;
output
[
AddrBits
-
1
:
0
]
rcMemAddr
;
output
[
7
:
0
]
rcMemData
;
output
rcMemWE
;
output
[
7
:
0
]
debug_out
;
//
// Registers
//
reg
[
7
:
0
]
debug_reg
;
reg
[
7
:
0
]
rcByteReg
;
reg
rcStarted
;
reg
[
2
:
0
]
rcBitIndexReg
;
reg
[
11
:
0
]
rcMemAddrReg
;
reg
[
11
:
0
]
rcMemAddrNext
;
reg
[
7
:
0
]
rcMemDataReg
;
reg
rcMemWEReg
;
reg
ssPrev
;
reg
ssFastToggleReg
;
reg
ssSlowToggle
;
reg
ssTurnOnReg
;
reg
ssTurnOnHandled
;
reg
[
7
:
0
]
cmd
;
reg
[
7
:
0
]
stateReg
;
reg
[
11
:
0
]
txMemAddrReg
;
reg
[
2
:
0
]
txBitAddr
;
//
// Wires
//
wire
rcByteValid
;
wire
[
7
:
0
]
rcByte
;
wire
rcStarting
;
wire
[
2
:
0
]
rcBitIndex
;
wire
ssTurnOn
;
wire
ssFastToggle
;
wire
[
7
:
0
]
state
;
wire
txMemAddrReset
;
//
// Output assigns
//
assign
debug_out
=
debug_reg
;
assign
rcMemAddr
=
rcMemAddrReg
;
assign
rcMemData
=
rcMemDataReg
;
assign
rcMemWE
=
rcMemWEReg
;
assign
txMemAddrReset
=
(
rcByteValid
&&
rcByte
==
`CMD_WRITE_START
?
1
:
0
)
;
assign
txMemAddr
=
(
txMemAddrReset
?
0
:
txMemAddrReg
)
;
assign
SPI_MISO
=
txMemData
[
txBitAddr
]
;
assign
ssFastToggle
=
(
ssPrev
==
1
&&
SPI_SS
==
0
?
~
ssFastToggleReg
:
ssFastToggleReg
)
;
//
// Wire assigns
//
assign
rcByteValid
=
rcStarted
&&
rcBitIndex
==
0
;
assign
rcByte
=
{
rcByteReg
[
7
:
1
]
,
SPI_MOSI
};
assign
rcStarting
=
ssTurnOn
;
assign
rcBitIndex
=
(
rcStarting
?
3'd7
:
rcBitIndexReg
)
;
assign
ssTurnOn
=
ssSlowToggle
^
ssFastToggle
;
assign
state
=
(
rcStarting
?
`STATE_GET_CMD
:
stateReg
)
;
initial
begin
ssSlowToggle
<=
0
;
end
always
@
(
posedge
SysClk
)
begin
ssPrev
<=
SPI_SS
;
if
(
Reset
)
begin
ssTurnOnReg
<=
0
;
ssFastToggleReg
<=
0
;
end
else
begin
if
(
ssPrev
&
(
~
SPI_SS
))
begin
ssTurnOnReg
<=
1
;
ssFastToggleReg
<=
~
ssFastToggleReg
;
end
else
if
(
ssTurnOnHandled
)
begin
ssTurnOnReg
<=
0
;
end
end
end
always
@
(
posedge
SPI_CLK
)
begin
ssSlowToggle
<=
ssFastToggle
;
if
(
Reset
)
begin
// Resetting
rcByteReg
<=
8'h00
;
rcStarted
<=
0
;
rcBitIndexReg
<=
3'd7
;
ssTurnOnHandled
<=
0
;
debug_reg
<=
8'hFF
;
end
else
begin
// Not resetting
ssTurnOnHandled
<=
ssTurnOn
;
stateReg
<=
state
;
rcMemAddrReg
<=
rcMemAddrNext
;
if
(
~
SPI_SS
)
begin
rcByteReg
[
rcBitIndex
]
<=
SPI_MOSI
;
rcBitIndexReg
<=
rcBitIndex
-
3'd1
;
rcStarted
<=
1
;
// Update txBitAddr if writing out
if
(
`STATE_WRITING
==
state
)
begin
if
(
txBitAddr
==
3'd1
)
begin
txMemAddrReg
<=
txMemAddr
+
1
;
end
txBitAddr
<=
txBitAddr
-
1
;
end
end
// We've just received a byte (well, currently receiving the last bit)
if
(
rcByteValid
)
begin
// For now, just display on LEDs
debug_reg
<=
rcByte
;
if
(
`STATE_GET_CMD
==
state
)
begin
cmd
<=
rcByte
;
// Will take effect next cycle
if
(
`CMD_READ_START
==
rcByte
)
begin
rcMemAddrNext
<=
0
;
stateReg
<=
`STATE_READING
;
end
else
if
(
`CMD_READ_MORE
==
rcByte
)
begin
stateReg
<=
`STATE_READING
;
end
else
if
(
`CMD_WRITE_START
==
rcByte
)
begin
txBitAddr
<=
3'd7
;
stateReg
<=
`STATE_WRITING
;
txMemAddrReg
<=
txMemAddr
;
// Keep at 0
end
end
else
if
(
`STATE_READING
==
state
)
begin
rcMemDataReg
<=
rcByte
;
rcMemAddrNext
<=
rcMemAddr
+
1
;
rcMemWEReg
<=
1
;
end
else
if
(
`STATE_WRITING
==
state
)
begin
txBitAddr
<=
3'd7
;
stateReg
<=
`STATE_WRITING
;
end
end
else
begin
// Not a valid byte
rcMemWEReg
<=
0
;
end
// valid/valid' byte
end
// Reset/Reset'
end
/*
reg rcByte_valid;
wire rcClockBridgeEmpty;
wire readRcByte;
assign getRcByte = ~rcClockBridgeEmpty;
wire rcClockBridgeReadValid;
wire rcClockBridgeFull;
wire [7:0] rcByte;
clock_bridge recvClockBridge (
.rst(Reset), // input rst
.wr_clk(~SPI_CLK), // input wr_clk
.rd_clk(SysClk), // input rd_clk
.din(SPI_MOSI), // input [0 : 0] din
.wr_en(~SPI_SS), // input wr_en
.rd_en(getRcByte), // input rd_en
.dout(rcByte), // output [7 : 0] dout
.full(rcClockBridgeFull), // output full
.empty(rcClockBridgeEmpty), // output empty
.valid(rcClockBridgeReadValid) // output valid
)
;
always @(posedge SysClk) begin
rcByte_valid <= getRcByte;
end
wire txCmdClkBridgeEmpty;
wire txCmdClkBridgeFull;
wire [7:0] txCmd;
wire txCmdValid;
assign txCmdValid = ~txCmdClkBridgeEmpty;
wire postTxCmd;
assign postTxCmd =
fifo_8bit_to_8bit txCmdClkBridge(
.rst(Reset), // input rst
.wr_clk(SysClk), // input wr_clk
.rd_clk(SPI_CLK), // input rd_clk
.din(din), // input [7 : 0] din
.wr_en(post), // input wr_en
.rd_en(txCmdValid), // input rd_en
.dout(txCmd), // output [7 : 0] dout
.full(txCmdClkBridgeFull), // output full
.empty(txCmdClkBridgeEmpty) // output empty
);
//
// Parameters
//
parameter
AddrBits
=
12
;
//
// Defines
//
`define
CMD_READ_START 8
'
d1
`define
CMD_READ_MORE 8
'
d2
`define
CMD_WRITE_START 8
'
d3
`define
CMD_WRITE_MORE 8
'
d4
`define
CMD_INTERRUPT 8
'
d5
`define
STATE_GET_CMD 8
'
d0
`define
STATE_READING 8
'
d1
`define
STATE_WRITING 8
'
d2
`define
STATE_WRITE_INTR 8
'
d3
//
// TRANSMIT: FPGA TO PC
//
assign SPI_MISO = txMemData[bitIndex];
reg [2:0] bitIndex;
reg [AddrBits-1:0] byteAddr;
assign txMemAddr = byteAddr;
reg [7:0] debug_reg;
assign debug_out = debug_reg;
//
// Input/Outputs
//
input
Reset
;
input
SysClk
;
input
SPI_CLK
;
output
SPI_MISO
;
// outgoing (from respect of this module)
input
SPI_MOSI
;
// incoming (from respect of this module)
input
SPI_SS
;
output
[
AddrBits
-
1
:
0
]
txMemAddr
;
// outgoing data
input
[
7
:
0
]
txMemData
;
output
[
AddrBits
-
1
:
0
]
rcMemAddr
;
// incoming data
output
[
7
:
0
]
rcMemData
;
output
rcMemWE
;
output
[
7
:
0
]
debug_out
;
initial begin
debug_reg <= 8'h00;
//rcState <= 0;
end
//
// Registers
//
reg
prev_spiClk
;
// Value of SPI_CLK during last SysClk cycle
reg
prev_spiSS
;
// Value of SPI_SS during last SysClk cycle
reg
[
7
:
0
]
state_reg
;
// Register backing the 'state' wire
reg
[
7
:
0
]
rcByte_reg
;
// Register backing 'rcByte'
reg
[
2
:
0
]
rcBitIndex_reg
;
// Register backing 'rcBitIndex'
reg
[
AddrBits
-
1
:
0
]
rcMemAddr_reg
;
// Byte addr to write MOSI data to
//
// Clocked logic
//
always @(posedge SPI_CLK) begin
if (Reset) begin
bitIndex <= 3'd0;
byteAddr <= 0;
end else if (SPI_SS == 1'b0) begin
bitIndex <= bitIndex - 3'd1;
if (bitIndex == 3'd1) begin
byteAddr <= byteAddr + 1;
end
end
end
//
// RECEIVE: PC TO FPGA
//
// Detect start of receive
reg ss_prev;
wire ss_negedge;
always @(posedge SysClk) begin
ss_prev <= SPI_SS;
end
assign ss_negedge = (ss_prev == 1'b1 && SPI_SS == 1'b0 ? 1'b1 : 1'b0);
`define RC_MODE_GET_STATUS 8'd0
`define RC_MODE_GET_BUFFER 8'd1
`define RC_MODE_PUT_BUFFER 8'd2
reg [7:0] rcMode;
`define RC_STATE_CMD 8'd0
`define RC_STATE_SIZE 8'd1
`define RC_STATE_PAYLOAD 8'd2
reg [7:0] rcState;
reg [31:0] rcByteCount;
reg [31:0] rcByteSize;
reg [7:0] rcMemData_reg;
reg [AddrBits-1:0] rcMemAddr_reg;
reg rcMemWE_reg;
assign rcMemData = rcMemData_reg;
assign rcMemAddr = rcMemAddr_reg;
assign rcMemWE = rcMemWE_reg;
always @(posedge SysClk) begin
// // About to receive
// if (ss_negedge) begin
// rcBitIndex <= 3'd7;
// rcState <= `RC_STATE_CMD;
//
// debug_reg[0] <= 1;
// end
//
// // Receiving
// if (receiving) begin
// rcByte[rcBitIndex] <= SPI_MOSI;
// rcBitIndex <= rcBitIndex - 3'd1;
// end
// rcByte_valid <= (receiving && rcBitIndex == 3'd0 ? 1'b1 : 1'b0);
// Handle the complete incoming byte
if (rcByte_valid) begin
debug_reg[7:4] <= rcByte[3:0];
//
// Wires
//
wire
risingSpiClk
;
// Did the SPI_CLK rise since last SysClk cycle?
wire
validSpiBit
;
// Are the SPI MOSI/MISO bits new and valid?
reg
state
;
// Current state in the module's state machine (always @* effectively wire)
wire
rcByteValid
;
// rcByte is valid and new
wire
[
7
:
0
]
rcByte
;
// Byte received from master
wire
[
2
:
0
]
rcBitIndex
;
// Bit of rcByte to write to next
// First byte: the command
if (`RC_STATE_CMD == rcState || ss_negedge) begin
// Disable writing to the read buffer (will be left on if the prev
// cycle was writing to it)
rcMemWE_reg <= 1'b0;
// Detect new valid bit
always
@
(
posedge
SysClk
)
begin
prev_spiClk
<=
SPI_CLK
;
end
assign
risingSpiClk
=
SPI_CLK
&
(
~
prev_spiClk
)
;
assign
validSpiBit
=
risingSpiClk
&
(
~
SPI_SS
)
;
debug_reg[0] <= 1;
// Decode the SPI command
case (rcByte)
`RC_MODE_GET_STATUS: begin end // no status yet
`RC_MODE_GET_BUFFER: begin rcMode <= `RC_MODE_GET_BUFFER; rcState <= `RC_STATE_SIZE; end
`RC_MODE_PUT_BUFFER: begin rcMode <= `RC_MODE_PUT_BUFFER; rcState <= `RC_STATE_SIZE; end
endcase
// Initialize counters
rcByteCount <= 32'd0;
rcByteSize <= 32'd0;
end
// Record size (in bytes) of payload
if (`RC_STATE_SIZE == rcState) begin
debug_reg[1] <= 1;
case (rcByteCount)
32'd0: begin rcByteSize[31:24] <= rcByte; rcByteCount <= 32'd1; end
32'd1: begin rcByteSize[23:16] <= rcByte; rcByteCount <= 32'd2; end
32'd2: begin rcByteSize[15: 8] <= rcByte; rcByteCount <= 32'd3; end
32'd3: begin
rcByteSize[ 7: 0] <= rcByte;
rcByteCount <= 32'd0;
rcState <= `RC_STATE_PAYLOAD;
rcByteCount <= 32'd0;
if (`RC_MODE_GET_BUFFER == rcMode) begin
// TODO: want reset tx byte addr here probably
end
end
endcase
end
// The payload
if (rcState == `RC_STATE_PAYLOAD) begin
debug_reg[2] <= 1;
case (rcMode)
`RC_MODE_GET_BUFFER: begin
// IGNORE EVERYTHING SO STUFF CAN BE READ OUT
end
`RC_MODE_PUT_BUFFER: begin
//debug_reg[4] <= 1;
rcMemWE_reg <= 1'b1;
rcMemData_reg <= rcByte;
rcMemAddr_reg <= rcByteCount[AddrBits-1:0];
end
endcase
// Detect new SPI packet (SS dropped low)
always
@
(
posedge
SysClk
)
begin
prev_spiSS
<=
SPI_SS
;
end
assign
packetStart
=
prev_spiSS
&
(
~
SPI_SS
)
;
if (rcByteCount == rcByteSize - 1) begin
rcState <= `RC_STATE_CMD;
//debug_reg[5] <= 1;
end else begin
rcByteCount <= rcByteCount + 32'd1;
end
end
end
else begin // not valid byte
if (ss_negedge) begin
rcState <= `RC_STATE_CMD;
end
end
// Build incoming byte
always
@
(
posedge
SysClk
)
begin
if
(
validSpiBit
)
begin
rcByte_reg
[
rcBitIndex
]
<=
SPI_MOSI
;
rcBitIndex_reg
<=
(
rcBitIndex
>
0
?
rcBitIndex
-
1
:
7
)
;
end
else
begin
rcBitIndex_reg
<=
rcBitIndex
;
end
//reg [7:0] rcByteReg;
//wire [7:0] rcByte;
//assign rcByte = {rcByteReg[7:1], (SPI_SS == 1'b0 && bitIndex ==
end
assign
rcBitIndex
=
(
Reset
||
packetStart
?
7
:
rcBitIndex_reg
)
;
assign
rcByte
=
{
rcByte_reg
[
7
:
1
]
,
SPI_MOSI
};
assign
rcByteValid
=
(
validSpiBit
&&
rcBitIndex
==
0
?
1
:
0
)
;
// Incoming MOSI data buffer management
assign
rcMemAddr
=
rcMemAddr_reg
;
assign
rcMemData
=
rcByte
;
assign
rcMemWE
=
(
state
==
`STATE_READING
&&
rcByteValid
?
1
:
0
)
;
always
@
(
posedge
SysClk
)
begin
if
(
Reset
||
(
`STATE_GET_CMD
==
state
&&
rcByteValid
))
begin
rcMemAddr_reg
<=
0
;
end
else
if
(
rcMemWE
)
begin
rcMemAddr_reg
<=
rcMemAddr
+
1
;
end
else
begin
rcMemAddr_reg
<=
rcMemAddr
;
end
end
// State machine
always
@
(
*
)
begin
if
(
Reset
||
packetStart
)
begin
state
<=
`STATE_GET_CMD
;
end
else
if
(
state_reg
==
`STATE_GET_CMD
&&
rcByteValid
)
begin
state
<=
rcByte
;
end
else
begin
state
<=
state_reg
;
end
end
always
@
(
posedge
SysClk
)
begin
if
(
`STATE_GET_CMD
==
state
&&
rcByteValid
)
begin
if
(
`CMD_READ_START
==
rcByte
)
begin
state_reg
<=
`STATE_READING
;
end
else
if
(
`CMD_READ_MORE
==
rcByte
)
begin
state_reg
<=
`STATE_READING
;
end
else
if
(
`CMD_WRITE_START
==
rcByte
)
begin
state_reg
<=
`STATE_WRITING
;
end
else
if
(
`CMD_WRITE_MORE
==
rcByte
)
begin
state_reg
<=
`STATE_WRITING
;
end
else
if
(
`CMD_INTERRUPT
==
rcByte
)
begin
// TODO: NYI
end
end
else
begin
state_reg
<=
state
;
end
end
// //
// // Receive (GPU to SPI)
// //
// reg SPI_SS_prev_cycle;
//
// // This is the register backing rcByteId. It is always one cycle
// // behind the true value of rcByteId, which we have to do a little
// // work to get instantaneously correct using wire logic.
// reg [31:0] rcByteIdPrev;
// wire [31:0] rcByteId;
// assign rcByteId = (SPI_SS_prev_cycle == 1 && SPI_SS == 0 ? 32'd0 : 32'd1 + rcByteIdPrev);
//
// // 1 if we're receiving from GPC, 0 if not.
// wire isRecv;
// assign isRecv = ~SPI_SS;
//
// // Bits to Byte aggregator
// reg [2:0] rcBitId;
// reg [7:0] rcByte;
//
//
// reg [31:0] rcSizeBytes;
//
// always @(posedge SPI_CLK) begin
// if (1 == isRecv) begin
// case (rcByteId)
// 0: rcSizeBytes[ 7: 0] <=
// end
//
// // Update registers for next cycle
// SPI_SS_prev_cycle <= SPI_SS;
// rcByteId <= rcByteIdPrev;
// end
*/
endmodule
src/spi_base/spiifc_fastclock.v
deleted
100644 → 0
View file @
94c99edd
`timescale
1
ns
/
1
ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 16:46:12 03/02/2012
// Design Name:
// Module Name: spiifc
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module
spiifc
(
Reset
,
SysClk
,
SPI_CLK
,
SPI_MISO
,
SPI_MOSI
,
SPI_SS
,
txMemAddr
,
txMemData
,
rcMemAddr
,
rcMemData
,
rcMemWE
,
debug_out
)
;
//
// Parameters
//
parameter
AddrBits
=
12
;
//
// Defines
//
`define
CMD_READ_START 8
'
d1
`define
CMD_READ_MORE 8
'
d2
`define
CMD_WRITE_START 8
'
d3
`define
CMD_WRITE_MORE 8
'
d4
`define
CMD_INTERRUPT 8
'
d5
`define
STATE_GET_CMD 8
'
d0
`define
STATE_READING 8
'
d1
`define
STATE_WRITING 8
'
d2
`define
STATE_WRITE_INTR 8
'
d3
//
// Input/Outputs
//
input
Reset
;
input
SysClk
;
input
SPI_CLK
;
output
SPI_MISO
;
// outgoing (from respect of this module)
input
SPI_MOSI
;
// incoming (from respect of this module)
input
SPI_SS
;
output
[
AddrBits
-
1
:
0
]
txMemAddr
;
// outgoing data
input
[
7
:
0
]
txMemData
;
output
[
AddrBits
-
1
:
0
]
rcMemAddr
;
// incoming data
output
[
7
:
0
]
rcMemData
;
output
rcMemWE
;
output
[
7
:
0
]
debug_out
;
//
// Registers
//
reg
prev_spiClk
;
// Value of SPI_CLK during last SysClk cycle
reg
prev_spiSS
;
// Value of SPI_SS during last SysClk cycle
reg
[
7
:
0
]
state_reg
;
// Register backing the 'state' wire
reg
[
7
:
0
]
rcByte_reg
;
// Register backing 'rcByte'
reg
[
2
:
0
]
rcBitIndex_reg
;
// Register backing 'rcBitIndex'
reg
[
AddrBits
-
1
:
0
]
rcMemAddr_reg
;
// Byte addr to write MOSI data to
//
// Wires
//
wire
risingSpiClk
;
// Did the SPI_CLK rise since last SysClk cycle?
wire
validSpiBit
;
// Are the SPI MOSI/MISO bits new and valid?
reg
state
;
// Current state in the module's state machine (always @* effectively wire)
wire
rcByteValid
;
// rcByte is valid and new
wire
[
7
:
0
]
rcByte
;
// Byte received from master
wire
[
2
:
0
]
rcBitIndex
;
// Bit of rcByte to write to next
// Detect new valid bit
always
@
(
posedge
SysClk
)
begin
prev_spiClk
<=
SPI_CLK
;
end
assign
risingSpiClk
=
SPI_CLK
&
(
~
prev_spiClk
)
;
assign
validSpiBit
=
risingSpiClk
&
(
~
SPI_SS
)
;
// Detect new SPI packet (SS dropped low)
always
@
(
posedge
SysClk
)
begin
prev_spiSS
<=
SPI_SS
;
end
assign
packetStart
=
prev_spiSS
&
(
~
SPI_SS
)
;
// Build incoming byte
always
@
(
posedge
SysClk
)
begin
if
(
validSpiBit
)
begin
rcByte_reg
[
rcBitIndex
]
<=
SPI_MOSI
;
rcBitIndex_reg
<=
(
rcBitIndex
>
0
?
rcBitIndex
-
1
:
7
)
;
end
else
begin
rcBitIndex_reg
<=
rcBitIndex
;
end
end
assign
rcBitIndex
=
(
Reset
||
packetStart
?
7
:
rcBitIndex_reg
)
;
assign
rcByte
=
{
rcByte_reg
[
7
:
1
]
,
SPI_MOSI
};
assign
rcByteValid
=
(
validSpiBit
&&
rcBitIndex
==
0
?
1
:
0
)
;
// Incoming MOSI data buffer management
assign
rcMemAddr
=
rcMemAddr_reg
;
assign
rcMemData
=
rcByte
;
assign
rcMemWE
=
(
state
==
`STATE_READING
&&
rcByteValid
?
1
:
0
)
;
always
@
(
posedge
SysClk
)
begin
if
(
Reset
||
(
`STATE_GET_CMD
==
state
&&
rcByteValid
))
begin
rcMemAddr_reg
<=
0
;
end
else
if
(
rcMemWE
)
begin
rcMemAddr_reg
<=
rcMemAddr
+
1
;
end
else
begin
rcMemAddr_reg
<=
rcMemAddr
;
end
end
// State machine
always
@
(
*
)
begin
if
(
Reset
||
packetStart
)
begin
state
<=
`STATE_GET_CMD
;
end
else
if
(
state_reg
==
`STATE_GET_CMD
&&
rcByteValid
)
begin
state
<=
rcByte
;
end
else
begin
state
<=
state_reg
;
end
end
always
@
(
posedge
SysClk
)
begin
if
(
`STATE_GET_CMD
==
state
&&
rcByteValid
)
begin
if
(
`CMD_READ_START
==
rcByte
)
begin
state_reg
<=
`STATE_READING
;
end
else
if
(
`CMD_READ_MORE
==
rcByte
)
begin
state_reg
<=
`STATE_READING
;
end
else
if
(
`CMD_WRITE_START
==
rcByte
)
begin
state_reg
<=
`STATE_WRITING
;
end
else
if
(
`CMD_WRITE_MORE
==
rcByte
)
begin
state_reg
<=
`STATE_WRITING
;
end
else
if
(
`CMD_INTERRUPT
==
rcByte
)
begin
// TODO: NYI
end
end
else
begin
state_reg
<=
state
;
end
end
endmodule
src/spi_base/spiifc_twoclock.v
0 → 100644
View file @
2ecfb943
`timescale
1
ns
/
1
ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 19:24:33 10/18/2011
// Design Name:
// Module Name: spiifc
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module
spiifc
(
Reset
,
SysClk
,
SPI_CLK
,
SPI_MISO
,
SPI_MOSI
,
SPI_SS
,
txMemAddr
,
txMemData
,
rcMemAddr
,
rcMemData
,
rcMemWE
,
debug_out
)
;
//
// Parameters
//
parameter
AddrBits
=
12
;
// Defines
`define
CMD_READ_START 8
'
d1
`define
CMD_READ_MORE 8
'
d2
`define
CMD_WRITE_START 8
'
d3
`define
STATE_GET_CMD 8
'
d0
`define
STATE_READING 8
'
d1
`define
STATE_WRITING 8
'
d2
//
// Input/Output defs
//
input
Reset
;
input
SysClk
;
input
SPI_CLK
;
output
SPI_MISO
;
input
SPI_MOSI
;
input
SPI_SS
;
output
[
AddrBits
-
1
:
0
]
txMemAddr
;
input
[
7
:
0
]
txMemData
;
output
[
AddrBits
-
1
:
0
]
rcMemAddr
;
output
[
7
:
0
]
rcMemData
;
output
rcMemWE
;
output
[
7
:
0
]
debug_out
;
//
// Registers
//
reg
[
7
:
0
]
debug_reg
;
reg
[
7
:
0
]
rcByteReg
;
reg
rcStarted
;
reg
[
2
:
0
]
rcBitIndexReg
;
reg
[
11
:
0
]
rcMemAddrReg
;
reg
[
11
:
0
]
rcMemAddrNext
;
reg
[
7
:
0
]
rcMemDataReg
;
reg
rcMemWEReg
;
reg
ssPrev
;
reg
ssFastToggleReg
;
reg
ssSlowToggle
;
reg
ssTurnOnReg
;
reg
ssTurnOnHandled
;
reg
[
7
:
0
]
cmd
;
reg
[
7
:
0
]
stateReg
;
reg
[
11
:
0
]
txMemAddrReg
;
reg
[
2
:
0
]
txBitAddr
;
//
// Wires
//
wire
rcByteValid
;
wire
[
7
:
0
]
rcByte
;
wire
rcStarting
;
wire
[
2
:
0
]
rcBitIndex
;
wire
ssTurnOn
;
wire
ssFastToggle
;
wire
[
7
:
0
]
state
;
wire
txMemAddrReset
;
//
// Output assigns
//
assign
debug_out
=
debug_reg
;
assign
rcMemAddr
=
rcMemAddrReg
;
assign
rcMemData
=
rcMemDataReg
;
assign
rcMemWE
=
rcMemWEReg
;
assign
txMemAddrReset
=
(
rcByteValid
&&
rcByte
==
`CMD_WRITE_START
?
1
:
0
)
;
assign
txMemAddr
=
(
txMemAddrReset
?
0
:
txMemAddrReg
)
;
assign
SPI_MISO
=
txMemData
[
txBitAddr
]
;
assign
ssFastToggle
=
(
ssPrev
==
1
&&
SPI_SS
==
0
?
~
ssFastToggleReg
:
ssFastToggleReg
)
;
//
// Wire assigns
//
assign
rcByteValid
=
rcStarted
&&
rcBitIndex
==
0
;
assign
rcByte
=
{
rcByteReg
[
7
:
1
]
,
SPI_MOSI
};
assign
rcStarting
=
ssTurnOn
;
assign
rcBitIndex
=
(
rcStarting
?
3'd7
:
rcBitIndexReg
)
;
assign
ssTurnOn
=
ssSlowToggle
^
ssFastToggle
;
assign
state
=
(
rcStarting
?
`STATE_GET_CMD
:
stateReg
)
;
initial
begin
ssSlowToggle
<=
0
;
end
always
@
(
posedge
SysClk
)
begin
ssPrev
<=
SPI_SS
;
if
(
Reset
)
begin
ssTurnOnReg
<=
0
;
ssFastToggleReg
<=
0
;
end
else
begin
if
(
ssPrev
&
(
~
SPI_SS
))
begin
ssTurnOnReg
<=
1
;
ssFastToggleReg
<=
~
ssFastToggleReg
;
end
else
if
(
ssTurnOnHandled
)
begin
ssTurnOnReg
<=
0
;
end
end
end
always
@
(
posedge
SPI_CLK
)
begin
ssSlowToggle
<=
ssFastToggle
;
if
(
Reset
)
begin
// Resetting
rcByteReg
<=
8'h00
;
rcStarted
<=
0
;
rcBitIndexReg
<=
3'd7
;
ssTurnOnHandled
<=
0
;
debug_reg
<=
8'hFF
;
end
else
begin
// Not resetting
ssTurnOnHandled
<=
ssTurnOn
;
stateReg
<=
state
;
rcMemAddrReg
<=
rcMemAddrNext
;
if
(
~
SPI_SS
)
begin
rcByteReg
[
rcBitIndex
]
<=
SPI_MOSI
;
rcBitIndexReg
<=
rcBitIndex
-
3'd1
;
rcStarted
<=
1
;
// Update txBitAddr if writing out
if
(
`STATE_WRITING
==
state
)
begin
if
(
txBitAddr
==
3'd1
)
begin
txMemAddrReg
<=
txMemAddr
+
1
;
end
txBitAddr
<=
txBitAddr
-
1
;
end
end
// We've just received a byte (well, currently receiving the last bit)
if
(
rcByteValid
)
begin
// For now, just display on LEDs
debug_reg
<=
rcByte
;
if
(
`STATE_GET_CMD
==
state
)
begin
cmd
<=
rcByte
;
// Will take effect next cycle
if
(
`CMD_READ_START
==
rcByte
)
begin
rcMemAddrNext
<=
0
;
stateReg
<=
`STATE_READING
;
end
else
if
(
`CMD_READ_MORE
==
rcByte
)
begin
stateReg
<=
`STATE_READING
;
end
else
if
(
`CMD_WRITE_START
==
rcByte
)
begin
txBitAddr
<=
3'd7
;
stateReg
<=
`STATE_WRITING
;
txMemAddrReg
<=
txMemAddr
;
// Keep at 0
end
end
else
if
(
`STATE_READING
==
state
)
begin
rcMemDataReg
<=
rcByte
;
rcMemAddrNext
<=
rcMemAddr
+
1
;
rcMemWEReg
<=
1
;
end
else
if
(
`STATE_WRITING
==
state
)
begin
txBitAddr
<=
3'd7
;
stateReg
<=
`STATE_WRITING
;
end
end
else
begin
// Not a valid byte
rcMemWEReg
<=
0
;
end
// valid/valid' byte
end
// Reset/Reset'
end
/*
reg rcByte_valid;
wire rcClockBridgeEmpty;
wire readRcByte;
assign getRcByte = ~rcClockBridgeEmpty;
wire rcClockBridgeReadValid;
wire rcClockBridgeFull;
wire [7:0] rcByte;
clock_bridge recvClockBridge (
.rst(Reset), // input rst
.wr_clk(~SPI_CLK), // input wr_clk
.rd_clk(SysClk), // input rd_clk
.din(SPI_MOSI), // input [0 : 0] din
.wr_en(~SPI_SS), // input wr_en
.rd_en(getRcByte), // input rd_en
.dout(rcByte), // output [7 : 0] dout
.full(rcClockBridgeFull), // output full
.empty(rcClockBridgeEmpty), // output empty
.valid(rcClockBridgeReadValid) // output valid
);
always @(posedge SysClk) begin
rcByte_valid <= getRcByte;
end
wire txCmdClkBridgeEmpty;
wire txCmdClkBridgeFull;
wire [7:0] txCmd;
wire txCmdValid;
assign txCmdValid = ~txCmdClkBridgeEmpty;
wire postTxCmd;
assign postTxCmd =
fifo_8bit_to_8bit txCmdClkBridge(
.rst(Reset), // input rst
.wr_clk(SysClk), // input wr_clk
.rd_clk(SPI_CLK), // input rd_clk
.din(din), // input [7 : 0] din
.wr_en(post), // input wr_en
.rd_en(txCmdValid), // input rd_en
.dout(txCmd), // output [7 : 0] dout
.full(txCmdClkBridgeFull), // output full
.empty(txCmdClkBridgeEmpty) // output empty
);
//
// TRANSMIT: FPGA TO PC
//
assign SPI_MISO = txMemData[bitIndex];
reg [2:0] bitIndex;
reg [AddrBits-1:0] byteAddr;
assign txMemAddr = byteAddr;
reg [7:0] debug_reg;
assign debug_out = debug_reg;
initial begin
debug_reg <= 8'h00;
//rcState <= 0;
end
//
// Clocked logic
//
always @(posedge SPI_CLK) begin
if (Reset) begin
bitIndex <= 3'd0;
byteAddr <= 0;
end else if (SPI_SS == 1'b0) begin
bitIndex <= bitIndex - 3'd1;
if (bitIndex == 3'd1) begin
byteAddr <= byteAddr + 1;
end
end
end
//
// RECEIVE: PC TO FPGA
//
// Detect start of receive
reg ss_prev;
wire ss_negedge;
always @(posedge SysClk) begin
ss_prev <= SPI_SS;
end
assign ss_negedge = (ss_prev == 1'b1 && SPI_SS == 1'b0 ? 1'b1 : 1'b0);
`define RC_MODE_GET_STATUS 8'd0
`define RC_MODE_GET_BUFFER 8'd1
`define RC_MODE_PUT_BUFFER 8'd2
reg [7:0] rcMode;
`define RC_STATE_CMD 8'd0
`define RC_STATE_SIZE 8'd1
`define RC_STATE_PAYLOAD 8'd2
reg [7:0] rcState;
reg [31:0] rcByteCount;
reg [31:0] rcByteSize;
reg [7:0] rcMemData_reg;
reg [AddrBits-1:0] rcMemAddr_reg;
reg rcMemWE_reg;
assign rcMemData = rcMemData_reg;
assign rcMemAddr = rcMemAddr_reg;
assign rcMemWE = rcMemWE_reg;
always @(posedge SysClk) begin
// // About to receive
// if (ss_negedge) begin
// rcBitIndex <= 3'd7;
// rcState <= `RC_STATE_CMD;
//
// debug_reg[0] <= 1;
// end
//
// // Receiving
// if (receiving) begin
// rcByte[rcBitIndex] <= SPI_MOSI;
// rcBitIndex <= rcBitIndex - 3'd1;
// end
// rcByte_valid <= (receiving && rcBitIndex == 3'd0 ? 1'b1 : 1'b0);
// Handle the complete incoming byte
if (rcByte_valid) begin
debug_reg[7:4] <= rcByte[3:0];
// First byte: the command
if (`RC_STATE_CMD == rcState || ss_negedge) begin
// Disable writing to the read buffer (will be left on if the prev
// cycle was writing to it)
rcMemWE_reg <= 1'b0;
debug_reg[0] <= 1;
// Decode the SPI command
case (rcByte)
`RC_MODE_GET_STATUS: begin end // no status yet
`RC_MODE_GET_BUFFER: begin rcMode <= `RC_MODE_GET_BUFFER; rcState <= `RC_STATE_SIZE; end
`RC_MODE_PUT_BUFFER: begin rcMode <= `RC_MODE_PUT_BUFFER; rcState <= `RC_STATE_SIZE; end
endcase
// Initialize counters
rcByteCount <= 32'd0;
rcByteSize <= 32'd0;
end
// Record size (in bytes) of payload
if (`RC_STATE_SIZE == rcState) begin
debug_reg[1] <= 1;
case (rcByteCount)
32'd0: begin rcByteSize[31:24] <= rcByte; rcByteCount <= 32'd1; end
32'd1: begin rcByteSize[23:16] <= rcByte; rcByteCount <= 32'd2; end
32'd2: begin rcByteSize[15: 8] <= rcByte; rcByteCount <= 32'd3; end
32'd3: begin
rcByteSize[ 7: 0] <= rcByte;
rcByteCount <= 32'd0;
rcState <= `RC_STATE_PAYLOAD;
rcByteCount <= 32'd0;
if (`RC_MODE_GET_BUFFER == rcMode) begin
// TODO: want reset tx byte addr here probably
end
end
endcase
end
// The payload
if (rcState == `RC_STATE_PAYLOAD) begin
debug_reg[2] <= 1;
case (rcMode)
`RC_MODE_GET_BUFFER: begin
// IGNORE EVERYTHING SO STUFF CAN BE READ OUT
end
`RC_MODE_PUT_BUFFER: begin
//debug_reg[4] <= 1;
rcMemWE_reg <= 1'b1;
rcMemData_reg <= rcByte;
rcMemAddr_reg <= rcByteCount[AddrBits-1:0];
end
endcase
if (rcByteCount == rcByteSize - 1) begin
rcState <= `RC_STATE_CMD;
//debug_reg[5] <= 1;
end else begin
rcByteCount <= rcByteCount + 32'd1;
end
end
end
else begin // not valid byte
if (ss_negedge) begin
rcState <= `RC_STATE_CMD;
end
end
end
//reg [7:0] rcByteReg;
//wire [7:0] rcByte;
//assign rcByte = {rcByteReg[7:1], (SPI_SS == 1'b0 && bitIndex ==
// //
// // Receive (GPU to SPI)
// //
// reg SPI_SS_prev_cycle;
//
// // This is the register backing rcByteId. It is always one cycle
// // behind the true value of rcByteId, which we have to do a little
// // work to get instantaneously correct using wire logic.
// reg [31:0] rcByteIdPrev;
// wire [31:0] rcByteId;
// assign rcByteId = (SPI_SS_prev_cycle == 1 && SPI_SS == 0 ? 32'd0 : 32'd1 + rcByteIdPrev);
//
// // 1 if we're receiving from GPC, 0 if not.
// wire isRecv;
// assign isRecv = ~SPI_SS;
//
// // Bits to Byte aggregator
// reg [2:0] rcBitId;
// reg [7:0] rcByte;
//
//
// reg [31:0] rcSizeBytes;
//
// always @(posedge SPI_CLK) begin
// if (1 == isRecv) begin
// case (rcByteId)
// 0: rcSizeBytes[ 7: 0] <=
// end
//
// // Update registers for next cycle
// SPI_SS_prev_cycle <= SPI_SS;
// rcByteId <= rcByteIdPrev;
// end
*/
endmodule
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment