`timescale 1ns / 1ps module dram_bridge #(ADDR_WIDTH = 32, WIDTH = 32) ( // local bus input wire [ADDR_WIDTH-1:0] mem_addr, output wire [WIDTH-1:0] mem_read_data, input wire [WIDTH-1:0] mem_write_data, input wire mem_read_enable, input wire mem_write_enable, input wire mem_read_ins, output wire mem_wait, input wire rst_n, input wire dram_front_clk, input wire dram_refclk, // DDR3 SDRAM inout wire [15:0] ddr3_dq, inout wire [1:0] ddr3_dqs_n, inout wire [1:0] ddr3_dqs_p, output wire [13:0] ddr3_addr, output wire [2:0] ddr3_ba, output wire ddr3_ras_n, output wire ddr3_cas_n, output wire ddr3_we_n, output wire ddr3_reset_n, output wire [0:0] ddr3_ck_p, output wire [0:0] ddr3_ck_n, output wire [0:0] ddr3_cke, output wire [0:0] ddr3_cs_n, output wire [1:0] ddr3_dm, output wire [0:0] ddr3_odt ); localparam DRAM_ADDR_WIDTH = 28, DRAM_DATA_WIDTH = 128, DRAM_MASK_WIDTH = 16; wire [DRAM_ADDR_WIDTH-1:0] app_addr; wire [2:0] app_cmd; wire app_en; wire app_rdy; wire [DRAM_DATA_WIDTH-1:0] app_rd_data; wire app_rd_data_end; wire app_rd_data_valid; wire [DRAM_DATA_WIDTH-1:0] app_wdf_data; wire app_wdf_end; wire [DRAM_MASK_WIDTH-1:0] app_wdf_mask; wire app_wdf_rdy; wire app_sr_active; wire app_ref_ack; wire app_zq_ack; wire app_wdf_wren; wire [11:0] device_temp; wire ui_clk, ui_rst_sync; wire init_calib_complete; localparam CMD_READ = 3'b1; localparam CMD_WRITE = 3'b0; mig_dram_0 dram0( // Inouts .ddr3_dq(ddr3_dq), .ddr3_dqs_n(ddr3_dqs_n), .ddr3_dqs_p(ddr3_dqs_p), // Outputs .ddr3_addr(ddr3_addr), .ddr3_ba(ddr3_ba), .ddr3_ras_n(ddr3_ras_n), .ddr3_cas_n(ddr3_cas_n), .ddr3_we_n(ddr3_we_n), .ddr3_reset_n(ddr3_reset_n), .ddr3_ck_p(ddr3_ck_p), .ddr3_ck_n(ddr3_ck_n), .ddr3_cke(ddr3_cke), .ddr3_cs_n(ddr3_cs_n), .ddr3_dm(ddr3_dm), .ddr3_odt(ddr3_odt), // Application interface ports .app_addr (app_addr), .app_cmd (app_cmd), .app_en (app_en), .app_wdf_data (app_wdf_data), .app_wdf_mask (app_wdf_mask), .app_wdf_end (app_wdf_end), .app_wdf_wren (app_wdf_wren), .app_rd_data (app_rd_data), .app_rd_data_end (app_rd_data_end), .app_rd_data_valid (app_rd_data_valid), .app_rdy (app_rdy), .app_wdf_rdy (app_wdf_rdy), .app_sr_req (1'b0), .app_ref_req (1'b0), .app_zq_req (1'b0), .app_sr_active (app_sr_active), .app_ref_ack (app_ref_ack), .app_zq_ack (app_zq_ack), .ui_clk (ui_clk), .ui_clk_sync_rst (ui_rst_sync), // System Clock Ports .sys_clk_i (dram_front_clk), // Reference Clock Ports .clk_ref_i (dram_refclk), .device_temp (device_temp), .init_calib_complete (init_calib_complete), .sys_rst (rst_n) ); (*KEEP*) reg [DRAM_DATA_WIDTH-1:0] ins_cache; (*KEEP*) reg [DRAM_ADDR_WIDTH-1:4] icached_addr; (*KEEP*) wire icache_hit = mem_read_enable && mem_read_ins && (icached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4]); (*KEEP*) reg [DRAM_DATA_WIDTH-1:0] d_cache; (*KEEP*) reg [DRAM_ADDR_WIDTH-1:4] dcached_addr; (*KEEP*) wire dcache_hit = mem_read_enable && !mem_read_ins && (dcached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4]); wire cache_hit = icache_hit | dcache_hit; reg [WIDTH-1:0] read_buf; reg read_inprogress = 0; wire dram_read_enable = mem_read_enable && !cache_hit; assign app_rd_data_end = 1'b1; // addresses on the memory interface are aligned to 16 bytes // and 28 bits wide (=256MB) assign app_addr = { mem_addr[DRAM_ADDR_WIDTH:4], 4'b0000 }; // select a word from the 128 bits transferred by the dram controller // according to the lower bits of the address (ignoring bits 1:0) wire [1:0] word_sel = mem_addr[3:2]; wire [WIDTH-1:0] read_word = word_sel == 2'b11 ? app_rd_data[31:0] : word_sel == 2'b10 ? app_rd_data[63:32] : word_sel == 2'b01 ? app_rd_data[95:64] : app_rd_data[127:96]; wire [WIDTH-1:0] read_icached_word = word_sel == 2'b11 ? ins_cache[31:0] : word_sel == 2'b10 ? ins_cache[63:32] : word_sel == 2'b01 ? ins_cache[95:64] : ins_cache[127:96]; wire [WIDTH-1:0] read_dcached_word = word_sel == 2'b11 ? d_cache[31:0] : word_sel == 2'b10 ? d_cache[63:32] : word_sel == 2'b01 ? d_cache[95:64] : d_cache[127:96]; (*KEEP*) assign mem_read_data = icache_hit ? read_icached_word : dcache_hit ? read_dcached_word : app_rd_data_valid ? read_word : read_buf; // set the write mask according to the lower bits of the address // (ignoring bit 0) assign app_wdf_mask = word_sel == 2'b11 ? 16'b1111111111110000 : word_sel == 2'b10 ? 16'b1111111100001111 : word_sel == 2'b01 ? 16'b1111000011111111 : 16'b0000111111111111 ; wire write_ready = mem_write_enable & app_wdf_rdy & app_rdy; assign app_wdf_wren = mem_write_enable & write_ready; assign app_wdf_end = mem_write_enable & write_ready; assign app_wdf_data = { {4{mem_write_data}} }; assign mem_wait = (dram_read_enable & ~read_inprogress) | (mem_write_enable & (~app_wdf_rdy | ~app_rdy)) | (read_inprogress & ~app_rd_data_valid); assign app_en = (dram_read_enable & ~read_inprogress) | (mem_write_enable & write_ready); assign app_cmd = dram_read_enable ? CMD_READ : CMD_WRITE; /* set instruction cache */ always @(posedge dram_front_clk) begin if(dram_read_enable && mem_read_ins && app_rd_data_valid) begin ins_cache <= app_rd_data; icached_addr <= mem_addr[DRAM_ADDR_WIDTH-1:4]; end end /* set data cache */ always @(posedge dram_front_clk) begin if(dram_read_enable && !mem_read_ins && app_rd_data_valid) begin d_cache <= app_rd_data; dcached_addr <= mem_addr[DRAM_ADDR_WIDTH-1:4]; end /* write-through cache - invalidate on write */ /* invalidate data cache on write */ // if(mem_write_enable && dcached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4]) // dcached_addr <= {DRAM_ADDR_WIDTH-4{1'b1}}; /* write-back cache - update cache on write */ // write back to data cache on mem_write if(mem_write_enable && dcached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4]) begin case(word_sel) 2'b11: d_cache[31:0] <= mem_write_data; 2'b10: d_cache[63:32] <= mem_write_data; 2'b01: d_cache[95:64] <= mem_write_data; 2'b00: d_cache[127:96] <= mem_write_data; endcase end end /* transfer read data, either from cache or from DRAM */ always @(posedge dram_front_clk) begin if(dram_read_enable & ~read_inprogress & app_rdy) read_inprogress <= 1; if(read_inprogress & app_rd_data_valid) read_inprogress <= 0; if(dram_read_enable & app_rd_data_valid) read_buf <= mem_read_data; else if (mem_read_enable & icache_hit) read_buf <= read_icached_word; else if (mem_read_enable & dcache_hit) read_buf <= read_dcached_word; end endmodule