/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2021 Cologne Chip AG * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ `timescale 1ps/1ps module CC_IBUF #( parameter PIN_NAME = "UNPLACED", parameter V_IO = "UNDEFINED", parameter [0:0] PULLUP = 1'bx, parameter [0:0] PULLDOWN = 1'bx, parameter [0:0] KEEPER = 1'bx, parameter [0:0] SCHMITT_TRIGGER = 1'bx, // IOSEL parameter [3:0] DELAY_IBF = 1'bx, parameter [0:0] FF_IBF = 1'bx )( (* iopad_external_pin *) input I, output Y ); assign Y = I; endmodule module CC_OBUF #( parameter PIN_NAME = "UNPLACED", parameter V_IO = "UNDEFINED", parameter DRIVE = "UNDEFINED", parameter SLEW = "UNDEFINED", // IOSEL parameter [3:0] DELAY_OBF = 1'bx, parameter [0:0] FF_OBF = 1'bx )( input A, (* iopad_external_pin *) output O ); assign O = A; endmodule module CC_TOBUF #( parameter PIN_NAME = "UNPLACED", parameter V_IO = "UNDEFINED", parameter DRIVE = "UNDEFINED", parameter SLEW = "UNDEFINED", parameter [0:0] PULLUP = 1'bx, parameter [0:0] PULLDOWN = 1'bx, parameter [0:0] KEEPER = 1'bx, // IOSEL parameter [3:0] DELAY_OBF = 1'bx, parameter [0:0] FF_OBF = 1'bx )( input A, T, (* iopad_external_pin *) output O ); assign O = T ? 1'bz : A; endmodule module CC_IOBUF #( parameter PIN_NAME = "UNPLACED", parameter V_IO = "UNDEFINED", parameter DRIVE = "UNDEFINED", parameter SLEW = "UNDEFINED", parameter [0:0] PULLUP = 1'bx, parameter [0:0] PULLDOWN = 1'bx, parameter [0:0] KEEPER = 1'bx, parameter [0:0] SCHMITT_TRIGGER = 1'bx, // IOSEL parameter [3:0] DELAY_IBF = 1'bx, parameter [3:0] DELAY_OBF = 1'bx, parameter [0:0] FF_IBF = 1'bx, parameter [0:0] FF_OBF = 1'bx )( input A, T, output Y, (* iopad_external_pin *) inout IO ); assign IO = T ? 1'bz : A; assign Y = IO; endmodule module CC_LVDS_IBUF #( parameter PIN_NAME_P = "UNPLACED", parameter PIN_NAME_N = "UNPLACED", parameter V_IO = "UNDEFINED", parameter [0:0] LVDS_RTERM = 1'bx, // IOSEL parameter [3:0] DELAY_IBF = 1'bx, parameter [0:0] FF_IBF = 1'bx )( (* iopad_external_pin *) input IP, IN, output Y ); assign Y = IP; endmodule module CC_LVDS_OBUF #( parameter PIN_NAME_P = "UNPLACED", parameter PIN_NAME_N = "UNPLACED", parameter V_IO = "UNDEFINED", parameter [0:0] LVDS_BOOST = 1'bx, // IOSEL parameter [3:0] DELAY_OBF = 1'bx, parameter [0:0] FF_OBF = 1'bx )( input A, (* iopad_external_pin *) output OP, ON ); assign OP = A; assign ON = ~A; endmodule module CC_LVDS_TOBUF #( parameter PIN_NAME_P = "UNPLACED", parameter PIN_NAME_N = "UNPLACED", parameter V_IO = "UNDEFINED", parameter [0:0] LVDS_BOOST = 1'bx, // IOSEL parameter [3:0] DELAY_OBF = 1'bx, parameter [0:0] FF_OBF = 1'bx )( input A, T, (* iopad_external_pin *) output OP, ON ); assign OP = T ? 1'bz : A; assign ON = T ? 1'bz : ~A; endmodule module CC_LVDS_IOBUF #( parameter PIN_NAME_P = "UNPLACED", parameter PIN_NAME_N = "UNPLACED", parameter V_IO = "UNDEFINED", parameter [0:0] LVDS_RTERM = 1'bx, parameter [0:0] LVDS_BOOST = 1'bx, // IOSEL parameter [3:0] DELAY_IBF = 1'bx, parameter [3:0] DELAY_OBF = 1'bx, parameter [0:0] FF_IBF = 1'bx, parameter [0:0] FF_OBF = 1'bx )( input A, T, (* iopad_external_pin *) inout IOP, ION, output Y ); assign IOP = T ? 1'bz : A; assign ION = T ? 1'bz : ~A; assign Y = IOP; endmodule module CC_IDDR #( parameter [0:0] CLK_INV = 1'b0 )( input D, (* clkbuf_sink *) input CLK, output reg Q0, Q1 ); wire clk; assign clk = (CLK_INV) ? ~CLK : CLK; always @(posedge clk) begin Q0 <= D; end always @(negedge clk) begin Q1 <= D; end endmodule module CC_ODDR #( parameter [0:0] CLK_INV = 1'b0 )( input D0, input D1, (* clkbuf_sink *) input CLK, (* clkbuf_sink *) input DDR, output Q ); wire clk; assign clk = (CLK_INV) ? ~CLK : CLK; reg q0, q1; assign Q = (DDR) ? q0 : q1; always @(posedge clk) begin q0 <= D0; end always @(negedge clk) begin q1 <= D1; end endmodule module CC_DFF #( parameter [0:0] CLK_INV = 1'b0, parameter [0:0] EN_INV = 1'b0, parameter [0:0] SR_INV = 1'b0, parameter [0:0] SR_VAL = 1'b0 )( input D, (* clkbuf_sink *) input CLK, input EN, input SR, output reg Q ); wire clk, en, sr; assign clk = (CLK_INV) ? ~CLK : CLK; assign en = (EN_INV) ? ~EN : EN; assign sr = (SR_INV) ? ~SR : SR; initial Q = 1'bX; always @(posedge clk or posedge sr) begin if (sr) begin Q <= SR_VAL; end else if (en) begin Q <= D; end end endmodule module CC_DLT #( parameter [0:0] G_INV = 1'b0, parameter [0:0] SR_INV = 1'b0, parameter [0:0] SR_VAL = 1'b0 )( input D, input G, input SR, output reg Q ); wire en, sr; assign en = (G_INV) ? ~G : G; assign sr = (SR_INV) ? ~SR : SR; initial Q = 1'bX; always @(*) begin if (sr) begin Q <= SR_VAL; end else if (en) begin Q <= D; end end endmodule module CC_LUT1 ( output O, input I0 ); parameter [1:0] INIT = 0; assign O = I0 ? INIT[1] : INIT[0]; endmodule module CC_LUT2 ( output O, input I0, I1 ); parameter [3:0] INIT = 0; wire [1:0] s1 = I1 ? INIT[3:2] : INIT[1:0]; assign O = I0 ? s1[1] : s1[0]; endmodule module CC_LUT3 ( output O, input I0, I1, I2 ); parameter [7:0] INIT = 0; wire [3:0] s2 = I2 ? INIT[7:4] : INIT[3:0]; wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0]; assign O = I0 ? s1[1] : s1[0]; endmodule module CC_LUT4 ( output O, input I0, I1, I2, I3 ); parameter [15:0] INIT = 0; wire [7:0] s3 = I3 ? INIT[15:8] : INIT[7:0]; wire [3:0] s2 = I2 ? s3[7:4] : s3[3:0]; wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0]; assign O = I0 ? s1[1] : s1[0]; endmodule module CC_MX2 ( input D0, D1, input S0, output Y ); assign Y = S0 ? D1 : D0; endmodule module CC_MX4 ( input D0, D1, D2, D3, input S0, S1, output Y ); assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0); endmodule module CC_MX8 ( input D0, D1, D2, D3, input D4, D5, D6, D7, input S0, S1, S2, output Y ); assign Y = S2 ? (S1 ? (S0 ? D7 : D6) : (S0 ? D5 : D4)) : (S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0)); endmodule module CC_ADDF ( input A, B, CI, output CO, S ); assign {CO, S} = A + B + CI; endmodule module CC_MULT #( parameter A_WIDTH = 0, parameter B_WIDTH = 0, parameter P_WIDTH = 0 )( input signed [A_WIDTH-1:0] A, input signed [B_WIDTH-1:0] B, output reg signed [P_WIDTH-1:0] P ); always @(*) begin P <= A * B; end endmodule module CC_BUFG ( input I, (* clkbuf_driver *) output O ); assign O = I; endmodule module CC_BRAM_20K ( output [19:0] A_DO, output [19:0] B_DO, output ECC_1B_ERR, output ECC_2B_ERR, (* clkbuf_sink *) input A_CLK, (* clkbuf_sink *) input B_CLK, input A_EN, input B_EN, input A_WE, input B_WE, input [15:0] A_ADDR, input [15:0] B_ADDR, input [19:0] A_DI, input [19:0] B_DI, input [19:0] A_BM, input [19:0] B_BM ); // Location format: D(0..N-1)(0..N-1)X(0..3)Y(0..7)Z(0..1) or UNPLACED parameter LOC = "UNPLACED"; // Port Widths parameter A_RD_WIDTH = 0; parameter B_RD_WIDTH = 0; parameter A_WR_WIDTH = 0; parameter B_WR_WIDTH = 0; // RAM and Write Modes parameter RAM_MODE = "SDP"; parameter A_WR_MODE = "NO_CHANGE"; parameter B_WR_MODE = "NO_CHANGE"; // Inverting Control Pins parameter A_CLK_INV = 1'b0; parameter B_CLK_INV = 1'b0; parameter A_EN_INV = 1'b0; parameter B_EN_INV = 1'b0; parameter A_WE_INV = 1'b0; parameter B_WE_INV = 1'b0; // Output Register parameter A_DO_REG = 1'b0; parameter B_DO_REG = 1'b0; // Error Checking and Correction parameter ECC_EN = 1'b0; // RAM Contents parameter INIT_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; localparam WIDTH_MODE_A = (A_RD_WIDTH > A_WR_WIDTH) ? A_RD_WIDTH : A_WR_WIDTH; localparam WIDTH_MODE_B = (B_RD_WIDTH > B_WR_WIDTH) ? B_RD_WIDTH : B_WR_WIDTH; integer i, k; // 512 x 40 bit reg [20479:0] memory = 20480'b0; initial begin // Check parameters if ((RAM_MODE != "SDP") && (RAM_MODE != "TDP")) begin $display("ERROR: Illegal RAM MODE %d.", RAM_MODE); $finish(); end if ((A_WR_MODE != "WRITE_THROUGH") && (A_WR_MODE != "NO_CHANGE")) begin $display("ERROR: Illegal RAM MODE %d.", RAM_MODE); $finish(); end if ((RAM_MODE == "SDP") && (A_WR_MODE == "WRITE_THROUGH")) begin $display("ERROR: %s is not supported in %s mode.", A_WR_MODE, RAM_MODE); $finish(); end if (ECC_EN != 1'b0) begin $display("WARNING: ECC feature not supported in simulation."); end if ((ECC_EN == 1'b1) && (RAM_MODE != "SDP") && (WIDTH_MODE_A != 40)) begin $display("ERROR: Illegal ECC Port configuration. Must be SDP 40 bit, but is %s %d.", RAM_MODE, WIDTH_MODE_A); $finish(); end if ((WIDTH_MODE_A == 40) && (RAM_MODE == "TDP")) begin $display("ERROR: Port A width of 40 bits is only supported in SDP mode."); $finish(); end if ((WIDTH_MODE_B == 40) && (RAM_MODE == "TDP")) begin $display("ERROR: Port B width of 40 bits is only supported in SDP mode."); $finish(); end if ((WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) && (WIDTH_MODE_A != 5) && (WIDTH_MODE_A != 2) && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A); $finish(); end if ((WIDTH_MODE_B != 40) && (WIDTH_MODE_B != 20) && (WIDTH_MODE_B != 10) && (WIDTH_MODE_B != 5) && (WIDTH_MODE_B != 2) && (WIDTH_MODE_B != 1) && (WIDTH_MODE_B != 0)) begin $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B); $finish(); end // RAM initialization memory[320*0+319:320*0] = INIT_00; memory[320*1+319:320*1] = INIT_01; memory[320*2+319:320*2] = INIT_02; memory[320*3+319:320*3] = INIT_03; memory[320*4+319:320*4] = INIT_04; memory[320*5+319:320*5] = INIT_05; memory[320*6+319:320*6] = INIT_06; memory[320*7+319:320*7] = INIT_07; memory[320*8+319:320*8] = INIT_08; memory[320*9+319:320*9] = INIT_09; memory[320*10+319:320*10] = INIT_0A; memory[320*11+319:320*11] = INIT_0B; memory[320*12+319:320*12] = INIT_0C; memory[320*13+319:320*13] = INIT_0D; memory[320*14+319:320*14] = INIT_0E; memory[320*15+319:320*15] = INIT_0F; memory[320*16+319:320*16] = INIT_10; memory[320*17+319:320*17] = INIT_11; memory[320*18+319:320*18] = INIT_12; memory[320*19+319:320*19] = INIT_13; memory[320*20+319:320*20] = INIT_14; memory[320*21+319:320*21] = INIT_15; memory[320*22+319:320*22] = INIT_16; memory[320*23+319:320*23] = INIT_17; memory[320*24+319:320*24] = INIT_18; memory[320*25+319:320*25] = INIT_19; memory[320*26+319:320*26] = INIT_1A; memory[320*27+319:320*27] = INIT_1B; memory[320*28+319:320*28] = INIT_1C; memory[320*29+319:320*29] = INIT_1D; memory[320*30+319:320*30] = INIT_1E; memory[320*31+319:320*31] = INIT_1F; memory[320*32+319:320*32] = INIT_20; memory[320*33+319:320*33] = INIT_21; memory[320*34+319:320*34] = INIT_22; memory[320*35+319:320*35] = INIT_23; memory[320*36+319:320*36] = INIT_24; memory[320*37+319:320*37] = INIT_25; memory[320*38+319:320*38] = INIT_26; memory[320*39+319:320*39] = INIT_27; memory[320*40+319:320*40] = INIT_28; memory[320*41+319:320*41] = INIT_29; memory[320*42+319:320*42] = INIT_2A; memory[320*43+319:320*43] = INIT_2B; memory[320*44+319:320*44] = INIT_2C; memory[320*45+319:320*45] = INIT_2D; memory[320*46+319:320*46] = INIT_2E; memory[320*47+319:320*47] = INIT_2F; memory[320*48+319:320*48] = INIT_30; memory[320*49+319:320*49] = INIT_31; memory[320*50+319:320*50] = INIT_32; memory[320*51+319:320*51] = INIT_33; memory[320*52+319:320*52] = INIT_34; memory[320*53+319:320*53] = INIT_35; memory[320*54+319:320*54] = INIT_36; memory[320*55+319:320*55] = INIT_37; memory[320*56+319:320*56] = INIT_38; memory[320*57+319:320*57] = INIT_39; memory[320*58+319:320*58] = INIT_3A; memory[320*59+319:320*59] = INIT_3B; memory[320*60+319:320*60] = INIT_3C; memory[320*61+319:320*61] = INIT_3D; memory[320*62+319:320*62] = INIT_3E; memory[320*63+319:320*63] = INIT_3F; end // Signal inversion wire clka = A_CLK_INV ^ A_CLK; wire clkb = B_CLK_INV ^ B_CLK; wire ena = A_EN_INV ^ A_EN; wire enb = B_EN_INV ^ B_EN; wire wea = A_WE_INV ^ A_WE; wire web = B_WE_INV ^ B_WE; // Internal signals wire [15:0] addra; wire [15:0] addrb; reg [19:0] A_DO_out = 0, A_DO_reg = 0; reg [19:0] B_DO_out = 0, B_DO_reg = 0; generate if (RAM_MODE == "SDP") begin // Port A (write) if (A_WR_WIDTH == 40) begin assign addra = A_ADDR[15:7]*40; end // Port B (read) if (B_RD_WIDTH == 40) begin assign addrb = B_ADDR[15:7]*40; end end else if (RAM_MODE == "TDP") begin // Port A if (WIDTH_MODE_A <= 1) begin wire [15:0] tmpa = {2'b0, A_ADDR[15:7], A_ADDR[5:1]}; assign addra = tmpa + (tmpa/4); end else if (WIDTH_MODE_A <= 2) begin wire [15:0] tmpa = {3'b0, A_ADDR[15:7], A_ADDR[5:2]}; assign addra = tmpa*2 + (tmpa/2); end else if (WIDTH_MODE_A <= 5) begin assign addra = {4'b0, A_ADDR[15:7], A_ADDR[5:3]}*5; end else if (WIDTH_MODE_A <= 10) begin assign addra = {5'b0, A_ADDR[15:7], A_ADDR[5:4]}*10; end else if (WIDTH_MODE_A <= 20) begin assign addra = {6'b0, A_ADDR[15:7], A_ADDR[5]}*20; end // Port B if (WIDTH_MODE_B <= 1) begin wire [15:0] tmpb = {2'b0, B_ADDR[15:7], B_ADDR[5:1]}; assign addrb = tmpb + (tmpb/4); end else if (WIDTH_MODE_B <= 2) begin wire [15:0] tmpb = {3'b0, B_ADDR[15:7], B_ADDR[5:2]}; assign addrb = tmpb*2 + (tmpb/2); end else if (WIDTH_MODE_B <= 5) begin assign addrb = {4'b0, B_ADDR[15:7], B_ADDR[5:3]}*5; end else if (WIDTH_MODE_B <= 10) begin assign addrb = {5'b0, B_ADDR[15:7], B_ADDR[5:4]}*10; end else if (WIDTH_MODE_B <= 20) begin assign addrb = {6'b0, B_ADDR[15:7], B_ADDR[5]}*20; end end endgenerate generate if (RAM_MODE == "SDP") begin // SDP write port always @(posedge clka) begin for (k=0; k < A_WR_WIDTH; k=k+1) begin if (k < 20) begin if (ena && wea && A_BM[k]) memory[addra+k] <= A_DI[k]; end else begin // use both ports if (ena && wea && B_BM[k-20]) memory[addra+k] <= B_DI[k-20]; end end end // SDP read port always @(posedge clkb) begin // "NO_CHANGE" only for (k=0; k < B_RD_WIDTH; k=k+1) begin if (k < 20) begin if (enb && !wea) A_DO_out[k] <= memory[addrb+k]; end else begin // use both ports if (enb && !wea) B_DO_out[k-20] <= memory[addrb+k]; end end end end else if (RAM_MODE == "TDP") begin // TDP port A always @(posedge clka) begin for (i=0; i < WIDTH_MODE_A; i=i+1) begin if (ena && wea && A_BM[i]) memory[addra+i] <= A_DI[i]; if (A_WR_MODE == "NO_CHANGE") begin if (ena && !wea) A_DO_out[i] <= memory[addra+i]; end else if (A_WR_MODE == "WRITE_THROUGH") begin if (ena) begin if (wea && A_BM[i]) begin A_DO_out[i] <= A_DI[i]; end else begin A_DO_out[i] <= memory[addra+i]; end end end end end // TDP port B always @(posedge clkb) begin for (i=0; i < WIDTH_MODE_B; i=i+1) begin if (enb && web && B_BM[i]) memory[addrb+i] <= B_DI[i]; if (B_WR_MODE == "NO_CHANGE") begin if (enb && !web) B_DO_out[i] <= memory[addrb+i]; end else if (B_WR_MODE == "WRITE_THROUGH") begin if (enb) begin if (web && B_BM[i]) begin B_DO_out[i] <= B_DI[i]; end else begin B_DO_out[i] <= memory[addrb+i]; end end end end end end endgenerate // Optional output register generate if (A_DO_REG) begin always @(posedge clka) begin A_DO_reg <= A_DO_out; end assign A_DO = A_DO_reg; end else begin assign A_DO = A_DO_out; end if (B_DO_REG) begin always @(posedge clkb) begin B_DO_reg <= B_DO_out; end assign B_DO = B_DO_reg; end else begin assign B_DO = B_DO_out; end endgenerate endmodule module CC_BRAM_40K ( output [39:0] A_DO, output [39:0] B_DO, output A_ECC_1B_ERR, output B_ECC_1B_ERR, output A_ECC_2B_ERR, output B_ECC_2B_ERR, output reg A_CO = 0, output reg B_CO = 0, (* clkbuf_sink *) input A_CLK, (* clkbuf_sink *) input B_CLK, input A_EN, input B_EN, input A_WE, input B_WE, input [15:0] A_ADDR, input [15:0] B_ADDR, input [39:0] A_DI, input [39:0] B_DI, input [39:0] A_BM, input [39:0] B_BM, input A_CI, input B_CI ); // Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED parameter LOC = "UNPLACED"; parameter CAS = "NONE"; // NONE, UPPER, LOWER // Port Widths parameter A_RD_WIDTH = 0; parameter B_RD_WIDTH = 0; parameter A_WR_WIDTH = 0; parameter B_WR_WIDTH = 0; // RAM and Write Modes parameter RAM_MODE = "SDP"; parameter A_WR_MODE = "NO_CHANGE"; parameter B_WR_MODE = "NO_CHANGE"; // Inverting Control Pins parameter A_CLK_INV = 1'b0; parameter B_CLK_INV = 1'b0; parameter A_EN_INV = 1'b0; parameter B_EN_INV = 1'b0; parameter A_WE_INV = 1'b0; parameter B_WE_INV = 1'b0; // Output Register parameter A_DO_REG = 1'b0; parameter B_DO_REG = 1'b0; // Error Checking and Correction parameter A_ECC_EN = 1'b0; parameter B_ECC_EN = 1'b0; parameter INIT_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_40 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_41 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_42 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_43 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_44 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_45 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_46 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_47 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_48 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_49 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_4A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_4B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_4C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_4D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_4E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_4F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_50 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_51 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_52 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_53 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_54 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_55 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_56 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_57 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_58 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_59 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_5A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_5B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_5C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_5D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_5E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_5F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_60 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_61 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_62 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_63 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_64 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_65 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_66 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_67 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_68 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_69 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_6A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_6B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_6C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_6D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_6E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_6F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_70 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_71 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_72 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_73 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_74 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_75 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_76 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_77 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_78 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_79 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_7A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_7B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_7C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_7D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_7E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INIT_7F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; localparam WIDTH_MODE_A = (A_RD_WIDTH > A_WR_WIDTH) ? A_RD_WIDTH : A_WR_WIDTH; localparam WIDTH_MODE_B = (B_RD_WIDTH > B_WR_WIDTH) ? B_RD_WIDTH : B_WR_WIDTH; integer i, k; // 512 x 80 bit reg [40959:0] memory = 40960'b0; initial begin // Check parameters if ((RAM_MODE != "SDP") && (RAM_MODE != "TDP")) begin $display("ERROR: Illegal RAM MODE %d.", RAM_MODE); $finish(); end if ((A_WR_MODE != "WRITE_THROUGH") && (A_WR_MODE != "NO_CHANGE")) begin $display("ERROR: Illegal RAM MODE %d.", RAM_MODE); $finish(); end if ((RAM_MODE == "SDP") && (A_WR_MODE == "WRITE_THROUGH")) begin $display("ERROR: %s is not supported in %s mode.", A_WR_MODE, RAM_MODE); $finish(); end if ((A_ECC_EN != 1'b0) || (B_ECC_EN != 1'b0)) begin $display("WARNING: ECC feature not supported in simulation."); end if ((A_ECC_EN == 1'b1) && (RAM_MODE != "SDP") && (WIDTH_MODE_A != 40)) begin $display("ERROR: Illegal ECC Port A configuration. Must be SDP 40 bit, but is %s %d.", RAM_MODE, WIDTH_MODE_A); $finish(); end if ((WIDTH_MODE_A == 80) && (RAM_MODE == "TDP")) begin $display("ERROR: Port A width of 80 bits is only supported in SDP mode."); $finish(); end if ((WIDTH_MODE_B == 80) && (RAM_MODE == "TDP")) begin $display("ERROR: Port B width of 80 bits is only supported in SDP mode."); $finish(); end if ((WIDTH_MODE_A != 80) && (WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) && (WIDTH_MODE_A != 5) && (WIDTH_MODE_A != 2) && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A); $finish(); end if ((WIDTH_MODE_B != 80) && (WIDTH_MODE_B != 40) && (WIDTH_MODE_B != 20) && (WIDTH_MODE_B != 10) && (WIDTH_MODE_B != 5) && (WIDTH_MODE_B != 2) && (WIDTH_MODE_B != 1) && (WIDTH_MODE_B != 0)) begin $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B); $finish(); end if ((CAS != "NONE") && ((WIDTH_MODE_A > 1) || (WIDTH_MODE_B > 1))) begin $display("ERROR: Cascade feature only supported in 1 bit data width mode."); $finish(); end if ((CAS != "NONE") && (RAM_MODE != "TDP")) begin $display("ERROR: Cascade feature only supported in TDP mode."); $finish(); end // RAM initialization memory[320*0+319:320*0] = INIT_00; memory[320*1+319:320*1] = INIT_01; memory[320*2+319:320*2] = INIT_02; memory[320*3+319:320*3] = INIT_03; memory[320*4+319:320*4] = INIT_04; memory[320*5+319:320*5] = INIT_05; memory[320*6+319:320*6] = INIT_06; memory[320*7+319:320*7] = INIT_07; memory[320*8+319:320*8] = INIT_08; memory[320*9+319:320*9] = INIT_09; memory[320*10+319:320*10] = INIT_0A; memory[320*11+319:320*11] = INIT_0B; memory[320*12+319:320*12] = INIT_0C; memory[320*13+319:320*13] = INIT_0D; memory[320*14+319:320*14] = INIT_0E; memory[320*15+319:320*15] = INIT_0F; memory[320*16+319:320*16] = INIT_10; memory[320*17+319:320*17] = INIT_11; memory[320*18+319:320*18] = INIT_12; memory[320*19+319:320*19] = INIT_13; memory[320*20+319:320*20] = INIT_14; memory[320*21+319:320*21] = INIT_15; memory[320*22+319:320*22] = INIT_16; memory[320*23+319:320*23] = INIT_17; memory[320*24+319:320*24] = INIT_18; memory[320*25+319:320*25] = INIT_19; memory[320*26+319:320*26] = INIT_1A; memory[320*27+319:320*27] = INIT_1B; memory[320*28+319:320*28] = INIT_1C; memory[320*29+319:320*29] = INIT_1D; memory[320*30+319:320*30] = INIT_1E; memory[320*31+319:320*31] = INIT_1F; memory[320*32+319:320*32] = INIT_20; memory[320*33+319:320*33] = INIT_21; memory[320*34+319:320*34] = INIT_22; memory[320*35+319:320*35] = INIT_23; memory[320*36+319:320*36] = INIT_24; memory[320*37+319:320*37] = INIT_25; memory[320*38+319:320*38] = INIT_26; memory[320*39+319:320*39] = INIT_27; memory[320*40+319:320*40] = INIT_28; memory[320*41+319:320*41] = INIT_29; memory[320*42+319:320*42] = INIT_2A; memory[320*43+319:320*43] = INIT_2B; memory[320*44+319:320*44] = INIT_2C; memory[320*45+319:320*45] = INIT_2D; memory[320*46+319:320*46] = INIT_2E; memory[320*47+319:320*47] = INIT_2F; memory[320*48+319:320*48] = INIT_30; memory[320*49+319:320*49] = INIT_31; memory[320*50+319:320*50] = INIT_32; memory[320*51+319:320*51] = INIT_33; memory[320*52+319:320*52] = INIT_34; memory[320*53+319:320*53] = INIT_35; memory[320*54+319:320*54] = INIT_36; memory[320*55+319:320*55] = INIT_37; memory[320*56+319:320*56] = INIT_38; memory[320*57+319:320*57] = INIT_39; memory[320*58+319:320*58] = INIT_3A; memory[320*59+319:320*59] = INIT_3B; memory[320*60+319:320*60] = INIT_3C; memory[320*61+319:320*61] = INIT_3D; memory[320*62+319:320*62] = INIT_3E; memory[320*63+319:320*63] = INIT_3F; memory[320*64+319:320*64] = INIT_40; memory[320*65+319:320*65] = INIT_41; memory[320*66+319:320*66] = INIT_42; memory[320*67+319:320*67] = INIT_43; memory[320*68+319:320*68] = INIT_44; memory[320*69+319:320*69] = INIT_45; memory[320*70+319:320*70] = INIT_46; memory[320*71+319:320*71] = INIT_47; memory[320*72+319:320*72] = INIT_48; memory[320*73+319:320*73] = INIT_49; memory[320*74+319:320*74] = INIT_4A; memory[320*75+319:320*75] = INIT_4B; memory[320*76+319:320*76] = INIT_4C; memory[320*77+319:320*77] = INIT_4D; memory[320*78+319:320*78] = INIT_4E; memory[320*79+319:320*79] = INIT_4F; memory[320*80+319:320*80] = INIT_50; memory[320*81+319:320*81] = INIT_51; memory[320*82+319:320*82] = INIT_52; memory[320*83+319:320*83] = INIT_53; memory[320*84+319:320*84] = INIT_54; memory[320*85+319:320*85] = INIT_55; memory[320*86+319:320*86] = INIT_56; memory[320*87+319:320*87] = INIT_57; memory[320*88+319:320*88] = INIT_58; memory[320*89+319:320*89] = INIT_59; memory[320*90+319:320*90] = INIT_5A; memory[320*91+319:320*91] = INIT_5B; memory[320*92+319:320*92] = INIT_5C; memory[320*93+319:320*93] = INIT_5D; memory[320*94+319:320*94] = INIT_5E; memory[320*95+319:320*95] = INIT_5F; memory[320*96+319:320*96] = INIT_60; memory[320*97+319:320*97] = INIT_61; memory[320*98+319:320*98] = INIT_62; memory[320*99+319:320*99] = INIT_63; memory[320*100+319:320*100] = INIT_64; memory[320*101+319:320*101] = INIT_65; memory[320*102+319:320*102] = INIT_66; memory[320*103+319:320*103] = INIT_67; memory[320*104+319:320*104] = INIT_68; memory[320*105+319:320*105] = INIT_69; memory[320*106+319:320*106] = INIT_6A; memory[320*107+319:320*107] = INIT_6B; memory[320*108+319:320*108] = INIT_6C; memory[320*109+319:320*109] = INIT_6D; memory[320*110+319:320*110] = INIT_6E; memory[320*111+319:320*111] = INIT_6F; memory[320*112+319:320*112] = INIT_70; memory[320*113+319:320*113] = INIT_71; memory[320*114+319:320*114] = INIT_72; memory[320*115+319:320*115] = INIT_73; memory[320*116+319:320*116] = INIT_74; memory[320*117+319:320*117] = INIT_75; memory[320*118+319:320*118] = INIT_76; memory[320*119+319:320*119] = INIT_77; memory[320*120+319:320*120] = INIT_78; memory[320*121+319:320*121] = INIT_79; memory[320*122+319:320*122] = INIT_7A; memory[320*123+319:320*123] = INIT_7B; memory[320*124+319:320*124] = INIT_7C; memory[320*125+319:320*125] = INIT_7D; memory[320*126+319:320*126] = INIT_7E; memory[320*127+319:320*127] = INIT_7F; end // Signal inversion wire clka = A_CLK_INV ^ A_CLK; wire clkb = B_CLK_INV ^ B_CLK; wire ena = A_EN_INV ^ A_EN; wire enb = B_EN_INV ^ B_EN; wire wea = A_WE_INV ^ A_WE; wire web = B_WE_INV ^ B_WE; // Internal signals wire [15:0] addra; wire [15:0] addrb; reg [39:0] A_DO_out = 0, A_DO_reg = 0; reg [39:0] B_DO_out = 0, B_DO_reg = 0; generate if (RAM_MODE == "SDP") begin // Port A (write) if (A_WR_WIDTH == 80) begin assign addra = A_ADDR[15:7]*80; end // Port B (read) if (B_RD_WIDTH == 80) begin assign addrb = B_ADDR[15:7]*80; end end else if (RAM_MODE == "TDP") begin // Port A if (WIDTH_MODE_A <= 1) begin wire [15:0] tmpa = {1'b0, A_ADDR[15:1]}; assign addra = tmpa + (tmpa/4); end else if (WIDTH_MODE_A <= 2) begin wire [15:0] tmpa = {2'b0, A_ADDR[15:2]}; assign addra = tmpa*2 + (tmpa/2); end else if (WIDTH_MODE_A <= 5) begin assign addra = {3'b0, A_ADDR[15:3]}*5; end else if (WIDTH_MODE_A <= 10) begin assign addra = {4'b0, A_ADDR[15:4]}*10; end else if (WIDTH_MODE_A <= 20) begin assign addra = {5'b0, A_ADDR[15:5]}*20; end else if (WIDTH_MODE_A <= 40) begin assign addra = {6'b0, A_ADDR[15:6]}*40; end // Port B if (WIDTH_MODE_B <= 1) begin wire [15:0] tmpb = {1'b0, B_ADDR[15:1]}; assign addrb = tmpb + (tmpb/4); end else if (WIDTH_MODE_B <= 2) begin wire [15:0] tmpb = {2'b0, B_ADDR[15:2]}; assign addrb = tmpb*2 + (tmpb/2); end else if (WIDTH_MODE_B <= 5) begin assign addrb = {3'b0, B_ADDR[15:3]}*5; end else if (WIDTH_MODE_B <= 10) begin assign addrb = {4'b0, B_ADDR[15:4]}*10; end else if (WIDTH_MODE_B <= 20) begin assign addrb = {5'b0, B_ADDR[15:5]}*20; end else if (WIDTH_MODE_B <= 40) begin assign addrb = {6'b0, B_ADDR[15:6]}*40; end end endgenerate generate if (RAM_MODE == "SDP") begin // SDP write port always @(posedge clka) begin for (k=0; k < A_WR_WIDTH; k=k+1) begin if (k < 40) begin if (ena && wea && A_BM[k]) memory[addra+k] <= A_DI[k]; end else begin // use both ports if (ena && wea && B_BM[k-40]) memory[addra+k] <= B_DI[k-40]; end end end // SDP read port always @(posedge clkb) begin // "NO_CHANGE" only for (k=0; k < B_RD_WIDTH; k=k+1) begin if (k < 40) begin if (enb && !wea) A_DO_out[k] <= memory[addrb+k]; end else begin // use both ports if (enb && !wea) B_DO_out[k-40] <= memory[addrb+k]; end end end end else if (RAM_MODE == "TDP") begin // {A,B}_ADDR[0]=0 selects lower, {A,B}_ADDR[0]=1 selects upper cascade memory wire upper_sel_a = ((CAS == "UPPER") && (A_ADDR[0] == 1)); wire lower_sel_a = ((CAS == "LOWER") && (A_ADDR[0] == 0)); wire upper_sel_b = ((CAS == "UPPER") && (B_ADDR[0] == 1)); wire lower_sel_b = ((CAS == "LOWER") && (B_ADDR[0] == 0)); reg dumm; // Cascade output port A always @(*) begin if ((A_WR_MODE == "NO_CHANGE") && lower_sel_a) begin A_CO = memory[addra]; end else if ((A_WR_MODE == "WRITE_THROUGH") && lower_sel_a) begin A_CO = ((wea && A_BM[0]) ? (A_DI[0]) : (memory[addra])); end end // Cascade output port B always @(*) begin if ((B_WR_MODE == "NO_CHANGE") && lower_sel_b) begin B_CO = memory[addrb]; end else if ((B_WR_MODE == "WRITE_THROUGH") && lower_sel_b) begin B_CO = ((web && B_BM[0]) ? (B_DI[0]) : (memory[addrb])); end end // TDP port A always @(posedge clka) begin for (i=0; i < WIDTH_MODE_A; i=i+1) begin if (upper_sel_a || lower_sel_a || (CAS == "NONE")) begin if (ena && wea && A_BM[i]) memory[addra+i] <= A_DI[i]; end if (A_WR_MODE == "NO_CHANGE") begin if (ena && !wea) begin if (CAS == "UPPER") begin A_DO_out[i] <= ((A_ADDR[0] == 1) ? (memory[addra+i]) : (A_CI)); end else if (CAS == "NONE") begin A_DO_out[i] <= memory[addra+i]; end end end else if (A_WR_MODE == "WRITE_THROUGH") begin if (ena) begin if (CAS == "UPPER") begin if (A_ADDR[0] == 1) begin A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i])); end else begin A_DO_out[i] <= A_CI; end end else if (CAS == "NONE") begin A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i])); end end end end end // TDP port B always @(posedge clkb) begin for (i=0; i < WIDTH_MODE_B; i=i+1) begin if (upper_sel_b || lower_sel_b || (CAS == "NONE")) begin if (enb && web && B_BM[i]) memory[addrb+i] <= B_DI[i]; end if (B_WR_MODE == "NO_CHANGE") begin if (enb && !web) begin if (CAS == "UPPER") begin B_DO_out[i] <= ((B_ADDR[0] == 1) ? (memory[addrb+i]) : (B_CI)); end else if (CAS == "NONE") begin B_DO_out[i] <= memory[addrb+i]; end end end else if (B_WR_MODE == "WRITE_THROUGH") begin if (enb) begin if (CAS == "UPPER") begin if (B_ADDR[0] == 1) begin B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i])); end else begin B_DO_out[i] <= B_CI; end end else if (CAS == "NONE") begin B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i])); end end end end end end endgenerate // Optional output register generate if (A_DO_REG) begin always @(posedge clka) begin A_DO_reg <= A_DO_out; end assign A_DO = A_DO_reg; end else begin assign A_DO = A_DO_out; end if (B_DO_REG) begin always @(posedge clkb) begin B_DO_reg <= B_DO_out; end assign B_DO = B_DO_reg; end else begin assign B_DO = B_DO_out; end endgenerate endmodule