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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1k_startup/] [rtl/] [verilog/] [spi_flash.v] - Blame information for rev 868

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

Line No. Rev Author Line
1 2 marcus.erl
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  spi_shift.v                                                 ////
4
////                                                              ////
5
////  This file is part of the SPI IP core project                ////
6
////  http://www.opencores.org/projects/spi/                      ////
7
////                                                              ////
8
////  Author(s):                                                  ////
9
////      - Simon Srot (simons@opencores.org)                     ////
10
////                                                              ////
11
////  All additional information is avaliable in the Readme.txt   ////
12
////  file.                                                       ////
13
////                                                              ////
14
//////////////////////////////////////////////////////////////////////
15
////                                                              ////
16
//// Copyright (C) 2002 Authors                                   ////
17
////                                                              ////
18
//// This source file may be used and distributed without         ////
19
//// restriction provided that this copyright statement is not    ////
20
//// removed from the file and that any derivative work contains  ////
21
//// the original copyright notice and the associated disclaimer. ////
22
////                                                              ////
23
//// This source file is free software; you can redistribute it   ////
24
//// and/or modify it under the terms of the GNU Lesser General   ////
25
//// Public License as published by the Free Software Foundation; ////
26
//// either version 2.1 of the License, or (at your option) any   ////
27
//// later version.                                               ////
28
////                                                              ////
29
//// This source is distributed in the hope that it will be       ////
30
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
31
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
32
//// PURPOSE.  See the GNU Lesser General Public License for more ////
33
//// details.                                                     ////
34
////                                                              ////
35
//// You should have received a copy of the GNU Lesser General    ////
36
//// Public License along with this source; if not, download it   ////
37
//// from http://www.opencores.org/lgpl.shtml                     ////
38
////                                                              ////
39
//////////////////////////////////////////////////////////////////////
40
 `timescale 1ns / 10ps
41
module spi_flash_clgen (clk_in, rst, go, enable, last_clk, clk_out, pos_edge, neg_edge);
42
   parameter divider_len = 2;
43
   parameter divider = 1;
44
   parameter Tp = 1;
45
   input                            clk_in;
46
   input                            rst;
47
   input                            enable;
48
   input                            go;
49
   input                            last_clk;
50
   output                           clk_out;
51
   output                           pos_edge;
52
   output                           neg_edge;
53
   reg                              clk_out;
54
   reg                              pos_edge;
55
   reg                              neg_edge;
56
   reg [divider_len-1:0]             cnt;
57
   wire                             cnt_zero;
58
   wire                             cnt_one;
59
   assign cnt_zero = cnt == {divider_len{1'b0}};
60
   assign cnt_one  = cnt == {{divider_len-1{1'b0}}, 1'b1};
61
   always @(posedge clk_in or posedge rst)
62
     begin
63
        if(rst)
64
          cnt <= #Tp {divider_len{1'b1}};
65
        else
66
          begin
67
             if(!enable || cnt_zero)
68
               cnt <= #Tp divider;
69
             else
70
               cnt <= #Tp cnt - {{divider_len-1{1'b0}}, 1'b1};
71
          end
72
     end
73
   always @(posedge clk_in or posedge rst)
74
     begin
75
        if(rst)
76
          clk_out <= #Tp 1'b0;
77
        else
78
          clk_out <= #Tp (enable && cnt_zero && (!last_clk || clk_out)) ? ~clk_out : clk_out;
79
     end
80
   always @(posedge clk_in or posedge rst)
81
     begin
82
        if(rst)
83
          begin
84
             pos_edge  <= #Tp 1'b0;
85
             neg_edge  <= #Tp 1'b0;
86
          end
87
        else
88
          begin
89
             pos_edge  <= #Tp (enable && !clk_out && cnt_one) || (!(|divider) && clk_out) || (!(|divider) && go && !enable);
90
             neg_edge  <= #Tp (enable && clk_out && cnt_one) || (!(|divider) && !clk_out && enable);
91
          end
92
     end
93
endmodule
94
 `timescale 1ns / 10ps
95
module spi_flash_shift
96
  (
97
   clk, rst, latch, byte_sel, len, go,
98
   pos_edge, neg_edge,
99
   lsb, rx_negedge, tx_negedge,
100
   tip, last,
101
   p_in, p_out, s_clk, s_in, s_out);
102
  parameter Tp = 1;
103
   input                          clk;
104
   input                          rst;
105
   input                          latch;
106
   input [3:0]                     byte_sel;
107
   input [6-1:0] len;
108
   input                          lsb;
109
   input                          tx_negedge;
110
   input                          rx_negedge;
111
   input                          go;
112
   input                          pos_edge;
113
   input                          neg_edge;
114
   output                         tip;
115
   output                         last;
116
   input [31:0]            p_in;
117
   output [32-1:0]         p_out;
118
   input                          s_clk;
119
   input                          s_in;
120
   output                         s_out;
121
   reg                            s_out;
122
   reg                            tip;
123
   reg [6:0]       cnt;
124
   reg [32-1:0]    data;
125
   wire [6:0]      tx_bit_pos;
126
   wire [6:0]      rx_bit_pos;
127
   wire                           rx_clk;
128
   wire                           tx_clk;
129
   assign p_out = data;
130
   assign tx_bit_pos = lsb ? {!(|len), len} - cnt : cnt - {{6{1'b0}},1'b1};
131
   assign rx_bit_pos = lsb ? {!(|len), len} - (rx_negedge ? cnt + {{6{1'b0}},1'b1} : cnt) : (rx_negedge ? cnt : cnt - {{6{1'b0}},1'b1});
132
  assign last = !(|cnt);
133
  assign rx_clk = (rx_negedge ? neg_edge : pos_edge) && (!last || s_clk);
134
  assign tx_clk = (tx_negedge ? neg_edge : pos_edge) && !last;
135
  always @(posedge clk or posedge rst)
136
  begin
137
    if(rst)
138
      cnt <= #Tp {6+1{1'b0}};
139
    else
140
      begin
141
        if(tip)
142
          cnt <= #Tp pos_edge ? (cnt - {{6{1'b0}}, 1'b1}) : cnt;
143
        else
144
          cnt <= #Tp !(|len) ? {1'b1, {6{1'b0}}} : {1'b0, len};
145
      end
146
  end
147
  always @(posedge clk or posedge rst)
148
  begin
149
    if(rst)
150
      tip <= #Tp 1'b0;
151
  else if(go && ~tip)
152
    tip <= #Tp 1'b1;
153
  else if(tip && last && pos_edge)
154
    tip <= #Tp 1'b0;
155
  end
156
  always @(posedge clk or posedge rst)
157
  begin
158
    if (rst)
159
      s_out   <= #Tp 1'b0;
160
    else
161
      s_out <= #Tp (tx_clk || !tip) ? data[tx_bit_pos[6-1:0]] : s_out;
162
  end
163
   always @(posedge clk or posedge rst)
164
     if (rst)
165
       data   <= #Tp 32'h03000000;
166
     else
167
       if (latch & !tip)
168
         begin
169
            if (byte_sel[0])
170
              data[7:0] <= #Tp p_in[7:0];
171
            if (byte_sel[1])
172
              data[15:8] <= #Tp p_in[15:8];
173
            if (byte_sel[2])
174
              data[23:16] <= #Tp p_in[23:16];
175
            if (byte_sel[3])
176
              data[31:24] <= #Tp p_in[31:24];
177
         end
178
       else
179
         data[rx_bit_pos[6-1:0]] <= #Tp rx_clk ? s_in : data[rx_bit_pos[6-1:0]];
180
endmodule
181
 `timescale 1ns / 10ps
182
module spi_flash_top
183
  (
184
   wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_sel_i,
185
   wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o,
186
   ss_pad_o, sclk_pad_o, mosi_pad_o, miso_pad_i
187
   );
188
   parameter divider_len = 2;
189
   parameter divider = 0;
190
   parameter Tp = 1;
191
   input                            wb_clk_i;
192
   input                            wb_rst_i;
193
   input [4:2]                      wb_adr_i;
194
   input [31:0]              wb_dat_i;
195
   output [31:0]                     wb_dat_o;
196
   input [3:0]                       wb_sel_i;
197
   input                            wb_we_i;
198
   input                            wb_stb_i;
199
   input                            wb_cyc_i;
200
   output                           wb_ack_o;
201
   output [2-1:0]            ss_pad_o;
202
   output                           sclk_pad_o;
203
   output                           mosi_pad_o;
204
   input                            miso_pad_i;
205
   reg [31:0]                        wb_dat_o;
206
   reg                              wb_ack_o;
207
   wire [14-1:0]             ctrl;
208
   reg [2-1:0]       ss;
209
   wire [32-1:0]             rx;
210
   wire [5:0]                        char_len;
211
   reg                              char_len_ctrl;
212
   reg                              go;
213
   wire                             spi_ctrl_sel;
214
   wire                             spi_tx_sel;
215
   wire                             spi_ss_sel;
216
   wire                             tip;
217
   wire                             pos_edge;
218
   wire                             neg_edge;
219
   wire                             last_bit;
220
  wire                             rx_negedge;
221
  wire                             tx_negedge;
222
  wire                             lsb;
223
  wire                             ass;
224
   assign spi_ctrl_sel    = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == 4);
225
   assign spi_tx_sel      = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == 0);
226
   assign spi_ss_sel      = wb_cyc_i & wb_stb_i & (wb_adr_i[4:2] == 6);
227
   always @(posedge wb_clk_i or posedge wb_rst_i)
228
  begin
229
     if (wb_rst_i)
230
       wb_dat_o <= #Tp 32'b0;
231
     else
232
       case (wb_adr_i[4:2])
233
         0:    wb_dat_o <= rx;
234
         4:    wb_dat_o <= {18'd0, ctrl};
235
         5:  wb_dat_o <= {{32-divider_len{1'b0}}, divider};
236
         6:      wb_dat_o <= {{32-2{1'b0}}, ss};
237
        default:      wb_dat_o  <= rx;
238
       endcase
239
  end
240
   always @(posedge wb_clk_i or posedge wb_rst_i)
241
     begin
242
        if (wb_rst_i)
243
          wb_ack_o <= #Tp 1'b0;
244
    else
245
      wb_ack_o <= #Tp wb_cyc_i & wb_stb_i & ~wb_ack_o;
246
     end
247
   always @(posedge wb_clk_i or posedge wb_rst_i)
248
     begin
249
        if (wb_rst_i)
250
          {go,char_len_ctrl} <= #Tp 2'b01;
251
        else if(spi_ctrl_sel && wb_we_i && !tip)
252
          begin
253
             if (wb_sel_i[0])
254
               char_len_ctrl <= #Tp wb_dat_i[5];
255
             if (wb_sel_i[1])
256
               go <= #Tp wb_dat_i[8];
257
          end
258
        else if(tip && last_bit && pos_edge)
259
          go <= #Tp 1'b0;
260
     end
261
   assign char_len = char_len_ctrl ? 6'd32 : 6'd8;
262
   assign ass = 1'b0;
263
   assign lsb = 1'b0;
264
   assign rx_negedge = 1'b0;
265
   assign tx_negedge = 1'b1;
266
   assign ctrl = {ass,1'b0,lsb,tx_negedge,rx_negedge,go,1'b0,1'b0,char_len};
267
   always @(posedge wb_clk_i or posedge wb_rst_i)
268
     if (wb_rst_i)
269
       ss <= #Tp {2{1'b0}};
270
     else if(spi_ss_sel && wb_we_i && !tip)
271
       if (wb_sel_i[0])
272
         ss <= #Tp wb_dat_i[2-1:0];
273
   assign ss_pad_o = ~((ss & {2{tip & ass}}) | (ss & {2{!ass}}));
274
   spi_flash_clgen
275
     #
276
     (
277
      .divider_len(divider_len),
278
      .divider(divider)
279
      )
280
     clgen
281
       (
282
        .clk_in(wb_clk_i),
283
        .rst(wb_rst_i),
284
        .go(go),
285
        .enable(tip),
286
        .last_clk(last_bit),
287
        .clk_out(sclk_pad_o),
288
        .pos_edge(pos_edge),
289
        .neg_edge(neg_edge)
290
        );
291
   spi_flash_shift  shift
292
     (
293
      .clk(wb_clk_i),
294
      .rst(wb_rst_i),
295
      .len(char_len[6-1:0]),
296
      .latch(spi_tx_sel & wb_we_i),
297
      .byte_sel(wb_sel_i),
298
      .go(go),
299
      .pos_edge(pos_edge),
300
      .neg_edge(neg_edge),
301
      .lsb(lsb),
302
      .rx_negedge(rx_negedge),
303
      .tx_negedge(tx_negedge),
304
      .tip(tip),
305
      .last(last_bit),
306
      .p_in(wb_dat_i),
307
      .p_out(rx),
308
      .s_clk(sclk_pad_o),
309
      .s_in(miso_pad_i),
310
      .s_out(mosi_pad_o)
311
      );
312
endmodule

powered by: WebSVN 2.1.0

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