OpenFPGA/yosys/tests/techmap/mem_simple_4x1_map.v

153 lines
3.7 KiB
Verilog

module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
parameter MEMID = "";
parameter SIZE = 256;
parameter OFFSET = 0;
parameter ABITS = 8;
parameter WIDTH = 8;
parameter signed INIT = 1'bx;
parameter RD_PORTS = 1;
parameter RD_CLK_ENABLE = 1'b1;
parameter RD_CLK_POLARITY = 1'b1;
parameter RD_TRANSPARENT = 1'b1;
parameter WR_PORTS = 1;
parameter WR_CLK_ENABLE = 1'b1;
parameter WR_CLK_POLARITY = 1'b1;
input [RD_PORTS-1:0] RD_CLK;
input [RD_PORTS-1:0] RD_EN;
input [RD_PORTS*ABITS-1:0] RD_ADDR;
output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
input [WR_PORTS-1:0] WR_CLK;
input [WR_PORTS*WIDTH-1:0] WR_EN;
input [WR_PORTS*ABITS-1:0] WR_ADDR;
input [WR_PORTS*WIDTH-1:0] WR_DATA;
wire [1023:0] _TECHMAP_DO_ = "proc; clean";
parameter _TECHMAP_CONNMAP_RD_CLK_ = 0;
parameter _TECHMAP_CONNMAP_WR_CLK_ = 0;
parameter _TECHMAP_CONSTVAL_RD_EN_ = 0;
parameter _TECHMAP_BITS_CONNMAP_ = 0;
parameter _TECHMAP_CONNMAP_WR_EN_ = 0;
reg _TECHMAP_FAIL_;
integer k;
initial begin
_TECHMAP_FAIL_ <= 0;
// no initialized memories
if (INIT !== 1'bx)
_TECHMAP_FAIL_ <= 1;
// only map cells with only one read and one write port
if (RD_PORTS > 1 || WR_PORTS > 1)
_TECHMAP_FAIL_ <= 1;
// read enable must be constant high
if (_TECHMAP_CONSTVAL_RD_EN_[0] !== 1'b1)
_TECHMAP_FAIL_ <= 1;
// we expect positive read clock and non-transparent reads
if (RD_TRANSPARENT || !RD_CLK_ENABLE || !RD_CLK_POLARITY)
_TECHMAP_FAIL_ <= 1;
// we expect positive write clock
if (!WR_CLK_ENABLE || !WR_CLK_POLARITY)
_TECHMAP_FAIL_ <= 1;
// only one global write enable bit is supported
for (k = 1; k < WR_PORTS*WIDTH; k = k+1)
if (_TECHMAP_CONNMAP_WR_EN_[0 +: _TECHMAP_BITS_CONNMAP_] !=
_TECHMAP_CONNMAP_WR_EN_[k*_TECHMAP_BITS_CONNMAP_ +: _TECHMAP_BITS_CONNMAP_])
_TECHMAP_FAIL_ <= 1;
// read and write must be in same clock domain
if (_TECHMAP_CONNMAP_RD_CLK_ != _TECHMAP_CONNMAP_WR_CLK_)
_TECHMAP_FAIL_ <= 1;
// we don't do small memories or memories with offsets
if (OFFSET != 0 || ABITS < 4 || SIZE < 16)
_TECHMAP_FAIL_ <= 1;
end
genvar i;
generate
for (i = 0; i < WIDTH; i=i+1) begin:slice
\$__mem_4x1_generator #(
.ABITS(ABITS),
.SIZE(SIZE)
) bit_slice (
.CLK(RD_CLK),
.RD_ADDR(RD_ADDR),
.RD_DATA(RD_DATA[i]),
.WR_ADDR(WR_ADDR),
.WR_DATA(WR_DATA[i]),
.WR_EN(WR_EN[0])
);
end
endgenerate
endmodule
module \$__mem_4x1_generator (CLK, RD_ADDR, RD_DATA, WR_ADDR, WR_DATA, WR_EN);
parameter ABITS = 4;
parameter SIZE = 16;
input CLK, WR_DATA, WR_EN;
input [ABITS-1:0] RD_ADDR, WR_ADDR;
output RD_DATA;
wire [1023:0] _TECHMAP_DO_ = "proc; clean";
generate
if (ABITS > 4) begin
wire high_rd_data, low_rd_data;
if (SIZE > 2**(ABITS-1)) begin
\$__mem_4x1_generator #(
.ABITS(ABITS-1),
.SIZE(SIZE - 2**(ABITS-1))
) part_high (
.CLK(CLK),
.RD_ADDR(RD_ADDR[ABITS-2:0]),
.RD_DATA(high_rd_data),
.WR_ADDR(WR_ADDR[ABITS-2:0]),
.WR_DATA(WR_DATA),
.WR_EN(WR_EN && WR_ADDR[ABITS-1])
);
end else begin
assign high_rd_data = 1'bx;
end
\$__mem_4x1_generator #(
.ABITS(ABITS-1),
.SIZE(SIZE > 2**(ABITS-1) ? 2**(ABITS-1) : SIZE)
) part_low (
.CLK(CLK),
.RD_ADDR(RD_ADDR[ABITS-2:0]),
.RD_DATA(low_rd_data),
.WR_ADDR(WR_ADDR[ABITS-2:0]),
.WR_DATA(WR_DATA),
.WR_EN(WR_EN && !WR_ADDR[ABITS-1])
);
reg delayed_abit;
always @(posedge CLK)
delayed_abit <= RD_ADDR[ABITS-1];
assign RD_DATA = delayed_abit ? high_rd_data : low_rd_data;
end else begin
MEM4X1 _TECHMAP_REPLACE_ (
.CLK(CLK),
.RD_ADDR(RD_ADDR),
.RD_DATA(RD_DATA),
.WR_ADDR(WR_ADDR),
.WR_DATA(WR_DATA),
.WR_EN(WR_EN)
);
end
endgenerate
endmodule