mirror of https://github.com/YosysHQ/yosys.git
130 lines
3.0 KiB
Verilog
130 lines
3.0 KiB
Verilog
|
|
module \$mem (RD_CLK, 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 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*ABITS-1:0] RD_ADDR;
|
|
output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
|
|
|
|
input [WR_PORTS-1:0] WR_CLK, 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;
|
|
|
|
reg _TECHMAP_FAIL_;
|
|
initial begin
|
|
_TECHMAP_FAIL_ <= 0;
|
|
|
|
// only map cells with only one read and one write port
|
|
if (RD_PORTS > 1 || WR_PORTS > 1)
|
|
_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;
|
|
|
|
// 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)
|
|
);
|
|
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
|
|
|