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

Subversion Repositories yifive

[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [spi_master/] [src/] [spim_regs.sv] - Blame information for rev 18

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

Line No. Rev Author Line
1 18 dinesha
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  SPI WishBone Register I/F Module                            ////
4
////                                                              ////
5
////  This file is part of the YIFive cores project               ////
6
////  http://www.opencores.org/cores/yifive/                      ////
7
////                                                              ////
8
////  Description                                                 ////
9
////     SPI WishBone I/F module                                  ////
10
////     This block support following functionality               ////
11
////        1. Direct SPI Read memory support for address rang    ////
12
////             0x0000 to 0x0FFF_FFFF - Use full for Instruction ////
13
////             Data Memory fetch                                ////
14
////        2. SPI Local Register Access                          ////
15
////        3. Indirect register way to access SPI Memory         ////
16
////                                                              ////
17
////  To Do:                                                      ////
18
////    nothing                                                   ////
19
////                                                              ////
20
////  Author(s):                                                  ////
21
////      - Dinesh Annayya, dinesha@opencores.org                 ////
22
////                                                              ////
23
////  Revision :                                                  ////
24
////     V.0  -  June 8, 2021                                     ////
25
////                                                              ////
26
//////////////////////////////////////////////////////////////////////
27
////                                                              ////
28
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
29
////                                                              ////
30
//// This source file may be used and distributed without         ////
31
//// restriction provided that this copyright statement is not    ////
32
//// removed from the file and that any derivative work contains  ////
33
//// the original copyright notice and the associated disclaimer. ////
34
////                                                              ////
35
//// This source file is free software; you can redistribute it   ////
36
//// and/or modify it under the terms of the GNU Lesser General   ////
37
//// Public License as published by the Free Software Foundation; ////
38
//// either version 2.1 of the License, or (at your option) any   ////
39
//// later version.                                               ////
40
////                                                              ////
41
//// This source is distributed in the hope that it will be       ////
42
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
43
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
44
//// PURPOSE.  See the GNU Lesser General Public License for more ////
45
//// details.                                                     ////
46
////                                                              ////
47
//// You should have received a copy of the GNU Lesser General    ////
48
//// Public License along with this source; if not, download it   ////
49
//// from http://www.opencores.org/lgpl.shtml                     ////
50
////                                                              ////
51
//////////////////////////////////////////////////////////////////////
52
 
53
 
54
module spim_regs #( parameter WB_WIDTH = 32) (
55
    input  logic                         mclk,
56
    input  logic                         rst_n,
57
 
58
    input  logic                         wbd_stb_i, // strobe/request
59
    input  logic   [WB_WIDTH-1:0]        wbd_adr_i, // address
60
    input  logic                         wbd_we_i,  // write
61
    input  logic   [WB_WIDTH-1:0]        wbd_dat_i, // data output
62
    input  logic   [3:0]                 wbd_sel_i, // byte enable
63
    output logic   [WB_WIDTH-1:0]        wbd_dat_o, // data input
64
    output logic                         wbd_ack_o, // acknowlegement
65
    output logic                         wbd_err_o,  // error
66
 
67
    output logic                   [7:0] spi_clk_div,
68
    output logic                         spi_clk_div_valid,
69
    input logic                    [7:0] spi_status,
70
 
71
    // Towards SPI TX/RX FSM
72
 
73
 
74
    output logic                          spi_req,
75
    output logic                   [31:0] spi_addr,
76
    output logic                    [5:0] spi_addr_len,
77
    output logic                   [7:0]  spi_cmd,
78
    output logic                    [5:0] spi_cmd_len,
79
    output logic                   [7:0]  spi_mode_cmd,
80
    output logic                          spi_mode_cmd_enb,
81
    output logic                    [3:0] spi_csreg,
82
    output logic                   [15:0] spi_data_len,
83
    output logic                   [15:0] spi_dummy_rd_len,
84
    output logic                   [15:0] spi_dummy_wr_len,
85
    output logic                          spi_swrst,
86
    output logic                          spi_rd,
87
    output logic                          spi_wr,
88
    output logic                          spi_qrd,
89
    output logic                          spi_qwr,
90
    output logic                   [31:0] spi_wdata,
91
    input logic                   [31:0]  spi_rdata,
92
    input logic                           spi_ack
93
 
94
    );
95
 
96
//----------------------------
97
// Register Decoding
98
// ---------------------------
99
parameter REG_CTRL     = 4'b0000;
100
parameter REG_CLKDIV   = 4'b0001;
101
parameter REG_SPICMD   = 4'b0010;
102
parameter REG_SPIADR   = 4'b0011;
103
parameter REG_SPILEN   = 4'b0100;
104
parameter REG_SPIDUM   = 4'b0101;
105
parameter REG_SPIWDATA = 4'b0110;
106
parameter REG_SPIRDATA = 4'b0111;
107
parameter REG_STATUS   = 4'b1000;
108
 
109
// Init FSM
110
parameter SPI_INIT_IDLE     = 3'b000;
111
parameter SPI_INIT_CMD_WAIT = 3'b001;
112
parameter SPI_INIT_WRR_CMD  = 3'b010;
113
parameter SPI_INIT_WRR_WAIT = 3'b011;
114
 
115
//---------------------------------------------------------
116
// Variable declartion
117
// -------------------------------------------------------
118
logic                 spi_init_done  ;
119
logic   [2:0]         spi_init_state ;
120
logic                spim_mem_req   ;
121
logic                spim_reg_req   ;
122
 
123
 
124
logic                 spim_wb_req    ;
125
logic                 spim_wb_req_l  ;
126
logic [WB_WIDTH-1:0]  spim_wb_wdata  ;
127
logic [WB_WIDTH-1:0]  spim_wb_addr   ;
128
logic                 spim_wb_ack    ;
129
logic                 spim_wb_we     ;
130
logic [3:0]           spim_wb_be     ;
131
logic [WB_WIDTH-1:0]  spim_reg_rdata ;
132
logic [WB_WIDTH-1:0]  spim_wb_rdata  ;
133
logic  [WB_WIDTH-1:0] reg_rdata      ;
134
 
135
// Control Signal Generated from Reg to SPI Access
136
logic                 reg2spi_req;
137
logic         [31:0]  reg2spi_addr;
138
logic          [5:0]  reg2spi_addr_len;
139
logic         [31:0]  reg2spi_cmd;
140
logic          [5:0]  reg2spi_cmd_len;
141
logic          [3:0]  reg2spi_csreg;
142
logic         [15:0]  reg2spi_data_len;
143
logic                 reg2spi_mode_enb; // mode enable
144
logic         [7:0]   reg2spi_mode;     // mode
145
logic         [15:0]  reg2spi_dummy_rd_len;
146
logic         [15:0]  reg2spi_dummy_wr_len;
147
logic                 reg2spi_swrst;
148
logic                 reg2spi_rd;
149
logic                 reg2spi_wr;
150
logic                 reg2spi_qrd;
151
logic                 reg2spi_qwr;
152
logic         [31:0]  reg2spi_wdata;
153
//------------------------------------------------------------------
154
// Priority given to mem2spi request over Reg2Spi
155
 
156
    assign  spi_req           =  (spim_mem_req && !spim_wb_we) ? 1'b1                           : reg2spi_req;
157
    assign  spi_addr          =  (spim_mem_req && !spim_wb_we) ? {spim_wb_addr[23:0],8'h0}      : reg2spi_addr;
158
    assign  spi_addr_len      =  (spim_mem_req && !spim_wb_we) ? 24                             : reg2spi_addr_len;
159
    assign  spi_cmd           =  (spim_mem_req && !spim_wb_we) ? 8'hEB                          : reg2spi_cmd;
160
    assign  spi_cmd_len       =  (spim_mem_req && !spim_wb_we) ? 8                              : reg2spi_cmd_len;
161
    assign  spi_mode_cmd      =  (spim_mem_req && !spim_wb_we) ? 8'h00                          : reg2spi_mode;
162
    assign  spi_mode_cmd_enb  =  (spim_mem_req && !spim_wb_we) ? 1                              : reg2spi_mode_enb;
163
    assign  spi_csreg         =  (spim_mem_req && !spim_wb_we) ? '1                             : reg2spi_csreg;
164
    assign  spi_data_len      =  (spim_mem_req && !spim_wb_we) ? 'h10                           : reg2spi_data_len;
165
    assign  spi_dummy_rd_len  =  (spim_mem_req && !spim_wb_we) ? 16                             : reg2spi_dummy_rd_len;
166
    assign  spi_dummy_wr_len  =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_dummy_wr_len;
167
    assign  spi_swrst         =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_swrst;
168
    assign  spi_rd            =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_rd;
169
    assign  spi_wr            =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_wr;
170
    assign  spi_qrd           =  (spim_mem_req && !spim_wb_we) ? 1                              : reg2spi_qrd;
171
    assign  spi_qwr           =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_qwr;
172
    assign  spi_wdata         =  (spim_mem_req && !spim_wb_we) ? 0                              : reg2spi_wdata;
173
 
174
 
175
 
176
 
177
  //---------------------------------------------------------------
178
  // Address Decoding
179
  // 0x0000_0000 - 0x0FFF_FFFF  - SPI FLASH MEMORY ACCESS - 256MB
180
  // 0x1000_0000 -              - SPI Register Access
181
  // --------------------------------------------------------------
182
 
183
  assign spim_mem_req = ((spim_wb_req) && spim_wb_addr[31:28] == 4'b0000);
184
  assign spim_reg_req = ((spim_wb_req) && spim_wb_addr[31:28] == 4'b0001);
185
 
186
 
187
  assign wbd_dat_o  =  spim_wb_rdata;
188
  assign wbd_ack_o  =  spim_wb_ack;
189
  assign wbd_err_o  =  1'b0;
190
 
191
  // To reduce the load/Timing Wishbone I/F, all the variable are registered
192
always_ff @(negedge rst_n or posedge mclk) begin
193
    if ( rst_n == 1'b0 ) begin
194
        spim_wb_req   <= '0;
195
        spim_wb_req_l <= '0;
196
        spim_wb_wdata <= '0;
197
        spim_wb_rdata <= '0;
198
        spim_wb_addr  <= '0;
199
        spim_wb_be    <= '0;
200
        spim_wb_we    <= '0;
201
        spim_wb_ack   <= '0;
202
   end else begin
203
        spim_wb_req   <= wbd_stb_i;
204
        spim_wb_req_l <= spim_wb_req;
205
        spim_wb_wdata <= wbd_dat_i;
206
        spim_wb_addr  <= wbd_adr_i;
207
        spim_wb_be    <= wbd_sel_i;
208
        spim_wb_we    <= wbd_we_i;
209
 
210
 
211
        // If there is Reg2Spi read Access, Register the Read Data
212
        if(reg2spi_req && (reg2spi_rd || reg2spi_qrd ) && spi_ack)
213
             spim_reg_rdata <= spi_rdata;
214
 
215
        if(!spim_wb_we && spim_wb_req && spi_ack)
216
           spim_wb_rdata <= spi_rdata;
217
        else
218
           spim_wb_rdata <= reg_rdata;
219
 
220
        // For safer design, we have generated ack after 2 cycle latter to
221
        // cross-check current request is towards SPI or not
222
        spim_wb_ack   <= (spi_req) ? spi_ack :
223
                         ((spim_wb_ack==0) && spim_wb_req && spim_wb_req_l) ;
224
   end
225
end
226
 
227
  integer byte_index;
228
  always_ff @(negedge rst_n or posedge mclk) begin
229
    if ( rst_n == 1'b0 ) begin
230
      reg2spi_swrst         <= 1'b0;
231
      reg2spi_rd            <= 1'b0;
232
      reg2spi_wr            <= 1'b0;
233
      reg2spi_qrd           <= 1'b0;
234
      reg2spi_qwr           <= 1'b0;
235
      reg2spi_cmd           <=  'h0;
236
      reg2spi_addr          <=  'h0;
237
      reg2spi_cmd_len       <=  'h0;
238
      reg2spi_addr_len      <=  'h0;
239
      reg2spi_data_len      <=  'h0;
240
      reg2spi_wdata         <=  'h0;
241
      reg2spi_mode_enb      <=  'h0;
242
      reg2spi_mode          <=  'h0;
243
      reg2spi_dummy_rd_len  <=  'h0;
244
      reg2spi_dummy_wr_len  <=  'h0;
245
      reg2spi_csreg         <=  'h0;
246
      reg2spi_req           <=  'h0;
247
      spi_clk_div_valid     <= 1'b0;
248
      spi_clk_div           <=  'h2;
249
      spi_init_done         <=  'h0;
250
      spi_init_state        <=  SPI_INIT_IDLE;
251
    end
252
    else if (spi_init_done == 0) begin
253
       case(spi_init_state)
254
           SPI_INIT_IDLE:
255
           begin
256
              reg2spi_rd        <= 'h0;
257
              reg2spi_wr        <= 'h1; // SPI Write Req
258
              reg2spi_qrd       <= 'h0;
259
              reg2spi_qwr       <= 'h0;
260
              reg2spi_swrst     <= 'h0;
261
              reg2spi_csreg     <= 'h1;
262
              reg2spi_cmd[7:0]  <= 'h6; // WREN command
263
              reg2spi_mode[7:0] <= 'h0;
264
              reg2spi_cmd_len   <= 'h8;
265
              reg2spi_addr_len  <= 'h0;
266
              reg2spi_data_len  <= 'h0;
267
              reg2spi_wdata     <= 'h0;
268
              reg2spi_req       <= 'h1;
269
              spi_init_state    <=  SPI_INIT_CMD_WAIT;
270
           end
271
           SPI_INIT_CMD_WAIT:
272
           begin
273
              if(spi_ack)   begin
274
                 reg2spi_req      <= 1'b0;
275
                 spi_init_state    <=  SPI_INIT_WRR_CMD;
276
              end
277
           end
278
           SPI_INIT_WRR_CMD:
279
           begin
280
              reg2spi_rd        <= 'h0;
281
              reg2spi_wr        <= 'h1; // SPI Write Req
282
              reg2spi_qrd       <= 'h0;
283
              reg2spi_qwr       <= 'h0;
284
              reg2spi_swrst     <= 'h0;
285
              reg2spi_csreg     <= 'h1;
286
              reg2spi_cmd[7:0]  <= 'h1; // WRR command
287
              reg2spi_mode[7:0] <= 'h0;
288
              reg2spi_cmd_len   <= 'h8;
289
              reg2spi_addr_len  <= 'h0;
290
              reg2spi_data_len  <= 'h10;
291
              reg2spi_wdata     <= {8'h0,8'h2,16'h0}; // <<16'h0> cr1[1] = 1 indicate quad mode
292
              reg2spi_req       <= 'h1;
293
              spi_init_state    <=  SPI_INIT_WRR_WAIT;
294
           end
295
           SPI_INIT_WRR_WAIT:
296
           begin
297
              if(spi_ack)   begin
298
                 reg2spi_req      <= 1'b0;
299
                 spi_init_done    <=  'h1;
300
              end
301
           end
302
       endcase
303
    end else if (spim_reg_req & spim_wb_we )
304
    begin
305
      case(spim_wb_addr[7:4])
306
        REG_CTRL:
307
        begin
308
          if ( spim_wb_be[0] == 1 )
309
          begin
310
            reg2spi_rd    <= spim_wb_wdata[0];
311
            reg2spi_wr    <= spim_wb_wdata[1];
312
            reg2spi_qrd   <= spim_wb_wdata[2];
313
            reg2spi_qwr   <= spim_wb_wdata[3];
314
            reg2spi_swrst <= spim_wb_wdata[4];
315
            reg2spi_req   <= 1'b1;
316
          end
317
          if ( spim_wb_be[1] == 1 )
318
          begin
319
            reg2spi_csreg <= spim_wb_wdata[11:8];
320
          end
321
        end
322
        REG_CLKDIV:
323
          if ( spim_wb_be[0] == 1 )
324
          begin
325
            spi_clk_div <= spim_wb_wdata[7:0];
326
            spi_clk_div_valid <= 1'b1;
327
          end
328
        REG_SPICMD: begin
329
          if ( spim_wb_be[0] == 1 )
330
              reg2spi_cmd[7:0] <= spim_wb_wdata[7:0];
331
          if ( spim_wb_be[1] == 1 )
332
              reg2spi_mode[7:0] <= spim_wb_wdata[15:8];
333
          end
334
        REG_SPIADR:
335
          for (byte_index = 0; byte_index < 4; byte_index = byte_index+1 )
336
            if ( spim_wb_be[byte_index] == 1 )
337
              reg2spi_addr[byte_index*8 +: 8] <= spim_wb_wdata[(byte_index*8) +: 8];
338
        REG_SPILEN:
339
        begin
340
          if ( spim_wb_be[0] == 1 ) begin
341
               reg2spi_mode_enb <= spim_wb_wdata[6];
342
               reg2spi_cmd_len  <= spim_wb_wdata[5:0];
343
          end
344
          if ( spim_wb_be[1] == 1 )
345
            reg2spi_addr_len <= spim_wb_wdata[13:8];
346
          if ( spim_wb_be[2] == 1 )
347
            reg2spi_data_len[7:0] <= spim_wb_wdata[23:16];
348
          if ( spim_wb_be[3] == 1 )
349
            reg2spi_data_len[15:8] <= spim_wb_wdata[31:24];
350
        end
351
        REG_SPIDUM:
352
        begin
353
          if ( spim_wb_be[0] == 1 )
354
            reg2spi_dummy_rd_len[7:0]  <= spim_wb_wdata[7:0];
355
          if ( spim_wb_be[1] == 1 )
356
            reg2spi_dummy_rd_len[15:8] <= spim_wb_wdata[15:8];
357
          if ( spim_wb_be[2] == 1 )
358
            reg2spi_dummy_wr_len[7:0]  <= spim_wb_wdata[23:16];
359
          if ( spim_wb_be[3] == 1 )
360
            reg2spi_dummy_wr_len[15:8] <= spim_wb_wdata[31:24];
361
        end
362
        REG_SPIWDATA: begin
363
           reg2spi_wdata     <= spim_wb_wdata;
364
        end
365
      endcase
366
    end
367
    else
368
    begin
369
      if(spi_ack && spim_reg_req)
370
         reg2spi_req <= 1'b0;
371
    end
372
  end
373
 
374
 
375
  // implement slave model register read mux
376
  always_comb
377
    begin
378
      reg_rdata = '0;
379
      case(spim_wb_addr[7:4])
380
        REG_CTRL:
381
                reg_rdata[31:0] =  { 20'h0,
382
                                     reg2spi_csreg,
383
                                     3'b0,
384
                                     reg2spi_swrst,
385
                                     reg2spi_qwr,
386
                                     reg2spi_qrd,
387
                                     reg2spi_wr,
388
                                     reg2spi_rd};
389
 
390
        REG_CLKDIV:
391
                reg_rdata[31:0] = {24'h0,spi_clk_div};
392
        REG_SPICMD:
393
                reg_rdata[31:0] = {16'h0,reg2spi_mode,reg2spi_cmd};
394
        REG_SPIADR:
395
                reg_rdata[31:0] = reg2spi_addr;
396
        REG_SPILEN:
397
                reg_rdata[31:0] = {reg2spi_data_len,2'b00,reg2spi_addr_len,1'b0,reg2spi_mode_enb,reg2spi_cmd_len};
398
        REG_SPIDUM:
399
                reg_rdata[31:0] = {reg2spi_dummy_wr_len,reg2spi_dummy_rd_len};
400
        REG_SPIWDATA:
401
                reg_rdata[31:0] = reg2spi_wdata;
402
        REG_SPIRDATA:
403
                reg_rdata[31:0] = spim_reg_rdata;
404
        REG_STATUS:
405
                reg_rdata[31:0] = {24'h0,spi_status};
406
      endcase
407
    end
408
 
409
 
410
endmodule

powered by: WebSVN 2.1.0

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