1 |
2 |
csantifort |
//////////////////////////////////////////////////////////////////
|
2 |
|
|
// //
|
3 |
|
|
// Wishbone Slave to Xilinx MCB (DDR3 controller) Bridge //
|
4 |
|
|
// //
|
5 |
|
|
// This file is part of the Amber project //
|
6 |
|
|
// http://www.opencores.org/project,amber //
|
7 |
|
|
// //
|
8 |
|
|
// Description //
|
9 |
|
|
// Converts wishbone read and write accesses to the signalling //
|
10 |
|
|
// used by the Xilinx DDR3 Controller in Spartan-6 FPGAs. //
|
11 |
|
|
// //
|
12 |
|
|
// The MCB is confgiured with a single 128-bit port. //
|
13 |
|
|
// //
|
14 |
|
|
// Author(s): //
|
15 |
|
|
// - Conor Santifort, csantifort.amber@gmail.com //
|
16 |
|
|
// //
|
17 |
|
|
//////////////////////////////////////////////////////////////////
|
18 |
|
|
// //
|
19 |
|
|
// Copyright (C) 2010 Authors and OPENCORES.ORG //
|
20 |
|
|
// //
|
21 |
|
|
// This source file may be used and distributed without //
|
22 |
|
|
// restriction provided that this copyright statement is not //
|
23 |
|
|
// removed from the file and that any derivative work contains //
|
24 |
|
|
// the original copyright notice and the associated disclaimer. //
|
25 |
|
|
// //
|
26 |
|
|
// This source file is free software; you can redistribute it //
|
27 |
|
|
// and/or modify it under the terms of the GNU Lesser General //
|
28 |
|
|
// Public License as published by the Free Software Foundation; //
|
29 |
|
|
// either version 2.1 of the License, or (at your option) any //
|
30 |
|
|
// later version. //
|
31 |
|
|
// //
|
32 |
|
|
// This source is distributed in the hope that it will be //
|
33 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied //
|
34 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
|
35 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more //
|
36 |
|
|
// details. //
|
37 |
|
|
// //
|
38 |
|
|
// You should have received a copy of the GNU Lesser General //
|
39 |
|
|
// Public License along with this source; if not, download it //
|
40 |
|
|
// from http://www.opencores.org/lgpl.shtml //
|
41 |
|
|
// //
|
42 |
|
|
//////////////////////////////////////////////////////////////////
|
43 |
|
|
|
44 |
|
|
|
45 |
|
|
module wb_ddr3_bridge
|
46 |
|
|
(
|
47 |
|
|
input i_clk,
|
48 |
|
|
|
49 |
|
|
// MBus Ports
|
50 |
|
|
input [31:0] i_wb_adr,
|
51 |
|
|
input [3:0] i_wb_sel,
|
52 |
|
|
input i_wb_we,
|
53 |
|
|
output reg [31:0] o_wb_dat = 'd0,
|
54 |
|
|
input [31:0] i_wb_dat,
|
55 |
|
|
input i_wb_cyc,
|
56 |
|
|
input i_wb_stb,
|
57 |
|
|
output o_wb_ack,
|
58 |
|
|
output o_wb_err,
|
59 |
|
|
|
60 |
|
|
output reg o_cmd_en = 'd0, // Command Enable
|
61 |
|
|
output reg [2:0] o_cmd_instr = 'd0, // write = 000, read = 001
|
62 |
|
|
output reg [29:0] o_cmd_byte_addr = 'd0, // Memory address
|
63 |
|
|
input i_cmd_full, // DDR3 I/F Command FIFO is full
|
64 |
|
|
|
65 |
|
|
input i_wr_full, // DDR3 I/F Write Data FIFO is full
|
66 |
|
|
output reg o_wr_en = 'd0, // Write data enable
|
67 |
|
|
output reg [15:0] o_wr_mask = 'd0, // 1 bit per byte
|
68 |
|
|
output reg [127:0] o_wr_data = 'd0, // 16 bytes write data
|
69 |
|
|
input [127:0] i_rd_data, // 16 bytes of read data
|
70 |
|
|
input i_rd_empty // low when read data is valid
|
71 |
|
|
|
72 |
|
|
);
|
73 |
|
|
|
74 |
|
|
wire start_write;
|
75 |
|
|
wire start_read;
|
76 |
|
|
reg start_write_d1;
|
77 |
|
|
reg start_read_d1;
|
78 |
|
|
reg start_read_hold = 'd0;
|
79 |
|
|
reg [31:0] wb_adr_d1;
|
80 |
|
|
wire ddr3_busy;
|
81 |
|
|
reg read_ack = 'd0;
|
82 |
|
|
reg read_ready = 1'd1;
|
83 |
|
|
|
84 |
|
|
assign start_write = i_wb_stb && i_wb_we && !start_read_d1;
|
85 |
|
|
assign start_read = i_wb_stb && !i_wb_we && read_ready;
|
86 |
|
|
assign ddr3_busy = i_cmd_full || i_wr_full;
|
87 |
|
|
|
88 |
|
|
assign o_wb_err = 'd0;
|
89 |
|
|
|
90 |
|
|
// ------------------------------------------------------
|
91 |
|
|
// Outputs
|
92 |
|
|
// ------------------------------------------------------
|
93 |
|
|
|
94 |
|
|
// Command FIFO
|
95 |
|
|
always @( posedge i_clk )
|
96 |
|
|
begin
|
97 |
|
|
o_cmd_byte_addr <= {wb_adr_d1[29:4], 4'd0};
|
98 |
|
|
o_cmd_en <= !ddr3_busy && ( start_write_d1 || start_read_d1 );
|
99 |
|
|
o_cmd_instr <= start_write_d1 ? 3'd0 : 3'd1;
|
100 |
|
|
end
|
101 |
|
|
|
102 |
|
|
|
103 |
|
|
// ------------------------------------------------------
|
104 |
|
|
// Write
|
105 |
|
|
// ------------------------------------------------------
|
106 |
|
|
always @( posedge i_clk )
|
107 |
|
|
begin
|
108 |
|
|
o_wr_en <= start_write;
|
109 |
|
|
|
110 |
|
|
`ifdef XILINX_VIRTEX6_FPGA
|
111 |
|
|
o_wr_mask <= i_wb_adr[2] == 2'd2 ? { 8'h0, 4'hf, ~i_wb_sel } :
|
112 |
|
|
{ 8'h0, ~i_wb_sel, 4'hf } ;
|
113 |
|
|
`else
|
114 |
|
|
o_wr_mask <= i_wb_adr[3:2] == 2'd0 ? { 12'hfff, ~i_wb_sel } :
|
115 |
|
|
i_wb_adr[3:2] == 2'd1 ? { 8'hff, ~i_wb_sel, 4'hf } :
|
116 |
|
|
i_wb_adr[3:2] == 2'd2 ? { 4'hf, ~i_wb_sel, 8'hff } :
|
117 |
|
|
{ ~i_wb_sel, 12'hfff } ;
|
118 |
|
|
`endif
|
119 |
|
|
|
120 |
|
|
o_wr_data <= {4{i_wb_dat}};
|
121 |
|
|
end
|
122 |
|
|
|
123 |
|
|
|
124 |
|
|
// ------------------------------------------------------
|
125 |
|
|
// Read
|
126 |
|
|
// ------------------------------------------------------
|
127 |
|
|
|
128 |
|
|
always @( posedge i_clk )
|
129 |
|
|
begin
|
130 |
|
|
if ( read_ack )
|
131 |
|
|
read_ready <= 1'd1;
|
132 |
|
|
else if ( start_read )
|
133 |
|
|
read_ready <= 1'd0;
|
134 |
|
|
|
135 |
|
|
start_write_d1 <= start_write;
|
136 |
|
|
start_read_d1 <= start_read;
|
137 |
|
|
wb_adr_d1 <= i_wb_adr;
|
138 |
|
|
|
139 |
|
|
if ( start_read )
|
140 |
|
|
start_read_hold <= 1'd1;
|
141 |
|
|
else if ( read_ack )
|
142 |
|
|
start_read_hold <= 1'd0;
|
143 |
|
|
|
144 |
|
|
if ( i_rd_empty == 1'd0 && start_read_hold )
|
145 |
|
|
begin
|
146 |
|
|
`ifdef XILINX_VIRTEX6_FPGA
|
147 |
|
|
o_wb_dat <= i_wb_adr[2] == 2'd2 ? i_rd_data[ 31:0] :
|
148 |
|
|
i_rd_data[ 63:32] ;
|
149 |
|
|
`else
|
150 |
|
|
o_wb_dat <= i_wb_adr[3:2] == 2'd0 ? i_rd_data[ 31: 0] :
|
151 |
|
|
i_wb_adr[3:2] == 2'd1 ? i_rd_data[ 63:32] :
|
152 |
|
|
i_wb_adr[3:2] == 2'd2 ? i_rd_data[ 95:64] :
|
153 |
|
|
i_rd_data[127:96] ;
|
154 |
|
|
`endif
|
155 |
|
|
read_ack <= 1'd1;
|
156 |
|
|
end
|
157 |
|
|
else
|
158 |
|
|
read_ack <= 1'd0;
|
159 |
|
|
end
|
160 |
|
|
|
161 |
|
|
assign o_wb_ack = i_wb_stb && ( start_write || read_ack );
|
162 |
|
|
|
163 |
|
|
|
164 |
|
|
// Debug DDR3 - Wishbone Bridge - not synthesizable
|
165 |
|
|
// ========================================================
|
166 |
|
|
//synopsys translate_off
|
167 |
|
|
|
168 |
|
|
`ifdef LP_MEMIF_DEBUG
|
169 |
|
|
always @( posedge i_clk )
|
170 |
|
|
begin
|
171 |
|
|
if (start_write)
|
172 |
|
|
$display("DDR3 Write Addr 0x%08x Data 0x%08h %08h %08h %08h, BE %d%d%d%d %d%d%d%d %d%d%d%d %d%d%d%d",
|
173 |
|
|
i_i_wb_adr, i_mwdata[127:96], i_mwdata[95:64], i_mwdata[63:32], i_mwdata[31:0],
|
174 |
|
|
i_mwben[15], i_mwben[14], i_mwben[13], i_mwben[12],
|
175 |
|
|
i_mwben[11], i_mwben[10], i_mwben[9], i_mwben[8],
|
176 |
|
|
i_mwben[7], i_mwben[6], i_mwben[5], i_mwben[4],
|
177 |
|
|
i_mwben[3], i_mwben[2], i_mwben[1], i_mwben[0]
|
178 |
|
|
);
|
179 |
|
|
|
180 |
|
|
if (i_rd_empty == 1'd0)
|
181 |
|
|
$display("DDR3 Read Addr 0x%08x Data 0x%08h %08h %08h %08h",
|
182 |
|
|
i_i_wb_adr, i_rd_data[127:96], i_rd_data [95:64], i_rd_data [63:32], i_rd_data [31:0]);
|
183 |
|
|
end
|
184 |
|
|
`endif
|
185 |
|
|
//synopsys translate_on
|
186 |
|
|
|
187 |
|
|
|
188 |
|
|
endmodule
|
189 |
|
|
|