Merge pull request #1073 from whitequark/ecp5-diamond-iob
[yosys.git] / tests / techmap / mem_simple_4x1_map.v
1
2 module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
3 parameter MEMID = "";
4 parameter SIZE = 256;
5 parameter OFFSET = 0;
6 parameter ABITS = 8;
7 parameter WIDTH = 8;
8 parameter signed INIT = 1'bx;
9
10 parameter RD_PORTS = 1;
11 parameter RD_CLK_ENABLE = 1'b1;
12 parameter RD_CLK_POLARITY = 1'b1;
13 parameter RD_TRANSPARENT = 1'b1;
14
15 parameter WR_PORTS = 1;
16 parameter WR_CLK_ENABLE = 1'b1;
17 parameter WR_CLK_POLARITY = 1'b1;
18
19 input [RD_PORTS-1:0] RD_CLK;
20 input [RD_PORTS-1:0] RD_EN;
21 input [RD_PORTS*ABITS-1:0] RD_ADDR;
22 output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
23
24 input [WR_PORTS-1:0] WR_CLK;
25 input [WR_PORTS*WIDTH-1:0] WR_EN;
26 input [WR_PORTS*ABITS-1:0] WR_ADDR;
27 input [WR_PORTS*WIDTH-1:0] WR_DATA;
28
29 wire [1023:0] _TECHMAP_DO_ = "proc; clean";
30
31 parameter _TECHMAP_CONNMAP_RD_CLK_ = 0;
32 parameter _TECHMAP_CONNMAP_WR_CLK_ = 0;
33
34 parameter _TECHMAP_CONSTVAL_RD_EN_ = 0;
35
36 parameter _TECHMAP_BITS_CONNMAP_ = 0;
37 parameter _TECHMAP_CONNMAP_WR_EN_ = 0;
38
39 reg _TECHMAP_FAIL_;
40 integer k;
41 initial begin
42 _TECHMAP_FAIL_ <= 0;
43
44 // no initialized memories
45 if (INIT !== 1'bx)
46 _TECHMAP_FAIL_ <= 1;
47
48 // only map cells with only one read and one write port
49 if (RD_PORTS > 1 || WR_PORTS > 1)
50 _TECHMAP_FAIL_ <= 1;
51
52 // read enable must be constant high
53 if (_TECHMAP_CONSTVAL_RD_EN_[0] !== 1'b1)
54 _TECHMAP_FAIL_ <= 1;
55
56 // we expect positive read clock and non-transparent reads
57 if (RD_TRANSPARENT || !RD_CLK_ENABLE || !RD_CLK_POLARITY)
58 _TECHMAP_FAIL_ <= 1;
59
60 // we expect positive write clock
61 if (!WR_CLK_ENABLE || !WR_CLK_POLARITY)
62 _TECHMAP_FAIL_ <= 1;
63
64 // only one global write enable bit is supported
65 for (k = 1; k < WR_PORTS*WIDTH; k = k+1)
66 if (_TECHMAP_CONNMAP_WR_EN_[0 +: _TECHMAP_BITS_CONNMAP_] !=
67 _TECHMAP_CONNMAP_WR_EN_[k*_TECHMAP_BITS_CONNMAP_ +: _TECHMAP_BITS_CONNMAP_])
68 _TECHMAP_FAIL_ <= 1;
69
70 // read and write must be in same clock domain
71 if (_TECHMAP_CONNMAP_RD_CLK_ != _TECHMAP_CONNMAP_WR_CLK_)
72 _TECHMAP_FAIL_ <= 1;
73
74 // we don't do small memories or memories with offsets
75 if (OFFSET != 0 || ABITS < 4 || SIZE < 16)
76 _TECHMAP_FAIL_ <= 1;
77 end
78
79 genvar i;
80 generate
81 for (i = 0; i < WIDTH; i=i+1) begin:slice
82 \$__mem_4x1_generator #(
83 .ABITS(ABITS),
84 .SIZE(SIZE)
85 ) bit_slice (
86 .CLK(RD_CLK),
87 .RD_ADDR(RD_ADDR),
88 .RD_DATA(RD_DATA[i]),
89 .WR_ADDR(WR_ADDR),
90 .WR_DATA(WR_DATA[i]),
91 .WR_EN(WR_EN[0])
92 );
93 end
94 endgenerate
95 endmodule
96
97 module \$__mem_4x1_generator (CLK, RD_ADDR, RD_DATA, WR_ADDR, WR_DATA, WR_EN);
98 parameter ABITS = 4;
99 parameter SIZE = 16;
100
101 input CLK, WR_DATA, WR_EN;
102 input [ABITS-1:0] RD_ADDR, WR_ADDR;
103 output RD_DATA;
104
105 wire [1023:0] _TECHMAP_DO_ = "proc; clean";
106
107 generate
108 if (ABITS > 4) begin
109 wire high_rd_data, low_rd_data;
110 if (SIZE > 2**(ABITS-1)) begin
111 \$__mem_4x1_generator #(
112 .ABITS(ABITS-1),
113 .SIZE(SIZE - 2**(ABITS-1))
114 ) part_high (
115 .CLK(CLK),
116 .RD_ADDR(RD_ADDR[ABITS-2:0]),
117 .RD_DATA(high_rd_data),
118 .WR_ADDR(WR_ADDR[ABITS-2:0]),
119 .WR_DATA(WR_DATA),
120 .WR_EN(WR_EN && WR_ADDR[ABITS-1])
121 );
122 end else begin
123 assign high_rd_data = 1'bx;
124 end
125 \$__mem_4x1_generator #(
126 .ABITS(ABITS-1),
127 .SIZE(SIZE > 2**(ABITS-1) ? 2**(ABITS-1) : SIZE)
128 ) part_low (
129 .CLK(CLK),
130 .RD_ADDR(RD_ADDR[ABITS-2:0]),
131 .RD_DATA(low_rd_data),
132 .WR_ADDR(WR_ADDR[ABITS-2:0]),
133 .WR_DATA(WR_DATA),
134 .WR_EN(WR_EN && !WR_ADDR[ABITS-1])
135 );
136 reg delayed_abit;
137 always @(posedge CLK)
138 delayed_abit <= RD_ADDR[ABITS-1];
139 assign RD_DATA = delayed_abit ? high_rd_data : low_rd_data;
140 end else begin
141 MEM4X1 _TECHMAP_REPLACE_ (
142 .CLK(CLK),
143 .RD_ADDR(RD_ADDR),
144 .RD_DATA(RD_DATA),
145 .WR_ADDR(WR_ADDR),
146 .WR_DATA(WR_DATA),
147 .WR_EN(WR_EN)
148 );
149 end
150 endgenerate
151 endmodule
152