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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [boards/] [xilinx/] [ml501/] [rtl/] [verilog/] [xilinx_ssram/] [xilinx_ssram.v] - Blame information for rev 856

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

Line No. Rev Author Line
1 412 julius
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  Xilinx ML501 SSRAM controller with Wishbone Interface       ////
4
////                                                              ////
5
////  Description                                                 ////
6
////  ZBT SSRAM controller for ML501 board part (or any ZBT RAM)  ////
7
////  Timing relies on definition of multi-cycle paths during     ////
8
////  synthesis.                                                  ////
9
////                                                              ////
10
////  To Do:                                                      ////
11
////                                                              ////
12
////  Author(s):                                                  ////
13
////      - Julius Baxter, julius.baxter@orsoc.se                 ////
14
////                                                              ////
15
////                                                              ////
16
//////////////////////////////////////////////////////////////////////
17
////                                                              ////
18
//// Copyright (C) 2010 Authors and OPENCORES.ORG                 ////
19
////                                                              ////
20
//// This source file may be used and distributed without         ////
21
//// restriction provided that this copyright statement is not    ////
22
//// removed from the file and that any derivative work contains  ////
23
//// the original copyright notice and the associated disclaimer. ////
24
////                                                              ////
25
//// This source file is free software; you can redistribute it   ////
26
//// and/or modify it under the terms of the GNU Lesser General   ////
27
//// Public License as published by the Free Software Foundation; ////
28
//// either version 2.1 of the License, or (at your option) any   ////
29
//// later version.                                               ////
30
////                                                              ////
31
//// This source is distributed in the hope that it will be       ////
32
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
33
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
34
//// PURPOSE.  See the GNU Lesser General Public License for more ////
35
//// details.                                                     ////
36
////                                                              ////
37
//// You should have received a copy of the GNU Lesser General    ////
38
//// Public License along with this source; if not, download it   ////
39
//// from http://www.opencores.org/lgpl.shtml                     ////
40
////                                                              ////
41
//////////////////////////////////////////////////////////////////////
42
/*
43
 * Controller for ZBT synchronous SRAM (ISSI IS61NLP25636A-200TQL)
44
 * Explicitly uses Xilinx primitives
45
 * Currently configured for a 1/4 ratio between bus/ssram clocks: 50 / 200 MHz
46
 * Requires declaration of some multi-cycle paths during synthesis.
47
 *
48
 * Note: clk_200 and bus clock should be in phase (from same DCM)
49
 *
50
 * Clocking/phase counting scheme (to change it to higher/lower ratio):
51
 *
52
 * We run a phase counter, checking the bus on the last cycle before we hit another multiple of the SSRAM clock to the bus clock (so cycle 3 if ratio is 4, or a 50MHz system bus and 200MHz SRAM), this gives the system bus signals almost another whole cycle to reach our 200MHz regs (and where we define one of the multi-cycle paths). Once we have the stuff registered it's business as usual on the bus to the SRAM. Then we let it sit in our register for a clock or two
53
 */
54
module xilinx_ssram
55
  (
56
   // WB ports
57
    input [31:0]       wb_adr_i,
58
    input              wb_stb_i,
59
    input              wb_cyc_i,
60
    input              wb_we_i,
61
    input [3:0]        wb_sel_i,
62
    input [31:0]       wb_dat_i,
63
    output [31:0]      wb_dat_o,
64
    output             wb_ack_o,
65
 
66
    input              wb_clk,
67
    input              wb_rst,
68
 
69
   // SSRAM interface
70
    input              clk_200,
71
    output wire        sram_clk,
72
    input              sram_clk_fb,
73
    output reg [21:1]  sram_addr,
74
    inout [31:0]       sram_dq_io,
75
    output reg         sram_ce_l,
76
    output reg         sram_oe_l,
77
    output reg         sram_we_l,
78
    output reg [3:0]   sram_bw_l,
79
    output reg         sram_adv_ld_l,
80
    output             sram_mode
81
 
82
   );
83
 
84
   wire [31:0]          sram_dq_i;
85
   reg [31:0]           sram_dq_o;
86
   reg                 ssram_controller_oe_l;
87
 
88
   wire                dcm0_clk0_prebufg, dcm0_clk0;
89
   wire                dcm0_locked;
90
 
91
   wire                dcms_locked;
92
 
93
   reg                 wb_clk_r = 1'b0;
94
   reg                 wb_clk_r_d;
95
   wire                wb_clk_edge;
96
 
97
   reg                 wb_ack_write;
98
   reg [2:0]            wb_ack_read_shiftreg;
99
 
100
   reg [2:0]            clk_200_phase;
101
   reg [4:0]            clk_200_cycle_counter;
102
 
103
   reg [31:0]           data_rd;
104
   wire [3:0]           we;
105
 
106
   reg                 write_cycle;
107
   reg [3:0]            we_r;
108
   reg                 reg_from_bus_domain, reg_from_bus_domain_r;
109
 
110
   assign dcms_locked = dcm0_locked;
111
 
112
   assign we = wb_sel_i & {4{wb_cyc_i & wb_stb_i & wb_we_i}};
113
 
114
   assign sram_clk = dcm0_clk0;
115
 
116
   // Do wb_clk edge detection with this
117
   assign wb_clk_edge = wb_clk_r & ~wb_clk_r_d;
118
 
119
   assign sram_mode = 0;
120
 
121
   initial begin
122
      $display("* SSRAM controller instantiated at %m.");
123
   end
124
 
125
   // We ACK writes after one cycle
126
   always @(posedge wb_clk)
127
     wb_ack_write <= wb_cyc_i & wb_stb_i & wb_we_i & !wb_ack_write;
128
 
129
   // We ACK reads after 3
130
   always @(posedge wb_clk)
131
     wb_ack_read_shiftreg <= {wb_ack_read_shiftreg[1:0], wb_cyc_i & wb_stb_i & !wb_we_i & !(|wb_ack_read_shiftreg)};
132
 
133
   assign wb_ack_o = wb_we_i ? wb_ack_write : wb_ack_read_shiftreg[2];
134
 
135
   // Push the bus clock through a register
136
   always @(posedge wb_clk) begin
137
      wb_clk_r <= ~wb_clk_r;
138
   end
139
 
140
   // Sample this with the 150 MHz clock
141
   always @(posedge clk_200) begin
142
      wb_clk_r_d <= wb_clk_r;
143
   end
144
 
145
  // Maintain a phase count, it goes 0->7 (8 phases, to be clear)
146
  always @(posedge clk_200) begin
147
    if (wb_clk_edge) begin
148
      // Will be at 1 next cycle
149
      clk_200_phase <= 3'd1;
150
    end else if (clk_200_phase < 3'd7 & dcms_locked) begin
151
      clk_200_phase <= clk_200_phase + 1;
152
    end else begin
153
      clk_200_phase <= 3'd0;
154
    end
155
  end
156
 
157
// Multicycle trickery
158
 
159
   // Reads will happen like this:
160
   // * Read address is given 3 clk_200 cycles to settle
161
   // * It is put onto the bus for two cycles
162
   // * Read data is then registered
163
   // * It then has several phases to make it back to the bus register
164
 
165
   // Number of cycles we preload counter with, depending on access
166
`define WRITE_CYCLES 5'h04
167
`define READ_CYCLES  5'h0c
168
 
169
   // We let the commands settle for 2 cycles (0, 1) and then sample
170
   // *but* data could have come on either cycle 0 _or_ 3, so check both
171
`define REQ_CHECK_CYCLE ((clk_200_phase == 3'd3)||(clk_200_phase == 3'd7))
172
 
173
   // Write OE - whole time, doesn't matter so much
174
`define WRITE_OE_CYCLE  (|clk_200_cycle_counter)
175
   // Read OE, just the first  two cycles
176
//`define READ_OE_CYCLE  (clk_200_cycle_counter > (`READ_CYCLES - 5'h4))
177
`define READ_OE_CYCLE  (|clk_200_cycle_counter)
178
 
179
   // Sample data from RAM 2 cycles after we sample the addr from system bus
180
`define RAM_DATA_SAMPLE_CYCLE (!(|we_r) && clk_200_cycle_counter == (`READ_CYCLES - 5'h5))
181
 
182
   // Cycle when we pull sram_we_l low   
183
`define WRITE_CE_CYCLE (reg_from_bus_domain & (|we))
184
   // Cycle when we ouptut the CE
185
`define READ_CE_CYCLE (reg_from_bus_domain & !(|we))
186
 
187
   // Register stuff when we've just loaded the counter
188
`define REG_FROM_BUS_DOMAIN reg_from_bus_domain
189
 
190
   // CE 2 cycles dring writes, only one during reads
191
   always @(posedge clk_200)
192
     sram_ce_l <= 0;
193
     //sram_ce_l <= ~((`WRITE_CE_CYCLE) || (`READ_CE_CYCLE ));
194
 
195
 
196
   always @(posedge clk_200)
197
     sram_adv_ld_l <= 0;
198
     //sram_adv_ld_l <= ~((`WRITE_CE_CYCLE) || (`READ_CE_CYCLE ));
199
 
200
   always @(posedge clk_200)
201
     sram_we_l <= ~(`WRITE_CE_CYCLE);
202
 
203
   always @(posedge clk_200)
204
     if (`REG_FROM_BUS_DOMAIN)
205
       sram_addr[21:1] <= wb_adr_i[22:2];
206
 
207
   always @(posedge clk_200)
208
     if (`REG_FROM_BUS_DOMAIN)
209
       sram_dq_o <= wb_dat_i;
210
 
211
   always @(posedge clk_200)
212
     if (`REG_FROM_BUS_DOMAIN)
213
       sram_bw_l <= ~we;
214
 
215
   always @(posedge clk_200)
216
     sram_oe_l <= ~((`READ_OE_CYCLE) & !(|(we_r | we)));
217
 
218
   always @(posedge clk_200)
219
     ssram_controller_oe_l = ~((`WRITE_OE_CYCLE) & (|we_r));
220
 
221
   // Register data from SSRAM
222
   always @(posedge clk_200)
223
     if (`RAM_DATA_SAMPLE_CYCLE)
224
       data_rd[31:0] <= sram_dq_i[31:0];
225
 
226
   assign wb_dat_o = data_rd;
227
 
228
   // Determine if we've got a request
229
   // This logic means the bus' control signals are slightly
230
   // more constrained than the data and address.
231
   always @(posedge clk_200)
232
     begin
233
        if (|clk_200_cycle_counter)
234
          clk_200_cycle_counter <= clk_200_cycle_counter - 1;
235
        else if (`REQ_CHECK_CYCLE)
236
          if (wb_cyc_i & wb_stb_i)
237
               clk_200_cycle_counter <= wb_we_i ?
238
                                               `WRITE_CYCLES : `READ_CYCLES;
239
          else
240
               clk_200_cycle_counter <= 0;
241
     end // always @ (posedge clk_200)
242
 
243
   always @(posedge clk_200)
244
     begin
245
        reg_from_bus_domain <= ((`REQ_CHECK_CYCLE) & wb_cyc_i & wb_stb_i & !(|clk_200_cycle_counter));
246
        reg_from_bus_domain_r <= reg_from_bus_domain;
247
     end
248
 
249
   // Must clear 
250
   always @(posedge clk_200)
251
     if (`REG_FROM_BUS_DOMAIN)
252
       we_r <= we;
253
     else if (!(|clk_200_cycle_counter))
254
       we_r <= 0;
255
 
256
 
257
   /* SSRAM Clocking configuration */
258
 
259
   /* DCM de-skewing SSRAM clock via external trace */
260
   DCM_BASE dcm0
261
     (/*AUTOINST*/
262
      // Outputs
263
      .CLK0                              (dcm0_clk0_prebufg),
264
      .CLK180                            (),
265
      .CLK270                            (),
266
      .CLK2X180                          (),
267
      .CLK2X                             (),
268
      .CLK90                             (),
269
      .CLKDV                             (),
270
      .CLKFX180                          (),
271
      .CLKFX                             (),
272
      .LOCKED                            (dcm0_locked),
273
      // Inputs
274
      .CLKFB                             (sram_clk_fb),
275
      .CLKIN                             (clk_200),
276
      .RST                               (wb_rst));
277
 
278
   BUFG dcm0_clk0_bufg
279
     (// Outputs
280
      .O                                 (dcm0_clk0),
281
      // Inputs
282
      .I                                 (dcm0_clk0_prebufg));
283
 
284
   /* Generate the DQ bus tristate buffers */
285
   genvar i;
286
   generate
287
      for (i=0; i<32; i=i+1) begin: SSRAM_DQ_TRISTATE
288
         IOBUF U (.O(sram_dq_i[i]),
289
                  .IO(sram_dq_io[i]),
290
                  .I(sram_dq_o[i]),
291
                  .T(ssram_controller_oe_l));
292
      end
293
   endgenerate
294
 
295
endmodule // xilinx_ssram
296
 
297
// Local Variables:
298
// verilog-library-directories:(".")
299
// verilog-library-extensions:(".v" ".h")
300
// End:

powered by: WebSVN 2.1.0

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