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

Subversion Repositories sdspi

[/] [sdspi/] [trunk/] [rtl/] [llsdspi.v] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    llsdspi.v
4
//
5
// Project:     SD-Card controller, using a shared SPI interface
6
//
7
// Purpose:     This file implements the "lower-level" interface to the
8
//              SD-Card controller.  Specifically, it turns byte-level
9
//      interaction requests into SPI bit-wise interactions.  Further, it
10
//      handles the request and grant for the SPI wires (i.e., it requests
11
//      the SPI port by pulling o_cs_n low, and then waits for i_bus_grant
12
//      to be true before continuing.).  Finally, the speed/clock rate of the
13
//      communication is adjustable as a division of the current clock rate.
14
//
15
//      i_speed
16
//              This is the number of clocks (minus one) between SPI clock
17
//              transitions.  Hence a '0' (not tested, doesn't work) would
18
//              result in a SPI clock that alternated on every input clock
19
//              equivalently dividing the input clock by two, whereas a '1' 
20
//              would divide the input clock by four.
21
//
22
//              In general, the SPI clock frequency will be given by the
23
//              master clock frequency divided by twice this number plus one.
24
//              In other words,
25
//
26
//              SPIFREQ=(i_clk FREQ) / (2*(i_speed+1))
27
//
28
//      i_stb
29
//              True if the master controller is requesting to send a byte.
30
//              This will be ignored unless o_idle is false.
31
//
32
//      i_byte
33
//              The byte that the master controller wishes to send across the
34
//              interface.
35
//
36
//      (The external SPI interface)
37
//
38
//      o_stb
39
//              Only true for one clock--when a byte is valid coming in from the
40
//              interface, this will be true for one clock (a strobe) indicating
41
//              that a valid byte is ready to be read.
42
//
43
//      o_byte
44
//              The value of the byte coming in.
45
//
46
//      o_idle
47
//              True if this low-level device handler is ready to accept a 
48
//              byte from the incoming interface, false otherwise.
49
//
50
//      i_bus_grant
51
//              True if the SPI bus has been granted to this interface, false
52
//              otherwise.  This has been placed here so that the interface of
53
//              the XuLA2 board may be shared between SPI-Flash and the SPI
54
//              based SDCard.  An external arbiter will determine which of the
55
//              two gets to control the clock and mosi outputs given their
56
//              cs_n requests.  If control is not granted, i_bus_grant will
57
//              remain low as will the actual cs_n going out of the FPGA.
58
//
59
//
60
//
61
// Creator:     Dan Gisselquist, Ph.D.
62
//              Gisselquist Technology, LLC
63
//
64
////////////////////////////////////////////////////////////////////////////////
65
//
66
// Copyright (C) 2016, Gisselquist Technology, LLC
67
//
68
// This program is free software (firmware): you can redistribute it and/or
69
// modify it under the terms of  the GNU General Public License as published
70
// by the Free Software Foundation, either version 3 of the License, or (at
71
// your option) any later version.
72
//
73
// This program is distributed in the hope that it will be useful, but WITHOUT
74
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
75
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
76
// for more details.
77
//
78
// You should have received a copy of the GNU General Public License along
79
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
80
// target there if the PDF file isn't present.)  If not, see
81
// <http://www.gnu.org/licenses/> for a copy.
82
//
83
// License:     GPL, v3, as defined and found on www.gnu.org,
84
//              http://www.gnu.org/licenses/gpl.html
85
//
86
//
87
////////////////////////////////////////////////////////////////////////////////
88
//
89
//
90
`define LLSDSPI_IDLE    4'h0
91
`define LLSDSPI_HOTIDLE 4'h1
92
`define LLSDSPI_WAIT    4'h2
93
`define LLSDSPI_START   4'h3
94
//
95
module  llsdspi(i_clk, i_speed, i_cs, i_stb, i_byte,
96
                o_cs_n, o_sclk, o_mosi, i_miso,
97
                o_stb, o_byte, o_idle, i_bus_grant);
98
        parameter       SPDBITS = 7;
99
        //
100
        input                   i_clk;
101
        // Parameters/setup
102
        input           [(SPDBITS-1):0]  i_speed;
103
        // The incoming interface
104
        input                   i_cs;
105
        input                   i_stb;
106
        input           [7:0]    i_byte;
107
        // The actual SPI interface
108
        output  reg             o_cs_n, o_sclk, o_mosi;
109
        input                   i_miso;
110
        // The outgoing interface
111
        output  reg             o_stb;
112
        output  reg     [7:0]    o_byte;
113
        output  wire            o_idle;
114
        // And whether or not we actually own the interface (yet)
115
        input                   i_bus_grant;
116
 
117
        reg                     r_z_counter;
118
        reg     [(SPDBITS-1):0]  r_clk_counter;
119
        reg                     r_idle;
120
        reg             [3:0]    r_state;
121
        reg             [7:0]    r_byte, r_ireg;
122
 
123
        wire    byte_accepted;
124
        assign  byte_accepted = (i_stb)&&(o_idle);
125
 
126
        initial r_clk_counter = 7'h0;
127
        always @(posedge i_clk)
128
        begin
129
                if ((~i_cs)||(~i_bus_grant))
130
                        r_clk_counter <= 0;
131
                else if (byte_accepted)
132
                        r_clk_counter <= i_speed;
133
                else if (~r_z_counter)
134
                        r_clk_counter <= (r_clk_counter - {{(SPDBITS-1){1'b0}},1'b1});
135
                else if ((r_state != `LLSDSPI_IDLE)&&(r_state != `LLSDSPI_HOTIDLE))
136
                        r_clk_counter <= (i_speed);
137
                // else 
138
                //      r_clk_counter <= 16'h00;
139
        end
140
 
141
        initial r_z_counter = 1'b1;
142
        always @(posedge i_clk)
143
        begin
144
                if ((~i_cs)||(~i_bus_grant))
145
                        r_z_counter <= 1'b1;
146
                else if (byte_accepted)
147
                        r_z_counter <= 1'b0;
148
                else if (~r_z_counter)
149
                        r_z_counter <= (r_clk_counter == 1);
150
                else if ((r_state != `LLSDSPI_IDLE)&&(r_state != `LLSDSPI_HOTIDLE))
151
                        r_z_counter <= 1'b0;
152
        end
153
 
154
        initial r_state = `LLSDSPI_IDLE;
155
        always @(posedge i_clk)
156
        begin
157
                o_stb <= 1'b0;
158
                o_cs_n <= ~i_cs;
159
                if (~i_cs)
160
                begin
161
                        r_state <= `LLSDSPI_IDLE;
162
                        r_idle <= 1'b0;
163
                        o_sclk <= 1'b1;
164
                end else if (~r_z_counter)
165
                begin
166
                        r_idle <= 1'b0;
167
                        if (byte_accepted)
168
                        begin // Will only happen within a hot idle state
169
                                r_byte <= { i_byte[6:0], 1'b1 };
170
                                r_state <= `LLSDSPI_START+1;
171
                                o_mosi <= i_byte[7];
172
                        end
173
                end else if (r_state == `LLSDSPI_IDLE)
174
                begin
175
                        o_sclk <= 1'b1;
176
                        if (byte_accepted)
177
                        begin
178
                                r_byte <= i_byte[7:0];
179
                                r_state <= (i_bus_grant)?`LLSDSPI_START:`LLSDSPI_WAIT;
180
                                r_idle <= 1'b0;
181
                                o_mosi <= i_byte[7];
182
                        end else begin
183
                                r_idle <= 1'b1;
184
                        end
185
                end else if (r_state == `LLSDSPI_WAIT)
186
                begin
187
                        r_idle <= 1'b0;
188
                        if (i_bus_grant)
189
                                r_state <= `LLSDSPI_START;
190
                end else if (r_state == `LLSDSPI_HOTIDLE)
191
                begin
192
                        // The clock is low, the bus is granted, we're just
193
                        // waiting for the next byte to transmit
194
                        o_sclk <= 1'b0;
195
                        if (byte_accepted)
196
                        begin
197
                                r_byte <= i_byte[7:0];
198
                                r_state <= `LLSDSPI_START;
199
                                r_idle <= 1'b0;
200
                                o_mosi <= i_byte[7];
201
                        end else
202
                                r_idle <= 1'b1;
203
                // end else if (r_state == `LLSDSPI_START)
204
                // begin
205
                        // o_sclk <= 1'b0;
206
                        // r_state <= r_state + 1;
207
                end else if (o_sclk)
208
                begin
209
                        o_mosi <= r_byte[7];
210
                        r_byte <= { r_byte[6:0], 1'b1 };
211
                        r_state <= r_state + 1;
212
                        o_sclk <= 1'b0;
213
                        if (r_state >= `LLSDSPI_START+8)
214
                        begin
215
                                r_state <= `LLSDSPI_HOTIDLE;
216
                                r_idle <= 1'b1;
217
                                o_stb <= 1'b1;
218
                                o_byte <= r_ireg;
219
                        end else
220
                                r_state <= r_state + 1;
221
                end else begin
222
                        r_ireg <= { r_ireg[6:0], i_miso };
223
                        o_sclk <= 1'b1;
224
                end
225
        end
226
 
227
        assign o_idle = (r_idle)&&( (i_cs)&&(i_bus_grant) );
228
endmodule
229
 
230
 

powered by: WebSVN 2.1.0

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