/* * This is very similar to design/slave.v, although with 1 important difference * - it's meant to be synthesizable (and use iCE40HX8K's embedded RAM). */ /* * | *WISHBONE DATASHEET* | * |---------------------------------------------------------------------------| * | *Description* | *Specification* | * |---------------------------------+-----------------------------------------| * | General description | (MEMORY_BLOCKS*256)x16-bit memory core | * |---------------------------------+-----------------------------------------| * | Supported cycles | SLAVE, pipelined READ/WRITE | * |---------------------------------+-----------------------------------------| * | Data port, size | 16-bit | * | Data port, granularity | 16-bit | * | Data port, maximum operand size | 16-bit | * | Data transfer ordering | Big endian and/or little endian | * | Data transfer ordering | Undefined | * | Address port, size | $clog2(MEMORY_BLOCKS) + 8 bits | * |---------------------------------+-----------------------------------------| * | Clock frequency constraints | NONE (determined by memory primitive, | * | | about 100 MHz in case of iCE40HX8K) | * |---------------------------------+-----------------------------------------| * | | *Signal name* | *WISHBONE Equiv.* | * | |------------------+----------------------| * | | ACK_O | ACK_O | * | | ADR_I | ADR_I() | * | Supported signal list and cross | CLK_I | CLK_I | * | reference to equivalent | DAT_I | DAT_I() | * | WISHBONE signals | DAT_O | DAT_O() | * | | STB_I | STB_I | * | | WE_I | WE_I | * | | RST_I | RST_I | * | | STALL_O | STALL_O | * |---------------------------------+-----------------------------------------| * | | Circuit assumes the use of synchronous | * | Special requirements | RAM with asynchronour read | * | | inreffable by synthesis software. | * |---------------------------------+-----------------------------------------| * | | The MEMORY_BLOCKS parameter can be used | * | | to decide the size of the memory. | * | Additional information | Single block contains 256 16-bit | * | | words. Address width changes | * | | accordingly to memory size. | */ `default_nettype none `define ADDR_WIDTH ($clog2(MEMORY_BLOCKS) + 8) module embedded_bram_slave #( parameter MEMORY_BLOCKS = 1, /* 1 block stores 256 16-bit words */ parameter WORDS_TO_INITIALIZE = 0, parameter INITIAL_CONTENTS_FILE = "some_file.mem" ) ( output wire ACK_O, input wire CLK_I, input wire [`ADDR_WIDTH - 1:0] ADR_I, input wire [15:0] DAT_I, output wire [15:0] DAT_O, input wire RST_I, input wire STB_I, input wire WE_I, output wire STALL_O ); reg [15:0] memory [256 * MEMORY_BLOCKS - 1 : 0]; generate if (WORDS_TO_INITIALIZE) begin initial $readmemb(INITIAL_CONTENTS_FILE, memory, 0, WORDS_TO_INITIALIZE - 1); end else begin always @ (posedge CLK_I) begin if (!RST_I && STB_I && WE_I) memory[ADR_I] <= DAT_I; end end endgenerate reg [15:0] output_data; reg ack; assign DAT_O = output_data; assign ACK_O = ack; assign STALL_O = 0; always @ (posedge CLK_I) begin if (RST_I) begin ack <= 0; end else begin ack <= STB_I; output_data <= memory[ADR_I]; end end endmodule // embedded_bram_slave