+`include "macros.v"
+`define BRAM_ADDR_WIDTH 8
+`define BRAM_DATA_WIDTH 37
+`include "bram.inc"
+
+module mem (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_DATA_WIDTH-1):0] bram_read_data;
+ reg [(`BRAM_ADDR_WIDTH-1):0] bram_write_address;
+ reg [(`BRAM_DATA_WIDTH-1):0] bram_write_data;
+ bram mybram(clk,
+ bram_we, bram_write_address,
+ read_addr_d, 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;
+
+ always @(posedge clk) begin
+ bram_we = 0;
+ 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
+
+ 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
+ end
+
+endmodule