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

Subversion Repositories attiny_atmega_xmega_core

[/] [attiny_atmega_xmega_core/] [trunk/] [rtl/] [io/] [spi_s.v] - Blame information for rev 15

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 morgothcre
/*
2
 * This IP is a SPI IO adapter implementation.
3
 *
4
 * Copyright (C) 2018  Iulian Gheorghiu
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
 */
20
 
21
`timescale 1ns / 1ps
22
 
23
`include "io_s_h.v"
24
 
25
module spi_s #(
26
        parameter DINAMIC_BAUDRATE = "TRUE",
27
        parameter BAUDRATE_DIVIDER = 3,
28
        parameter ADDRESS = 0,
29
        parameter BUS_ADDR_DATA_LEN = 16
30
    )(
31
        input rst,
32
        input clk,
33
        input [BUS_ADDR_DATA_LEN-1:0]addr,
34
        input wr,
35
        input rd,
36
        input [7:0]bus_in,
37
        output reg[7:0]bus_out,
38
        output int,
39
 
40
        output sck,/* SPI 'sck' signal (output) */
41
        output mosi,/* SPI 'mosi' signal (output) */
42
        input miso,/* SPI 'miso' signal (input) */
43
        output reg ss/* SPI 'ss' signal (if send buffer is maintained full the ss signal will not go high between between transmit chars)(output) */
44
    );
45
 
46
//reg [7:0]CTRL;
47
//reg [7:0]BAUD;
48
 
49
wire cs_int = addr >= ADDRESS && addr < (ADDRESS + 8);
50
wire rd_int = cs_int && rd;
51
wire wr_int = cs_int && wr;
52
 
53
reg [7:0]baud_cnt;
54
 
55
wire buffempty;
56
 
57
reg [7:0]CTRL;
58
reg [7:0]INTCTRL;
59
reg [7:0]STATUS;
60
 
61
 
62
localparam WORD_LEN = 8;
63
localparam PRESCALLER_SIZE = 8;
64
 
65
reg _mosi;
66
 
67
reg charreceivedp;
68
reg charreceivedn;
69
 
70
reg inbufffullp = 1'b0;
71
reg inbufffulln = 1'b0;
72
 
73
reg [WORD_LEN - 1:0]input_buffer;
74
reg [WORD_LEN - 1:0]output_buffer;
75
 
76
assign buffempty = ~(inbufffullp ^ inbufffulln);
77
reg [2:0]prescallerbuff;
78
 
79
always @ (posedge clk or posedge rst)
80
begin
81
        if(rst)
82
        begin
83
                inbufffullp <= 1'b0;
84
                prescallerbuff <= 3'b000;
85
                CTRL <= 0;
86
                INTCTRL <= 0;
87
                input_buffer <= 0;
88
        end
89
        else
90
        begin
91
                if(wr_int)
92
                begin
93
                        case(addr[2:0])
94
                        `SPI_CTRL: CTRL <= bus_in;
95
                        `SPI_INTCTRL: INTCTRL <= bus_in;
96
                        `SPI_DATA:
97
                        begin
98
                                if(inbufffullp == inbufffulln && buffempty && CTRL[`SPI_ENABLE_bp])
99
                                begin
100
                                        inbufffullp <= ~inbufffullp;
101
                                        prescallerbuff <= {CTRL[`SPI_CLK2X_bp], CTRL[`SPI_PRESCALER_gp + 1:`SPI_PRESCALER_gp]};
102
                                        input_buffer <= bus_in;
103
                                end
104
                        end
105
                        endcase
106
                end
107
        end
108
end
109
 
110
always @ (posedge clk or posedge rst)
111
begin
112
        if(rst)
113
        begin
114
                STATUS <= 8'h00;
115
                charreceivedn <= 1'b0;
116
        end
117
        else if(rd_int)
118
        begin
119
                case(addr[2:0])
120
                `SPI_DATA: STATUS[`SPI_IF_bp] <= 1'b0;
121
                endcase
122
        end
123
        else if(charreceivedp != charreceivedn)
124
        begin
125
                STATUS[`SPI_IF_bp] <= 1'b1;
126
                charreceivedn <= ~charreceivedn;
127
        end
128
 
129
end
130
 
131
always @ (*)
132
begin
133
        bus_out <= 8'bz;
134
        if(rd_int)
135
        begin
136
                case(addr[2:0])
137
                `SPI_CTRL: bus_out <= CTRL;
138
                `SPI_INTCTRL: bus_out <= INTCTRL;
139
                `SPI_STATUS: bus_out <= STATUS;
140
                `SPI_DATA: bus_out <= output_buffer;
141
                endcase
142
        end
143
end
144
 
145
assign int = INTCTRL[`SPI_INTLVL_gp + 1: `SPI_INTLVL_gp] ? STATUS[`SPI_IF_bp] : 1'b0;
146
 
147
/***********************************************/
148
/************ !Asynchronus send ****************/
149
/***********************************************/
150
localparam state_idle = 1'b0;
151
localparam state_busy = 1'b1;
152
reg state;
153
 
154
 
155
reg [PRESCALLER_SIZE - 1:0]prescaller_cnt;
156
reg [WORD_LEN - 1:0]shift_reg_out;
157
reg [WORD_LEN - 1:0]shift_reg_in;
158
reg [4:0]sckint;
159
//reg sckintn;
160
reg [2:0]prescallerint;
161
reg [7:0]prescdemux;
162
 
163
 
164
always @ (*)
165
begin
166
        case(prescallerint)
167
        3'b000: prescdemux <= 3;
168
        3'b001: prescdemux <= 15;
169
        3'b010: prescdemux <= 63;
170
        3'b011: prescdemux <= 127;
171
        3'b100: prescdemux <= 1;
172
        3'b101: prescdemux <= 7;
173
        3'b110: prescdemux <= 31;
174
        3'b111: prescdemux <= 63;
175
        endcase
176
end
177
 
178
reg lsbfirstint;
179
reg [1:0]modeint;
180
 
181
 
182
always  @       (posedge clk or posedge rst)
183
begin
184
        if(rst)
185
        begin
186
                baud_cnt = 'h00;
187
        inbufffulln <= 1'b0;
188
                ss <= 1'b1;
189
                state <= state_idle;
190
                prescaller_cnt <= {PRESCALLER_SIZE{1'b0}};
191
                prescallerint <= {PRESCALLER_SIZE{3'b0}};
192
                shift_reg_out <= {WORD_LEN{1'b0}};
193
                shift_reg_in <= {WORD_LEN{1'b0}};
194
                sckint <=  {5{1'b0}};
195
                _mosi <= 1'b1;
196
                output_buffer <= {WORD_LEN{1'b0}};
197
                charreceivedp <= 1'b0;
198
                lsbfirstint <= 1'b0;
199
                modeint <= 2'b00;
200
        end
201
        else
202
        begin
203
                if(CTRL[`SPI_ENABLE_bp])
204
                begin
205
                        if(DINAMIC_BAUDRATE == "TRUE" ? baud_cnt == prescdemux : baud_cnt == {BAUDRATE_DIVIDER})
206
                        begin
207
                        baud_cnt <= 'h00;
208
                                case(state)
209
                                state_idle:
210
                                        begin
211
                                                if(inbufffullp != inbufffulln)
212
                                                begin
213
                                                        inbufffulln <= ~inbufffulln;
214
                                                        ss <= 1'b0;
215
                                                        prescaller_cnt <= {PRESCALLER_SIZE{1'b0}};
216
                                                        prescallerint <= prescallerbuff;
217
                                                        lsbfirstint <= CTRL[`SPI_DORD_bp];
218
                                                        modeint <= CTRL[`SPI_MODE_gp + 1:`SPI_MODE_gp];
219
                                                        shift_reg_out <= input_buffer;
220
                                                        state <= state_busy;
221
                                                        if(!CTRL[`SPI_MODE_gp])
222
                                                        begin
223
                                                                if(!CTRL[`SPI_DORD_bp])
224
                                                                        _mosi <= input_buffer[WORD_LEN - 1];
225
                                                                else
226
                                                                        _mosi <= input_buffer[0];
227
                                                        end
228
                                                end
229
                                        end
230
                                        state_busy:
231
                                        begin
232
                                                if(prescaller_cnt != prescdemux)
233
                                                begin
234
                                                        prescaller_cnt <= prescaller_cnt + 1;
235
                                                end
236
                                                else
237
                                                begin
238
                                                        prescaller_cnt <= {PRESCALLER_SIZE{1'b0}};
239
                                                        sckint <= sckint + 1;
240
                                                        if(sckint[0] == modeint[0])
241
                                                        begin
242
                                                                if(!lsbfirstint)
243
                                                                begin
244
                                                                        shift_reg_in <= {miso, shift_reg_in[7:1]};
245
                                                                        shift_reg_out <= {shift_reg_out[6:0], 1'b1};
246
                                                                end
247
                                                                else
248
                                                                begin
249
                                                                        shift_reg_in <= {shift_reg_in[6:0], miso};
250
                                                                        shift_reg_out <= {1'b1, shift_reg_out[7:1]};
251
                                                                end
252
                                                        end
253
                                                        else
254
                                                        begin
255
                                                                if(sckint[4:1] == WORD_LEN - 1)
256
                                                                begin
257
                                                                        sckint <= {5{1'b0}};
258
                                                                        if(inbufffullp == inbufffulln)
259
                                                                        begin
260
                                                                                ss <= 1'b1;
261
                                                                        end
262
                                                                        output_buffer <= shift_reg_in;
263
                                                                        if(charreceivedp == charreceivedn)
264
                                                                        begin
265
                                                                                charreceivedp <= ~charreceivedp;
266
                                                                        end
267
                                                                        state <= state_idle;
268
                                                                end
269
                                                                else
270
                                                                begin
271
                                                                if(!lsbfirstint)
272
                                                                        _mosi <= shift_reg_out[WORD_LEN - 1];
273
                                                                else
274
                                                                        _mosi <= shift_reg_out[0];
275
                                                                end
276
                                                        end
277
                                                end
278
                                        end
279
                                endcase
280
                        end
281
                        else
282
                        begin
283
                                baud_cnt <= baud_cnt + 1;
284
                        end
285
                end
286
        end
287
end
288
 
289
assign sck = (modeint[1])? ~sckint : sckint;
290
assign mosi = (ss) ? 1'b1:_mosi;
291
 
292
endmodule

powered by: WebSVN 2.1.0

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