Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- `define MEM_MINWIDTH 5
- `define MEM_MAXWIDTH 15
- `define DSP_A_MAXWIDTH 25
- `define DSP_B_MAXWIDTH 18
- 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;
- parameter _TECHMAP_CONNMAP_RD_ADDR_ = 0;
- parameter _TECHMAP_CONNMAP_WR_ADDR_ = 0;
- parameter _TECHMAP_CONNMAP_RD_PORTS_ = 0;
- parameter _TECHMAP_CONNMAP_WR_PORTS_ = 0;
- reg _TECHMAP_FAIL_;
- initial begin
- _TECHMAP_FAIL_ <= 0;
- // only map cells with only one read and one write port
- if (RD_PORTS > 2 || WR_PORTS > 2)
- _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 < `MEM_MINWIDTH || SIZE < 2**`MEM_MINWIDTH)
- _TECHMAP_FAIL_ <= 1;
- if (_TECHMAP_CONNMAP_RD_ADDR_ != _TECHMAP_CONNMAP_WR_ADDR_)
- _TECHMAP_FAIL_ <= 1;
- end
- genvar i;
- generate
- for (i = 0; i < WIDTH; i=i+1) begin:slice
- if (RD_PORTS > 1 || WR_PORTS > 1) begin
- \$__mem_Wx1_dp_generator #(
- .ABITS(ABITS),
- .SIZE(SIZE),
- ) bit_slice (
- .CLK(RD_CLK),
- .RD_ADDR(RD_ADDR),
- .RD_DATA(RD_DATA[RD_PORTS*(i+1)-1:RD_PORTS*i]),
- .WR_ADDR(WR_ADDR),
- .WR_DATA(WR_DATA[WD_PORTS*(i+1)-1:WD_PORTS*i]),
- .WR_EN(WR_EN)
- );
- end
- else begin
- \$__mem_Wx1_sp_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
- end
- endgenerate
- endmodule
- module \$__mem_Wx1_dp_generator (CLK, RD_ADDR, RD_DATA, WR_ADDR, WR_DATA, WR_EN);
- parameter ABITS = 4;
- parameter SIZE = 16;
- input CLK;
- input [1:0] WR_EN, WR_DATA;
- input [2*ABITS-1:0] RD_ADDR, WR_ADDR;
- output [1:0] RD_DATA;
- wire [1023:0] _TECHMAP_DO_ = "proc; clean";
- generate
- if (ABITS > `MEM_MAXWIDTH) begin
- wire [1:0] high_rd_data, low_rd_data;
- if (SIZE > 2**(ABITS-1)) begin
- \$__mem_Wx1_dp_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 = 2'bxx;
- end
- \$__mem_Wx1_dp_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
- dual_port_ram _TECHMAP_REPLACE_ (
- .clk(CLK),
- .addr1({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR[ABITS-1:0] }),
- .addr1__U({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR[ABITS-1:0] }),
- .data1(RD_DATA[0]),
- .out1(WR_DATA[0]),
- .we1({ {8}{WR_EN[0]} }),
- .we1__U({ {8}{WR_EN[0]} }),
- .addr2({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR[2*ABITS-1:ABITS] }),
- .addr2__U({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR[2*ABITS-1:ABITS] }),
- .data2(RD_DATA[1]),
- .out2(WR_DATA[1]),
- .we2({ {8}{WR_EN[1]} }),
- .we2__U({ {8}{WR_EN[1]} })
- );
- end
- endgenerate
- endmodule
- module \$__mem_Wx1_sp_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 > `MEM_MAXWIDTH) begin
- wire high_rd_data, low_rd_data;
- if (SIZE > 2**(ABITS-1)) begin
- \$__mem_Wx1_sp_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_Wx1_sp_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
- single_port_ram _TECHMAP_REPLACE_ (
- .clk(CLK),
- .addr({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR }),
- .addr__U({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR }),
- .addr__AL({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR }),
- .addr__AU({ {{`MEM_MAXWIDTH-ABITS}{1'bx}}, RD_ADDR }),
- .data(RD_DATA),
- .out(WR_DATA),
- .we({ {8}{WR_EN} }),
- .we__U({ {8}{WR_EN} })
- );
- end
- endgenerate
- endmodule
- module \$mul (A, B, Y);
- parameter A_SIGNED = 0;
- parameter B_SIGNED = 0;
- parameter A_WIDTH = 1;
- parameter B_WIDTH = 1;
- parameter Y_WIDTH = 1;
- input [A_WIDTH-1:0] A;
- input [B_WIDTH-1:0] B;
- output [Y_WIDTH-1:0] Y;
- wire [1023:0] _TECHMAP_DO_ = "proc; clean";
- parameter _TECHMAP_CONSTMSK_A_ = A_WIDTH'b0;
- parameter _TECHMAP_CONSTMSK_B_ = B_WIDTH'b0;
- parameter _TECHMAP_CONSTVAL_A_ = A_WIDTH'bx;
- parameter _TECHMAP_CONSTVAL_B_ = B_WIDTH'bx;
- integer a_width = A_WIDTH;
- integer b_width = B_WIDTH;
- integer tmp;
- reg _TECHMAP_FAIL_;
- initial begin
- _TECHMAP_FAIL_ <= 0;
- if (A_SIGNED || B_SIGNED)
- _TECHMAP_FAIL_ <= 1;
- //if (A_WIDTH < B_WIDTH)
- // _TECHMAP_FAIL_ <= 1;
- //if (A_WIDTH > `DSP_A_MAXWIDTH || B_WIDTH > `DSP_B_MAXWIDTH)
- // _TECHMAP_FAIL_ <= 1;
- //if (Y_WIDTH > (`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH))
- // _TECHMAP_FAIL_ <= 1;
- end
- localparam A_WIDTH_NEW = (_TECHMAP_CONSTMSK_A_ === {{A_WIDTH}{1'b1}} ? $clog2(_TECHMAP_CONSTVAL_A_) : A_WIDTH );
- localparam B_WIDTH_NEW = (_TECHMAP_CONSTMSK_B_ === {{B_WIDTH}{1'b1}} ? $clog2(_TECHMAP_CONSTVAL_B_) : B_WIDTH );
- //localparam Y_WIDTH_NEW = (A_WIDTH_NEW+BWIDTH_NEW-1 < Y_WIDTH ? A_WIDTH_NEW+B_WIDTH_NEW-1 : Y_WIDTH );
- generate
- begin
- \$__mul_AxB_generator #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH_NEW),
- .B_WIDTH(B_WIDTH_NEW),
- .Y_WIDTH(Y_WIDTH)
- ) mul_slice (
- .A(A[A_WIDTH_NEW-1:0]),
- .B(B[B_WIDTH_NEW-1:0]),
- .Y(Y[Y_WIDTH-1:0])
- );
- end
- endgenerate
- endmodule
- module \$__mul_AxB_generator (A, B, Y);
- parameter A_SIGNED = 0;
- parameter B_SIGNED = 0;
- parameter A_WIDTH = 1;
- parameter B_WIDTH = 1;
- parameter Y_WIDTH = 1;
- input [A_WIDTH-1:0] A;
- input [B_WIDTH-1:0] B;
- output [Y_WIDTH-1:0] Y;
- wire [1023:0] _TECHMAP_DO_ = "proc; clean";
- generate
- if (A_WIDTH > `DSP_A_MAXWIDTH) begin
- localparam n_floored = A_WIDTH/`DSP_A_MAXWIDTH;
- localparam n = n_floored + (n_floored*`DSP_A_MAXWIDTH < A_WIDTH ? 1 : 0);
- wire [Y_WIDTH-1:0] partial [n-1:1];
- wire [Y_WIDTH-1:0] partial_sum [n-2:0];
- \$__mul_AxB_generator #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(`DSP_A_MAXWIDTH),
- .B_WIDTH(B_WIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) mul_slice_first (
- .A(A[`DSP_A_MAXWIDTH-1:0]),
- .B(B),
- .Y(partial_sum[0])
- );
- genvar i;
- generate
- for (i = 1; i < n-1; i=i+1) begin:slice
- \$__mul_AxB_generator #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(`DSP_A_MAXWIDTH),
- .B_WIDTH(B_WIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) mul_slice (
- .A(A[(i+1)*`DSP_A_MAXWIDTH-1:i*`DSP_A_MAXWIDTH]),
- .B(B),
- .Y(partial[i])
- );
- assign partial_sum[i] = partial[i] << i*`DSP_A_MAXWIDTH + partial_sum[i-1];
- end
- endgenerate
- \$__mul_AxB_generator #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH),
- .B_WIDTH(B_WIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) mul_slice_last (
- .A(A[A_WIDTH-1:(n-1)*`DSP_A_MAXWIDTH]),
- .B(B),
- .Y(partial[n-1])
- );
- assign Y = partial[n-1] << (n-1)*`DSP_A_MAXWIDTH + partial_sum[n-2];
- end
- else if (B_WIDTH > `DSP_B_MAXWIDTH) begin
- localparam n_floored = B_WIDTH/`DSP_B_MAXWIDTH;
- localparam n = n_floored + (n_floored*`DSP_B_MAXWIDTH < B_WIDTH ? 1 : 0);
- wire [Y_WIDTH-1:0] partial [n-1:1];
- wire [Y_WIDTH-1:0] partial_sum [n-2:0];
- \$__mul_AxB_generator #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(`DSP_B_MAXWIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) mul_slice_first (
- .A(A),
- .B(B[`DSP_B_MAXWIDTH-1:0]),
- .Y(partial_sum[0])
- );
- genvar i;
- generate
- for (i = 1; i < n-1; i=i+1) begin:slice
- \$__mul_AxB_generator #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(`DSP_B_MAXWIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) mul_slice (
- .A(A),
- .B(B[(i+1)*`DSP_B_MAXWIDTH-1:i*`DSP_B_MAXWIDTH]),
- .Y(partial[i])
- );
- assign partial_sum[i] = partial[i] << i*`DSP_B_MAXWIDTH + partial_sum[i-1];
- end
- endgenerate
- \$__mul_AxB_generator #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(B_WIDTH-(n-1)*`DSP_B_MAXWIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) mul_slice_last (
- .A(A),
- .B(B[B_WIDTH-1:(n-1)*`DSP_B_MAXWIDTH]),
- .Y(partial[n-1])
- );
- assign Y = partial[n-1] << (n-1)*`DSP_B_MAXWIDTH + partial_sum[n-2];
- end
- else begin
- if (`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH > Y_WIDTH) begin
- wire [`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH-Y_WIDTH-1:0] dummy;
- multiply _TECHMAP_REPLACE_ (
- .a({ {{`DSP_A_MAXWIDTH-A_WIDTH}{1'bx}}, A }),
- .b({ {{`DSP_B_MAXWIDTH-B_WIDTH}{1'bx}}, B }),
- .out({ dummy, Y })
- );
- end
- else
- multiply _TECHMAP_REPLACE_ (
- .a({ {{`DSP_A_MAXWIDTH-A_WIDTH}{1'bx}}, A }),
- .b({ {{`DSP_B_MAXWIDTH-B_WIDTH}{1'bx}}, B }),
- .out(Y[`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH-1:0])
- );
- end
- endgenerate
- endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement