Line 41... |
Line 41... |
// from http://www.opencores.org/lgpl.shtml //
|
// from http://www.opencores.org/lgpl.shtml //
|
// //
|
// //
|
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
module wb_xs6_ddr3_bridge
|
module wb_xs6_ddr3_bridge #(
|
(
|
parameter WB_DWIDTH = 32,
|
|
parameter WB_SWIDTH = 4
|
|
)(
|
input i_clk,
|
input i_clk,
|
|
|
input i_mem_ctrl, // 0=128MB, 1=32MB
|
input i_mem_ctrl, // 0=128MB, 1=32MB
|
|
|
// Wishbone Bus
|
// Wishbone Bus
|
input [31:0] i_wb_adr,
|
input [31:0] i_wb_adr,
|
input [3:0] i_wb_sel,
|
input [WB_SWIDTH-1:0] i_wb_sel,
|
input i_wb_we,
|
input i_wb_we,
|
output reg [31:0] o_wb_dat = 'd0,
|
output reg [WB_DWIDTH-1:0] o_wb_dat = 'd0,
|
input [31:0] i_wb_dat,
|
input [WB_DWIDTH-1:0] i_wb_dat,
|
input i_wb_cyc,
|
input i_wb_cyc,
|
input i_wb_stb,
|
input i_wb_stb,
|
output o_wb_ack,
|
output o_wb_ack,
|
output o_wb_err,
|
output o_wb_err,
|
|
|
Line 72... |
Line 74... |
input [127:0] i_rd_data, // 16 bytes of read data
|
input [127:0] i_rd_data, // 16 bytes of read data
|
input i_rd_empty // low when read data is valid
|
input i_rd_empty // low when read data is valid
|
|
|
);
|
);
|
|
|
wire start_write;
|
wire write_request;
|
wire start_read;
|
wire read_request;
|
reg start_write_d1;
|
reg write_request_r;
|
reg start_read_d1;
|
reg read_request_r;
|
reg start_read_hold = 'd0;
|
reg read_active_r = 'd0;
|
reg [29:0] wb_adr_d1;
|
reg [29:0] wb_adr_r;
|
wire ddr3_busy;
|
reg cmd_full_r = 1'd0;
|
reg read_ack = 'd0;
|
reg read_ack_r = 'd0;
|
reg read_ready = 1'd1;
|
reg read_ready = 1'd1;
|
reg cmd_en_r = 'd0;
|
reg cmd_en_r = 'd0;
|
reg wr_en_r = 'd0;
|
reg wr_en_r = 'd0;
|
|
wire write_ack;
|
|
|
assign start_write = i_wb_stb && i_wb_we && !start_read_d1;
|
// Buffer 1 write request
|
assign start_read = i_wb_stb && !i_wb_we && read_ready;
|
reg write_buf_r = 1'd0;
|
assign ddr3_busy = i_cmd_full;// || i_wr_full;
|
reg [WB_SWIDTH-1:0] wb_sel_buf_r = 'd0;
|
|
reg [WB_DWIDTH-1:0] wb_dat_buf_r = 'd0;
|
|
reg [31:0] wb_adr_buf_r = 'd0;
|
|
wire [WB_SWIDTH-1:0] wb_sel;
|
|
wire [WB_DWIDTH-1:0] wb_dat;
|
|
wire [31:0] wb_adr;
|
|
|
|
|
|
assign write_request = i_wb_stb && i_wb_we && !read_request_r;
|
|
assign read_request = i_wb_stb && !i_wb_we && read_ready;
|
|
|
assign o_wb_err = 'd0;
|
assign o_wb_err = 'd0;
|
|
|
// ------------------------------------------------------
|
// ------------------------------------------------------
|
// Outputs
|
// Outputs
|
// ------------------------------------------------------
|
// ------------------------------------------------------
|
|
always @( posedge i_clk )
|
|
cmd_full_r <= i_cmd_full;
|
|
|
// Command FIFO
|
// Command FIFO
|
always @( posedge i_clk )
|
always @( posedge i_clk )
|
if ( !ddr3_busy )
|
if ( !i_cmd_full )
|
begin
|
begin
|
o_cmd_byte_addr <= {wb_adr_d1[29:4], 4'd0};
|
o_cmd_byte_addr <= {wb_adr_r[29:4], 4'd0};
|
cmd_en_r <= ( start_write_d1 || start_read_d1 );
|
cmd_en_r <= ( write_request_r || read_request_r );
|
o_cmd_instr <= start_write_d1 ? 3'd0 : 3'd1;
|
o_cmd_instr <= write_request_r ? 3'd0 : 3'd1;
|
end
|
end
|
|
|
assign o_cmd_en = cmd_en_r && !i_cmd_full;
|
assign o_cmd_en = cmd_en_r && !i_cmd_full;
|
|
|
|
|
|
// ------------------------------------------------------
|
|
// Write Buffer
|
|
// ------------------------------------------------------
|
|
always @( posedge i_clk )
|
|
if ( i_cmd_full && write_request )
|
|
begin
|
|
write_buf_r <= 1'd1;
|
|
wb_sel_buf_r <= i_wb_sel;
|
|
wb_dat_buf_r <= i_wb_dat;
|
|
wb_adr_buf_r <= i_wb_adr;
|
|
end
|
|
else if ( !i_cmd_full )
|
|
write_buf_r <= 1'd0;
|
|
|
// ------------------------------------------------------
|
// ------------------------------------------------------
|
// Write
|
// Write
|
// ------------------------------------------------------
|
// ------------------------------------------------------
|
|
|
|
// Select between incoming reqiests and the write request buffer
|
|
assign wb_sel = write_buf_r ? wb_sel_buf_r : i_wb_sel;
|
|
assign wb_dat = write_buf_r ? wb_dat_buf_r : i_wb_dat;
|
|
assign wb_adr = write_buf_r ? wb_adr_buf_r : i_wb_adr;
|
|
|
|
|
|
generate
|
|
if (WB_DWIDTH == 32) begin :wb32w
|
|
|
always @( posedge i_clk )
|
always @( posedge i_clk )
|
if ( !ddr3_busy )
|
if ( !i_cmd_full )
|
begin
|
begin
|
wr_en_r <= start_write;
|
wr_en_r <= write_request || write_buf_r;
|
|
|
o_wr_mask <= i_wb_adr[3:2] == 2'd0 ? { 12'hfff, ~i_wb_sel } :
|
o_wr_mask <= wb_adr[3:2] == 2'd0 ? { 12'hfff, ~wb_sel } :
|
i_wb_adr[3:2] == 2'd1 ? { 8'hff, ~i_wb_sel, 4'hf } :
|
wb_adr[3:2] == 2'd1 ? { 8'hff, ~wb_sel, 4'hf } :
|
i_wb_adr[3:2] == 2'd2 ? { 4'hf, ~i_wb_sel, 8'hff } :
|
wb_adr[3:2] == 2'd2 ? { 4'hf, ~wb_sel, 8'hff } :
|
{ ~i_wb_sel, 12'hfff } ;
|
{ ~wb_sel, 12'hfff } ;
|
|
|
o_wr_data <= {4{i_wb_dat}};
|
o_wr_data <= {4{wb_dat}};
|
end
|
end
|
|
|
|
end
|
|
else begin : wb128w
|
|
|
|
always @( posedge i_clk )
|
|
if ( !i_cmd_full )
|
|
begin
|
|
wr_en_r <= write_request;
|
|
o_wr_mask <= ~wb_sel;
|
|
o_wr_data <= wb_dat;
|
|
end
|
|
|
|
end
|
|
endgenerate
|
|
|
assign o_wr_en = wr_en_r && !i_cmd_full;
|
assign o_wr_en = wr_en_r && !i_cmd_full;
|
|
|
|
|
// ------------------------------------------------------
|
// ------------------------------------------------------
|
// Read
|
// Read
|
// ------------------------------------------------------
|
// ------------------------------------------------------
|
always @( posedge i_clk )
|
always @( posedge i_clk )
|
begin
|
begin
|
if ( read_ack )
|
if ( read_ack_r )
|
read_ready <= 1'd1;
|
read_ready <= 1'd1;
|
else if ( start_read )
|
else if ( read_request )
|
read_ready <= 1'd0;
|
read_ready <= 1'd0;
|
|
|
if ( !ddr3_busy )
|
if ( !i_cmd_full )
|
begin
|
begin
|
start_write_d1 <= start_write;
|
write_request_r <= write_request;
|
start_read_d1 <= start_read;
|
read_request_r <= read_request;
|
wb_adr_d1 <= i_mem_ctrl ? {5'd0, i_wb_adr[24:0]} : i_wb_adr[29:0];
|
wb_adr_r <= i_mem_ctrl ? {5'd0, i_wb_adr[24:0]} : i_wb_adr[29:0];
|
end
|
end
|
|
|
if ( start_read )
|
if ( read_request )
|
start_read_hold <= 1'd1;
|
read_active_r <= 1'd1;
|
else if ( read_ack )
|
else if ( read_ack_r )
|
start_read_hold <= 1'd0;
|
read_active_r <= 1'd0;
|
|
|
if ( i_rd_empty == 1'd0 && start_read_hold )
|
if ( i_rd_empty == 1'd0 && read_active_r )
|
begin
|
read_ack_r <= 1'd1;
|
|
else
|
|
read_ack_r <= 1'd0;
|
|
end
|
|
|
|
|
|
generate
|
|
if (WB_DWIDTH == 32) begin :wb32r
|
|
|
|
always @( posedge i_clk )
|
|
if ( !i_rd_empty && read_active_r )
|
o_wb_dat <= i_wb_adr[3:2] == 2'd0 ? i_rd_data[ 31: 0] :
|
o_wb_dat <= i_wb_adr[3:2] == 2'd0 ? i_rd_data[ 31: 0] :
|
i_wb_adr[3:2] == 2'd1 ? i_rd_data[ 63:32] :
|
i_wb_adr[3:2] == 2'd1 ? i_rd_data[ 63:32] :
|
i_wb_adr[3:2] == 2'd2 ? i_rd_data[ 95:64] :
|
i_wb_adr[3:2] == 2'd2 ? i_rd_data[ 95:64] :
|
i_rd_data[127:96] ;
|
i_rd_data[127:96] ;
|
read_ack <= 1'd1;
|
|
end
|
end
|
else
|
else begin : wb128r
|
read_ack <= 1'd0;
|
|
|
always @( posedge i_clk )
|
|
if ( !i_rd_empty && read_active_r )
|
|
o_wb_dat <= i_rd_data;
|
|
|
end
|
end
|
|
endgenerate
|
|
|
assign o_wb_ack = i_wb_stb && ( start_write || read_ack ) && !i_cmd_full;
|
assign write_ack = write_request && !write_buf_r;
|
|
assign o_wb_ack = ( i_wb_stb && read_ack_r ) || write_ack;
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|