OpenCores
URL https://opencores.org/ocsvn/vspi/vspi/trunk

Subversion Repositories vspi

[/] [vspi/] [trunk/] [src/] [spi_base/] [spiifc.v] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 mjlyons
`timescale 1ns / 1ps
2
//////////////////////////////////////////////////////////////////////////////////
3
// Company: 
4
// Engineer: 
5
// 
6
// Create Date:    16:46:12 03/02/2012 
7
// Design Name: 
8
// Module Name:    spiifc 
9
// Project Name: 
10
// Target Devices: 
11
// Tool versions: 
12
// Description: 
13
//
14
// Dependencies: 
15
//
16
// Revision: 
17
// Revision 0.01 - File Created
18
// Additional Comments: 
19
//
20
//////////////////////////////////////////////////////////////////////////////////
21
module spiifc(
22
  Reset,
23
  SysClk,
24
  SPI_CLK,
25
  SPI_MISO,
26
  SPI_MOSI,
27
  SPI_SS,
28
  txMemAddr,
29
  txMemData,
30
  rcMemAddr,
31
  rcMemData,
32
  rcMemWE,
33
  regAddr,
34
  regReadData,
35
  regWriteEn,
36
  regWriteData,
37
  debug_out
38
);
39
 
40
//
41
// Parameters
42
//
43
parameter AddrBits = 12;
44
parameter RegAddrBits = 4;
45
 
46
//
47
// Defines
48
//
49
`define CMD_READ_START    8'd1
50
`define CMD_READ_MORE     8'd2
51
`define CMD_WRITE_START   8'd3
52
`define CMD_WRITE_MORE    8'd4
53
`define CMD_INTERRUPT     8'd5
54
 
55
`define CMD_REG_BASE      8'd128
56
`define CMD_REG_BIT       7
57
`define CMD_REG_WE_BIT    6
58
`define CMD_REG_ID_MASK   8'h3F
59
 
60
`define STATE_GET_CMD     8'd0
61
`define STATE_READING     8'd1
62
`define STATE_WRITING     8'd2
63
`define STATE_WRITE_INTR  8'd3
64
`define STATE_BUILD_WORD  8'd4
65
`define STATE_SEND_WORD   8'd5
66
 
67
//
68
// Input/Outputs
69
//
70
input                    Reset;
71
input                    SysClk;
72
 
73
input                    SPI_CLK;
74
output                   SPI_MISO;     // outgoing (from respect of this module)
75
input                    SPI_MOSI;     // incoming (from respect of this module)
76
input                    SPI_SS;
77
 
78
output [AddrBits-1:0]    txMemAddr;    // outgoing data
79
input           [7:0]    txMemData;
80
output [AddrBits-1:0]    rcMemAddr;    // incoming data
81
output          [7:0]    rcMemData;
82
output                   rcMemWE;
83
 
84
output [RegAddrBits-1:0] regAddr;       // Register read address (combinational)
85
input             [31:0] regReadData;   // Result of register read
86
output                   regWriteEn;    // Enable write to register, otherwise read
87
output            [31:0] regWriteData;  // Register write data
88
 
89
 
90
output          [7:0] debug_out;
91
 
92
//
93
// Registers
94
//
95
reg                   SPI_CLK_reg;    // Stabalized version of SPI_CLK
96
reg                   SPI_SS_reg;     // Stabalized version of SPI_SS
97
reg                   SPI_MOSI_reg;   // Stabalized version of SPI_MOSI
98
 
99
reg                   prev_spiClk;    // Value of SPI_CLK during last SysClk cycle
100
reg                   prev_spiSS;     // Value of SPI_SS during last SysClk cycle
101
reg             [7:0] state_reg;      // Register backing the 'state' wire
102
reg             [7:0] rcByte_reg;     // Register backing 'rcByte'
103
reg             [2:0] rcBitIndex_reg; // Register backing 'rcBitIndex'
104
reg    [AddrBits-1:0] rcMemAddr_reg;  // Byte addr to write MOSI data to
105
reg             [7:0] debug_reg;      // register backing debug_out signal
106
reg             [2:0] txBitIndex_reg; // Register backing txBitIndex
107
reg    [AddrBits-1:0] txMemAddr_reg;  // Register backing txAddr
108
 
109
reg             [7:0] command;        // Command being handled
110
reg            [31:0] rcWord;         // Incoming word being built
111
reg             [1:0] rcWordByteId;   // Which byte the in the rcWord to map to
112
reg [RegAddrBits-1:0] regAddr_reg;    // Address of register to read/write to
113
 
114
//
115
// Wires
116
//
117
wire                  risingSpiClk;       // Did the SPI_CLK rise since last SysClk cycle?
118
wire                  validSpiBit;        // Are the SPI MOSI/MISO bits new and valid?
119
reg             [7:0] state;              // Current state in the module's state machine (always @* effectively wire)
120
wire                  rcByteValid;        // rcByte is valid and new
121
wire            [7:0] rcByte;             // Byte received from master
122
wire            [2:0] rcBitIndex;         // Bit of rcByte to write to next
123
reg             [2:0] txBitIndex;         // bit of txByte to send to master next
124
reg    [AddrBits-1:0] txMemAddr_oreg;     // Wirereg piped to txMemAddr output
125
reg             [7:0] regReadByte_oreg;   // Which byte of the reg word we're reading out master
126
 
127
// Save buffered SPI inputs
128
always @(posedge SysClk) begin
129
  SPI_CLK_reg <= SPI_CLK;
130
  SPI_SS_reg <= SPI_SS;
131
  SPI_MOSI_reg <= SPI_MOSI;
132
end
133
 
134
// Detect new valid bit
135
always @(posedge SysClk) begin
136
  prev_spiClk <= SPI_CLK_reg;
137
end
138
assign risingSpiClk = SPI_CLK_reg & (~prev_spiClk);
139
assign validSpiBit = risingSpiClk & (~SPI_SS_reg);
140
 
141
// Detect new SPI packet (SS dropped low)
142
always @(posedge SysClk) begin
143
  prev_spiSS <= SPI_SS_reg;
144
end
145
assign packetStart = prev_spiSS & (~SPI_SS_reg);
146
 
147
// Build incoming byte
148
always @(posedge SysClk) begin
149
  if (validSpiBit) begin
150
    rcByte_reg[rcBitIndex] <= SPI_MOSI_reg;
151
    rcBitIndex_reg <= (rcBitIndex > 0 ? rcBitIndex - 1 : 7);
152
  end else begin
153
    rcBitIndex_reg <= rcBitIndex;
154
  end
155
end
156
assign rcBitIndex = (Reset || packetStart ? 7 : rcBitIndex_reg);
157
assign rcByte = {rcByte_reg[7:1], SPI_MOSI_reg};
158
assign rcByteValid = (validSpiBit && rcBitIndex == 0 ? 1 : 0);
159
 
160
// Incoming MOSI data buffer management
161
assign rcMemAddr = rcMemAddr_reg;
162
assign rcMemData = rcByte;
163
assign rcMemWE = (state == `STATE_READING && rcByteValid ? 1 : 0);
164
always @(posedge SysClk) begin
165
  if (Reset || (`STATE_GET_CMD == state && rcByteValid)) begin
166
    rcMemAddr_reg <= 0;
167
  end else if (rcMemWE) begin
168
    rcMemAddr_reg <= rcMemAddr + 1;
169
  end else begin
170
    rcMemAddr_reg <= rcMemAddr;
171
  end
172
end
173
 
174
// Outgoing MISO data buffer management
175
always @(*) begin
176
  if (Reset || (state == `STATE_GET_CMD && rcByteValid &&
177
                  (rcByte == `CMD_WRITE_START ||
178
                   rcByte[`CMD_REG_BIT:`CMD_REG_WE_BIT] == 2'b11)
179
                )) begin
180
    txBitIndex <= 3'd7;
181
    txMemAddr_oreg <= 0;
182
  end else begin
183
    txBitIndex <= txBitIndex_reg;
184
 
185
    //txMemAddr_oreg <= txMemAddr_reg;
186
    if ((state == `STATE_WRITING || state == `STATE_SEND_WORD) &&
187
        validSpiBit && txBitIndex == 0) begin
188
      txMemAddr_oreg <= txMemAddr_reg + 1;
189
    end else begin
190
      txMemAddr_oreg <= txMemAddr_reg;
191
    end
192
 
193
  end
194
end
195
always @(posedge SysClk) begin
196
  if (validSpiBit && (state == `STATE_WRITING || state == `STATE_SEND_WORD)) begin
197
    txBitIndex_reg <= (txBitIndex == 0 ? 7 : txBitIndex - 1);
198
  end else begin
199
    txBitIndex_reg <= txBitIndex;
200
  end
201
 
202
  txMemAddr_reg <= txMemAddr;
203
//  if (state == `STATE_WRITING && validSpiBit && txBitIndex == 0) begin
204
//    txMemAddr_reg <= txMemAddr + 1;
205
//  end else begin
206
//    txMemAddr_reg <= txMemAddr;  
207
//  end
208
end
209
assign txMemAddr = txMemAddr_oreg;
210
assign SPI_MISO = (state == `STATE_SEND_WORD ? regReadByte_oreg[txBitIndex] : txMemData[txBitIndex]);
211
 
212
// State machine
213
always @(*) begin
214
  if (Reset || packetStart) begin
215
    state <= `STATE_GET_CMD;
216
// Handled in state_reg logic, should be latched, not immediate.
217
//  end else if (state_reg == `STATE_GET_CMD && rcByteValid) begin
218
//    state <= rcByte;
219
  end else begin
220
    state <= state_reg;
221
  end
222
end
223
always @(posedge SysClk) begin
224
  if (`STATE_GET_CMD == state && rcByteValid) begin
225
    if (`CMD_READ_START == rcByte) begin
226
      state_reg <= `STATE_READING;
227
    end else if (`CMD_READ_MORE == rcByte) begin
228
      state_reg <= `STATE_READING;
229
    end else if (`CMD_WRITE_START == rcByte) begin
230
      state_reg <= `STATE_WRITING;
231
    end else if (`CMD_WRITE_MORE == rcByte) begin
232
      state_reg <= `STATE_WRITING;
233
    end else if (rcByte[`CMD_REG_BIT] != 0) begin
234
      // Register access
235
      rcWordByteId <= 0;
236
      command <= `CMD_REG_BASE;               // Write reg           Read reg
237
      state_reg <= (rcByte[`CMD_REG_WE_BIT] ? `STATE_BUILD_WORD : `STATE_SEND_WORD);
238
    end else if (`CMD_INTERRUPT == rcByte) begin
239
      // TODO: NYI
240
    end
241
  end else if (`STATE_BUILD_WORD == state && rcByteValid) begin
242
    if (0 == rcWordByteId) begin
243
      rcWord[31:24] <= rcByte;
244
      rcWordByteId <= 1;
245
    end else if (1 == rcWordByteId) begin
246
      rcWord[23:16] <= rcByte;
247
      rcWordByteId <= 2;
248
    end else if (2 == rcWordByteId) begin
249
      rcWord[15:8] <= rcByte;
250
      rcWordByteId <= 3;
251
    end else if (3 == rcWordByteId) begin
252
      rcWord[7:0] <= rcByte;
253
      state_reg <= `STATE_GET_CMD;
254
    end
255
  end else if (`STATE_SEND_WORD == state && rcByteValid) begin
256
    rcWordByteId <= rcWordByteId + 1;
257
    state_reg <= (rcWordByteId == 3 ? `STATE_GET_CMD : `STATE_SEND_WORD);
258
 
259
  end else begin
260
    state_reg <= state;
261
  end
262
end
263
 
264
// Register logic
265
assign regAddr = (`STATE_GET_CMD == state && rcByteValid && rcByte[`CMD_REG_BIT] ? (rcByte & `CMD_REG_ID_MASK) : regAddr_reg);
266
assign regWriteEn = (`STATE_BUILD_WORD == state && rcByteValid && 3 == rcWordByteId ? 1 : 0);
267
assign regWriteData = {rcWord[31:8], rcByte};
268
always @(posedge SysClk) begin
269
  regAddr_reg <= regAddr;
270
end
271
always @(*) begin
272
  case (rcWordByteId)
273
    0: regReadByte_oreg <= regReadData[31:24];
274
    1: regReadByte_oreg <= regReadData[23:16];
275
    2: regReadByte_oreg <= regReadData[15:8];
276
    3: regReadByte_oreg <= regReadData[7:0];
277
  endcase
278
end
279
 
280
// Debugging
281
always @(posedge SysClk) begin
282
  if (rcByteValid) begin
283
    debug_reg <= rcByte;
284
  end
285
end
286
assign debug_out = debug_reg;
287
 
288
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.