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

Subversion Repositories sdspi

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

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 3 dgisselq
`default_nettype        none
91
//
92 2 dgisselq
`define LLSDSPI_IDLE    4'h0
93
`define LLSDSPI_HOTIDLE 4'h1
94
`define LLSDSPI_WAIT    4'h2
95
`define LLSDSPI_START   4'h3
96
//
97
module  llsdspi(i_clk, i_speed, i_cs, i_stb, i_byte,
98
                o_cs_n, o_sclk, o_mosi, i_miso,
99
                o_stb, o_byte, o_idle, i_bus_grant);
100
        parameter       SPDBITS = 7;
101
        //
102 3 dgisselq
        input   wire            i_clk;
103 2 dgisselq
        // Parameters/setup
104 3 dgisselq
        input   wire    [(SPDBITS-1):0]  i_speed;
105 2 dgisselq
        // The incoming interface
106 3 dgisselq
        input   wire            i_cs;
107
        input   wire            i_stb;
108
        input   wire    [7:0]    i_byte;
109 2 dgisselq
        // The actual SPI interface
110
        output  reg             o_cs_n, o_sclk, o_mosi;
111 3 dgisselq
        input   wire            i_miso;
112 2 dgisselq
        // The outgoing interface
113
        output  reg             o_stb;
114
        output  reg     [7:0]    o_byte;
115
        output  wire            o_idle;
116
        // And whether or not we actually own the interface (yet)
117 3 dgisselq
        input   wire            i_bus_grant;
118 2 dgisselq
 
119
        reg                     r_z_counter;
120
        reg     [(SPDBITS-1):0]  r_clk_counter;
121
        reg                     r_idle;
122
        reg             [3:0]    r_state;
123
        reg             [7:0]    r_byte, r_ireg;
124
 
125
        wire    byte_accepted;
126
        assign  byte_accepted = (i_stb)&&(o_idle);
127
 
128
        initial r_clk_counter = 7'h0;
129
        always @(posedge i_clk)
130
        begin
131 3 dgisselq
                if ((!i_cs)||(!i_bus_grant))
132 2 dgisselq
                        r_clk_counter <= 0;
133
                else if (byte_accepted)
134
                        r_clk_counter <= i_speed;
135 3 dgisselq
                else if (!r_z_counter)
136 2 dgisselq
                        r_clk_counter <= (r_clk_counter - {{(SPDBITS-1){1'b0}},1'b1});
137
                else if ((r_state != `LLSDSPI_IDLE)&&(r_state != `LLSDSPI_HOTIDLE))
138
                        r_clk_counter <= (i_speed);
139
                // else 
140
                //      r_clk_counter <= 16'h00;
141
        end
142
 
143
        initial r_z_counter = 1'b1;
144
        always @(posedge i_clk)
145
        begin
146 3 dgisselq
                if ((!i_cs)||(!i_bus_grant))
147 2 dgisselq
                        r_z_counter <= 1'b1;
148
                else if (byte_accepted)
149
                        r_z_counter <= 1'b0;
150 3 dgisselq
                else if (!r_z_counter)
151 2 dgisselq
                        r_z_counter <= (r_clk_counter == 1);
152
                else if ((r_state != `LLSDSPI_IDLE)&&(r_state != `LLSDSPI_HOTIDLE))
153
                        r_z_counter <= 1'b0;
154
        end
155
 
156
        initial r_state = `LLSDSPI_IDLE;
157
        always @(posedge i_clk)
158
        begin
159
                o_stb <= 1'b0;
160 3 dgisselq
                o_cs_n <= !i_cs;
161
                if (!i_cs)
162 2 dgisselq
                begin
163
                        r_state <= `LLSDSPI_IDLE;
164
                        r_idle <= 1'b0;
165
                        o_sclk <= 1'b1;
166 3 dgisselq
                end else if (!r_z_counter)
167 2 dgisselq
                begin
168
                        r_idle <= 1'b0;
169
                        if (byte_accepted)
170
                        begin // Will only happen within a hot idle state
171
                                r_byte <= { i_byte[6:0], 1'b1 };
172
                                r_state <= `LLSDSPI_START+1;
173
                                o_mosi <= i_byte[7];
174
                        end
175
                end else if (r_state == `LLSDSPI_IDLE)
176
                begin
177
                        o_sclk <= 1'b1;
178
                        if (byte_accepted)
179
                        begin
180
                                r_byte <= i_byte[7:0];
181
                                r_state <= (i_bus_grant)?`LLSDSPI_START:`LLSDSPI_WAIT;
182
                                r_idle <= 1'b0;
183
                                o_mosi <= i_byte[7];
184
                        end else begin
185
                                r_idle <= 1'b1;
186
                        end
187
                end else if (r_state == `LLSDSPI_WAIT)
188
                begin
189
                        r_idle <= 1'b0;
190
                        if (i_bus_grant)
191
                                r_state <= `LLSDSPI_START;
192
                end else if (r_state == `LLSDSPI_HOTIDLE)
193
                begin
194
                        // The clock is low, the bus is granted, we're just
195
                        // waiting for the next byte to transmit
196
                        o_sclk <= 1'b0;
197
                        if (byte_accepted)
198
                        begin
199
                                r_byte <= i_byte[7:0];
200
                                r_state <= `LLSDSPI_START;
201
                                r_idle <= 1'b0;
202
                                o_mosi <= i_byte[7];
203
                        end else
204
                                r_idle <= 1'b1;
205
                // end else if (r_state == `LLSDSPI_START)
206
                // begin
207
                        // o_sclk <= 1'b0;
208
                        // r_state <= r_state + 1;
209
                end else if (o_sclk)
210
                begin
211
                        o_mosi <= r_byte[7];
212
                        r_byte <= { r_byte[6:0], 1'b1 };
213
                        r_state <= r_state + 1;
214
                        o_sclk <= 1'b0;
215
                        if (r_state >= `LLSDSPI_START+8)
216
                        begin
217
                                r_state <= `LLSDSPI_HOTIDLE;
218
                                r_idle <= 1'b1;
219
                                o_stb <= 1'b1;
220
                                o_byte <= r_ireg;
221
                        end else
222
                                r_state <= r_state + 1;
223
                end else begin
224
                        r_ireg <= { r_ireg[6:0], i_miso };
225
                        o_sclk <= 1'b1;
226
                end
227
        end
228
 
229
        assign o_idle = (r_idle)&&( (i_cs)&&(i_bus_grant) );
230
endmodule
231
 
232
 

powered by: WebSVN 2.1.0

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