2 * Multi-port ZBT SRAM WISHBONE controller
3 * Copyright (C) 2008 Sebastien Bourdeauducq - http://lekernel.net
4 * This file is part of Milkymist.
6 * Milkymist is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Library General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your option)
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 GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 // Wishbone bus A, highest priority, with prefetch
26 input [31:0] wbA_adr_i,
27 input [31:0] wbA_dat_i,
28 output [31:0] wbA_dat_o,
29 input [ 3:0] wbA_sel_i,
34 // Wishbone bus B, lower priority
35 input [31:0] wbB_adr_i,
36 input [31:0] wbB_dat_i,
37 output [31:0] wbB_dat_o,
38 input [ 3:0] wbB_sel_i,
48 output [ 3:0] sram_bw,
56 assign sram_clk = clk;
57 assign sram_oe = 1'b0;
58 assign sram_ce = 1'b0;
59 assign sram_adv = 1'b0;
60 assign sram_mode = 1'b0;
61 assign sram_zz = 1'b0;
63 /* Wishbone decoding */
68 assign busA_active = wbA_cyc_i & wbA_stb_i;
69 assign busB_active = wbB_cyc_i & wbB_stb_i;
71 /* Those are used to represent the state of the SRAM pipeline
72 * Bit 0 = Write Enable
73 * Bits 18..1 = Address
75 wire [18:0] pipeline_in;
76 reg [18:0] pipeline_internal;
77 reg [18:0] pipeline_out;
79 always @(posedge clk or posedge rst) begin
81 pipeline_internal <= 0;
84 pipeline_internal <= pipeline_in;
85 pipeline_out <= pipeline_internal;
89 /* Pipeline contents decode */
94 assign inprogressA = (pipeline_internal[18:1] == wbA_adr_i[19:2]) & (pipeline_internal[0] == wbA_we_i);
95 assign inprogressB = (pipeline_internal[18:1] == wbB_adr_i[19:2]) & (pipeline_internal[0] == wbB_we_i);
100 assign hitA = (pipeline_out[18:1] == wbA_adr_i[19:2]) & (pipeline_out[0] == wbA_we_i);
101 assign hitB = (pipeline_out[18:1] == wbB_adr_i[19:2]) & (pipeline_out[0] == wbB_we_i);
103 /* Access arbitration */
105 wire [1:0] bus_request;
107 assign bus_request[0] = busA_active & ~inprogressA & ~hitA;
108 assign bus_request[1] = busB_active & ~inprogressB & ~hitB;
110 wire prefetch_enable;
111 reg [17:0] prefetch_address;
113 assign prefetch_enable = ~bus_request[0] & ~bus_request[1];
114 always @(posedge clk) begin
116 prefetch_address <= wbA_adr_i[19:2] + 2;
118 prefetch_address <= wbA_adr_i[19:2] + 1;
121 wire [1:0] bus_selected;
123 assign bus_selected[0] = bus_request[0];
124 assign bus_selected[1] = bus_request[1] & ~bus_request[0];
126 assign pipeline_in[18:1] = ({18{bus_selected[0]}} & wbA_adr_i[19:2])
127 | ({18{bus_selected[1]}} & wbB_adr_i[19:2])
128 | ({18{prefetch_enable}} & prefetch_address);
129 assign pipeline_in[0] = (bus_selected[0] & wbA_we_i)|(bus_selected[1] & wbB_we_i);
133 assign sram_a = pipeline_in[18:1];
134 assign sram_bw = ~(({4{bus_selected[0]}} & wbA_sel_i)|({4{bus_selected[1]}} & wbB_sel_i));
135 assign sram_we = ~pipeline_in[0];
139 wire [31:0] bus_wdata;
141 assign wbA_ack_o = busA_active & hitA;
142 assign wbB_ack_o = busB_active & hitB;
144 assign bus_wdata = ({32{hitA}} & wbA_dat_i)|({32{hitB}} & wbB_dat_i);
145 assign sram_d = pipeline_out[0] ? bus_wdata : 32'hzzzzzzzz;
146 assign wbA_dat_o = sram_d;
147 assign wbB_dat_o = sram_d;