`include "macros.v" `define BRAM_ADDR_WIDTH 14 `define BRAM_DATA_WIDTH `DATAWIDTH `define BRAM_NAME dcache_bram `include "bram.inc" module dcache (clk, read_addr_r, read_addr_a_, read_addr_d, read_data_r_, read_data_a, read_data_d_, write_addr_r, write_addr_a_, write_addr_d, write_data_r, write_data_a_, write_data_d, write_done_r_, write_done_a, write_done_d_ ); input clk; `input(read_addr_r, read_addr_a, read_addr_a_, [(`DATAWIDTH-1):0], read_addr_d) `output(read_data_r, read_data_r_, read_data_a, [(`DATAWIDTH-1):0], read_data_d_) `defreg(read_data_d_, [(`DATAWIDTH-1):0], read_data_d) `input(write_addr_r, write_addr_a, write_addr_a_, [(`DATAWIDTH-1):0], write_addr_d) `input(write_data_r, write_data_a, write_data_a_, [(`DATAWIDTH-1):0], write_data_d) `output(write_done_r, write_done_r_, write_done_a, [(`DATAWIDTH-1):0], write_done_d_) `defreg(write_done_d_, [(`DATAWIDTH-1):0], write_done_d) reg bram_we; wire bram_we_; assign bram_we_ = bram_we; wire [(`BRAM_DATA_WIDTH-1):0] bram_read_data; reg [(`BRAM_ADDR_WIDTH-1):0] bram_write_address; wire [(`BRAM_ADDR_WIDTH-1):0] bram_read_address; reg [(`BRAM_DATA_WIDTH-1):0] bram_write_data; wire [(`BRAM_DATA_WIDTH-1):0] bram_write_data_; assign bram_write_data_ = bram_write_data; `BRAM_NAME mybram(clk, bram_we_, bram_write_address, bram_read_address, bram_write_data_, not_connected, bram_read_data); reg send_done; reg have_read; initial have_read = 0; reg read_pending; initial read_pending = 0; assign bram_read_address = read_addr_d; always @(posedge clk) begin bram_we = 0; if (send_done) begin `onwrite(write_done_r, write_done_a) send_done = 0; end end else begin if (!write_addr_r && write_addr_a) write_addr_a = 0; if (!write_data_r && write_data_a) write_data_a = 0; if (write_addr_r && write_data_r) begin write_addr_a = 1; write_data_a = 1; bram_we = 1; send_done = 1; bram_write_address = write_addr_d; bram_write_data = write_data_d; end end if (read_pending) begin read_pending <= 0; have_read <= 1; read_data_d <= bram_read_data; end else if (have_read) begin `onwrite(read_data_r, read_data_a) have_read <= 0; end end else begin `onread(read_addr_r, read_addr_a) // ======= Careful with the timing here! ===================== // We MUST capture bram_read_data on the very next clock since // read_addr_d is free to change after the next clock // =========================================================== read_pending <= 1; end end end endmodule