ql-qlf: qlf_k6n10f: add TDPBRAM36 simulation models Signed-off-by: Paweł Czarnecki <pczarnecki@antmicro.com>
diff --git a/ql-qlf-plugin/qlf_k6n10f/TDP18Kx18_FIFO.v b/ql-qlf-plugin/qlf_k6n10f/TDP18Kx18_FIFO.v new file mode 100644 index 0000000..185cb96 --- /dev/null +++ b/ql-qlf-plugin/qlf_k6n10f/TDP18Kx18_FIFO.v
@@ -0,0 +1,353 @@ +// Copyright (C) 2020-2021 The SymbiFlow Authors. +// +// Use of this source code is governed by a ISC-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/ISC +// +// SPDX-License-Identifier:ISC + +module TDP18Kx18_FIFO ( + RMODE_A, + RMODE_B, + WMODE_A, + WMODE_B, + WEN_A, + WEN_B, + REN_A, + REN_B, + CLK_A, + CLK_B, + BE_A, + BE_B, + ADDR_A, + ADDR_B, + WDATA_A, + WDATA_B, + RDATA_A, + RDATA_B, + EMPTY, + EPO, + EWM, + UNDERRUN, + FULL, + FMO, + FWM, + OVERRUN, + FLUSH, + FMODE, + SYNC_FIFO, + POWERDN, + SLEEP, + PROTECT, + UPAF, + UPAE, + PL_INIT, + PL_ENA, + PL_WEN, + PL_REN, + PL_CLK, + PL_ADDR, + PL_DATA_IN, + PL_DATA_OUT, + RAM_ID +); + input wire [2:0] RMODE_A; + input wire [2:0] RMODE_B; + input wire [2:0] WMODE_A; + input wire [2:0] WMODE_B; + input wire WEN_A; + input wire WEN_B; + input wire REN_A; + input wire REN_B; + input wire CLK_A; + input wire CLK_B; + input wire [1:0] BE_A; + input wire [1:0] BE_B; + input wire [13:0] ADDR_A; + input wire [13:0] ADDR_B; + input wire [17:0] WDATA_A; + input wire [17:0] WDATA_B; + output reg [17:0] RDATA_A; + output reg [17:0] RDATA_B; + output wire EMPTY; + output wire EPO; + output wire EWM; + output wire UNDERRUN; + output wire FULL; + output wire FMO; + output wire FWM; + output wire OVERRUN; + input wire FLUSH; + input wire FMODE; + input wire SYNC_FIFO; + input wire POWERDN; + input wire SLEEP; + input wire PROTECT; + input wire [10:0] UPAF; + input wire [10:0] UPAE; + input PL_INIT; + input PL_ENA; + input PL_WEN; + input PL_REN; + input PL_CLK; + input [23:0] PL_ADDR; + input [17:0] PL_DATA_IN; + output reg [17:0] PL_DATA_OUT; + input [8:0] RAM_ID; + reg [17:0] wmsk_a; + reg [17:0] wmsk_b; + wire [8:0] addr_a; + wire [8:0] addr_b; + reg [4:0] addr_a_d; + reg [4:0] addr_b_d; + wire [17:0] ram_rdata_a; + wire [17:0] ram_rdata_b; + reg [17:0] aligned_wdata_a; + reg [17:0] aligned_wdata_b; + wire ren_o; + wire [10:0] ff_raddr; + wire [10:0] ff_waddr; + wire [13:0] ram_addr_a; + wire [13:0] ram_addr_b; + wire preload; + wire my_id; + wire initn; + wire smux_rclk; + wire smux_wclk; + wire real_fmode; + wire [3:0] raw_fflags; + reg [1:0] fifo_rmode; + reg [1:0] fifo_wmode; + wire smux_clk_a; + wire smux_clk_b; + wire ram_ren_a; + wire ram_ren_b; + wire ram_wen_a; + wire ram_wen_b; + wire cen_a; + wire cen_b; + localparam MODE_9 = 3'b101; + always @(*) begin + fifo_rmode = (RMODE_B == MODE_9 ? 2'b10 : 2'b01); + fifo_wmode = (WMODE_A == MODE_9 ? 2'b10 : 2'b01); + end + assign my_id = (PL_ADDR[23:14] == RAM_ID) | PL_INIT; + assign preload = (PROTECT ? 1'b0 : my_id & PL_ENA); + assign smux_clk_a = (preload ? PL_CLK : CLK_A); + assign smux_clk_b = (preload ? 0 : (FMODE ? (SYNC_FIFO ? CLK_A : CLK_B) : CLK_B)); + assign real_fmode = (preload ? 1'b0 : FMODE); + assign ram_ren_b = (preload ? PL_REN : (real_fmode ? ren_o : REN_B)); + assign ram_wen_a = (preload ? PL_WEN : (FMODE ? ~FULL & WEN_A : WEN_A)); + assign ram_ren_a = (preload ? 1'b1 : (FMODE ? 0 : REN_A)); + assign ram_wen_b = (preload ? 1'b1 : (FMODE ? 1'b0 : WEN_B)); + assign cen_b = ram_ren_b | ram_wen_b; + assign cen_a = ram_ren_a | ram_wen_a; + assign ram_addr_b = (preload ? {PL_ADDR[9:0], 4'b0000} : (real_fmode ? {ff_raddr[10:0], 3'b000} : {ADDR_B[13:4], addr_b_d[3:0]})); + assign ram_addr_a = (preload ? {PL_ADDR[8:0], 4'b0000} : (real_fmode ? {ff_waddr[10:0], 3'b000} : {ADDR_A[13:4], addr_a_d[3:0]})); + always @(posedge CLK_A) addr_a_d[3:0] <= ADDR_A[3:0]; + always @(posedge CLK_B) addr_b_d[3:0] <= ADDR_B[3:0]; + sram1024x18 uram( + .clk_a(smux_clk_a), + .cen_a(~cen_a), + .wen_a(~ram_wen_a), + .addr_a(ram_addr_a[13:4]), + .wmsk_a(wmsk_a), + .wdata_a(aligned_wdata_a), + .rdata_a(ram_rdata_a), + .clk_b(smux_clk_b), + .cen_b(~cen_b), + .wen_b(~ram_wen_b), + .addr_b(ram_addr_b[13:4]), + .wmsk_b(wmsk_b), + .wdata_b(aligned_wdata_b), + .rdata_b(ram_rdata_b) + ); + fifo_ctl #( + .ADDR_WIDTH(11), + .FIFO_WIDTH(2) + ) fifo_ctl( + .rclk(smux_clk_b), + .rst_R_n(~FLUSH), + .wclk(smux_clk_a), + .rst_W_n(~FLUSH), + .ren(REN_B), + .wen(ram_wen_a), + .depth(3'b000), + .sync(SYNC_FIFO), + .rmode(fifo_rmode), + .wmode(fifo_wmode), + .ren_o(ren_o), + .fflags({FULL, FMO, FWM, OVERRUN, EMPTY, EPO, EWM, UNDERRUN}), + .raddr(ff_raddr), + .waddr(ff_waddr), + .upaf(UPAF), + .upae(UPAE) + ); + always @(*) begin : PRELOAD_DATA + if (preload & ram_ren_a) + PL_DATA_OUT = ram_rdata_a; + else + PL_DATA_OUT = PL_DATA_IN; + end + localparam MODE_1 = 3'b001; + localparam MODE_18 = 3'b110; + localparam MODE_2 = 3'b010; + localparam MODE_4 = 3'b100; + always @(*) begin : WDATA_MODE_SEL + if (ram_wen_a == 1) begin + if (preload) begin + aligned_wdata_a = PL_DATA_IN; + wmsk_a = 18'h00000; + end + else + case (WMODE_A) + MODE_18: begin + aligned_wdata_a = WDATA_A; + {wmsk_a[17], wmsk_a[15:8]} = (FMODE ? 9'h000 : (BE_A[1] ? 9'h000 : 9'h1ff)); + {wmsk_a[16], wmsk_a[7:0]} = (FMODE ? 9'h000 : (BE_A[0] ? 9'h000 : 9'h1ff)); + end + MODE_9: begin + aligned_wdata_a = {{2 {WDATA_A[16]}}, {2 {WDATA_A[7:0]}}}; + {wmsk_a[17], wmsk_a[15:8]} = (ram_addr_a[3] ? (FMODE ? 9'h000 : (BE_A[0] ? 9'h000 : 9'h1ff)) : 9'h1ff); + {wmsk_a[16], wmsk_a[7:0]} = (ram_addr_a[3] ? 9'h1ff : (FMODE ? 9'h000 : (BE_A[0] ? 9'h000 : 9'h1ff))); + end + MODE_4: begin + aligned_wdata_a = {2'b00, {4 {WDATA_A[3:0]}}}; + wmsk_a[17:16] = 2'b11; + wmsk_a[15:12] = (ram_addr_a[3:2] == 2'b11 ? 4'h0 : 4'hf); + wmsk_a[11:8] = (ram_addr_a[3:2] == 2'b10 ? 4'h0 : 4'hf); + wmsk_a[7:4] = (ram_addr_a[3:2] == 2'b01 ? 4'h0 : 4'hf); + wmsk_a[3:0] = (ram_addr_a[3:2] == 2'b00 ? 4'h0 : 4'hf); + end + MODE_2: begin + aligned_wdata_a = {2'b00, {8 {WDATA_A[1:0]}}}; + wmsk_a[17:16] = 2'b11; + wmsk_a[15:14] = (ram_addr_a[3:1] == 3'b111 ? 2'h0 : 2'h3); + wmsk_a[13:12] = (ram_addr_a[3:1] == 3'b110 ? 2'h0 : 2'h3); + wmsk_a[11:10] = (ram_addr_a[3:1] == 3'b101 ? 2'h0 : 2'h3); + wmsk_a[9:8] = (ram_addr_a[3:1] == 3'b100 ? 2'h0 : 2'h3); + wmsk_a[7:6] = (ram_addr_a[3:1] == 3'b011 ? 2'h0 : 2'h3); + wmsk_a[5:4] = (ram_addr_a[3:1] == 3'b010 ? 2'h0 : 2'h3); + wmsk_a[3:2] = (ram_addr_a[3:1] == 3'b001 ? 2'h0 : 2'h3); + wmsk_a[1:0] = (ram_addr_a[3:1] == 3'b000 ? 2'h0 : 2'h3); + end + MODE_1: begin + aligned_wdata_a = {2'b00, {16 {WDATA_A[0]}}}; + wmsk_a = 18'h3fffe; + wmsk_a[ram_addr_a[3:0]] = 0; + end + endcase + end + else begin + aligned_wdata_a = 18'h00000; + wmsk_a = 18'h3ffff; + end + if (ram_wen_b == 1) + case (WMODE_B) + MODE_18: begin + aligned_wdata_b = WDATA_B; + {wmsk_b[17], wmsk_b[15:8]} = (BE_B[1] ? 9'h000 : 9'h1ff); + {wmsk_b[16], wmsk_b[7:0]} = (BE_B[0] ? 9'h000 : 9'h1ff); + end + MODE_9: begin + aligned_wdata_b = {{2 {WDATA_B[16]}}, {2 {WDATA_B[7:0]}}}; + {wmsk_b[17], wmsk_b[15:8]} = (ram_addr_b[3] ? (BE_B[0] ? 9'h000 : 9'h1ff) : 9'h1ff); + {wmsk_b[16], wmsk_b[7:0]} = (ram_addr_b[3] ? 9'h1ff : (BE_B[0] ? 9'h000 : 9'h1ff)); + end + MODE_4: begin + aligned_wdata_b = {2'b00, {4 {WDATA_B[3:0]}}}; + wmsk_b[17:16] = 2'b11; + wmsk_b[15:12] = (ram_addr_b[3:2] == 2'b11 ? 4'h0 : 4'hf); + wmsk_b[11:8] = (ram_addr_b[3:2] == 2'b10 ? 4'h0 : 4'hf); + wmsk_b[7:4] = (ram_addr_b[3:2] == 2'b01 ? 4'h0 : 4'hf); + wmsk_b[3:0] = (ram_addr_b[3:2] == 2'b00 ? 4'h0 : 4'hf); + end + MODE_2: begin + aligned_wdata_b = {2'b00, {8 {WDATA_B[1:0]}}}; + wmsk_b[17:16] = 2'b11; + wmsk_b[15:14] = (ram_addr_b[3:1] == 3'b111 ? 2'h0 : 2'h3); + wmsk_b[13:12] = (ram_addr_b[3:1] == 3'b110 ? 2'h0 : 2'h3); + wmsk_b[11:10] = (ram_addr_b[3:1] == 3'b101 ? 2'h0 : 2'h3); + wmsk_b[9:8] = (ram_addr_b[3:1] == 3'b100 ? 2'h0 : 2'h3); + wmsk_b[7:6] = (ram_addr_b[3:1] == 3'b011 ? 2'h0 : 2'h3); + wmsk_b[5:4] = (ram_addr_b[3:1] == 3'b010 ? 2'h0 : 2'h3); + wmsk_b[3:2] = (ram_addr_b[3:1] == 3'b001 ? 2'h0 : 2'h3); + wmsk_b[1:0] = (ram_addr_b[3:1] == 3'b000 ? 2'h0 : 2'h3); + end + MODE_1: begin + aligned_wdata_b = {2'b00, {16 {WDATA_B[0]}}}; + wmsk_b = 18'h3fffe; + wmsk_b[ram_addr_b[3:0]] = 0; + end + endcase + else begin + aligned_wdata_b = 18'b000000000000000000; + wmsk_b = 18'h3ffff; + end + end + always @(*) begin : RDATA_A_MODE_SEL + case (RMODE_A) + default: RDATA_A = 18'h00000; + MODE_18: RDATA_A = ram_rdata_a; + MODE_9: begin + RDATA_A[17:9] = 9'h000; + RDATA_A[8:0] = (ram_addr_a[3] ? {ram_rdata_a[17], ram_rdata_a[15:8]} : {ram_rdata_a[16], ram_rdata_a[7:0]}); + end + MODE_4: begin + RDATA_A[17:4] = 14'h0000; + case (ram_addr_a[3:2]) + 3: RDATA_A[3:0] = ram_rdata_a[15:12]; + 2: RDATA_A[3:0] = ram_rdata_a[11:8]; + 1: RDATA_A[3:0] = ram_rdata_a[7:4]; + 0: RDATA_A[3:0] = ram_rdata_a[3:0]; + endcase + end + MODE_2: begin + RDATA_A[17:2] = 16'h0000; + case (ram_addr_a[3:1]) + 7: RDATA_A[1:0] = ram_rdata_a[15:14]; + 6: RDATA_A[1:0] = ram_rdata_a[13:12]; + 5: RDATA_A[1:0] = ram_rdata_a[11:10]; + 4: RDATA_A[1:0] = ram_rdata_a[9:8]; + 3: RDATA_A[1:0] = ram_rdata_a[7:6]; + 2: RDATA_A[1:0] = ram_rdata_a[5:4]; + 1: RDATA_A[1:0] = ram_rdata_a[3:2]; + 0: RDATA_A[1:0] = ram_rdata_a[1:0]; + endcase + end + MODE_1: begin + RDATA_A[17:1] = 17'h00000; + RDATA_A[0] = ram_rdata_a[ram_addr_a[3:0]]; + end + endcase + end + always @(*) + case (RMODE_B) + default: RDATA_B = 18'h15566; + MODE_18: RDATA_B = ram_rdata_b; + MODE_9: begin + RDATA_B[17:9] = 1'sb1; + RDATA_B[8] = (ram_addr_b[3] ? ram_rdata_b[17] : ram_rdata_b[16]); + RDATA_B[7:0] = (ram_addr_b[3] ? ram_rdata_b[15:8] : ram_rdata_b[7:0]); + end + MODE_4: + case (ram_addr_b[3:2]) + 3: RDATA_B[3:0] = ram_rdata_b[15:12]; + 2: RDATA_B[3:0] = ram_rdata_b[11:8]; + 1: RDATA_B[3:0] = ram_rdata_b[7:4]; + 0: RDATA_B[3:0] = ram_rdata_b[3:0]; + endcase + MODE_2: + case (ram_addr_b[3:1]) + 7: RDATA_B[1:0] = ram_rdata_b[15:14]; + 6: RDATA_B[1:0] = ram_rdata_b[13:12]; + 5: RDATA_B[1:0] = ram_rdata_b[11:10]; + 4: RDATA_B[1:0] = ram_rdata_b[9:8]; + 3: RDATA_B[1:0] = ram_rdata_b[7:6]; + 2: RDATA_B[1:0] = ram_rdata_b[5:4]; + 1: RDATA_B[1:0] = ram_rdata_b[3:2]; + 0: RDATA_B[1:0] = ram_rdata_b[1:0]; + endcase + MODE_1: RDATA_B[0] = ram_rdata_b[ram_addr_b[3:0]]; + endcase +endmodule
diff --git a/ql-qlf-plugin/qlf_k6n10f/cells_sim.v b/ql-qlf-plugin/qlf_k6n10f/cells_sim.v index 6270f49..9ea74c4 100644 --- a/ql-qlf-plugin/qlf_k6n10f/cells_sim.v +++ b/ql-qlf-plugin/qlf_k6n10f/cells_sim.v
@@ -488,180 +488,594 @@ endmodule module TDP_BRAM36 ( - (* clkbuf_sink *) - input CLOCKA, - (* clkbuf_sink *) - input CLOCKB, - input READENABLEA, - input READENABLEB, - input [14:0] ADDRA, - input [14:0] ADDRB, - input [31:0] WRITEDATAA, - input [31:0] WRITEDATAB, - input [3:0] WRITEDATAAP, - input [3:0] WRITEDATABP, - input WRITEENABLEA, - input WRITEENABLEB, - input [3:0] BYTEENABLEA, - input [3:0] BYTEENABLEB, - //input [2:0] WRITEDATAWIDTHA, - //input [2:0] WRITEDATAWIDTHB, - //input [2:0] READDATAWIDTHA, - //input [2:0] READDATAWIDTHB, - output [31:0] READDATAA, - output [31:0] READDATAB, - output [3:0] READDATAAP, - output [3:0] READDATABP + WEN_A1, + WEN_B1, + REN_A1, + REN_B1, + CLK_A1, + CLK_B1, + BE_A1, + BE_B1, + ADDR_A1, + ADDR_B1, + WDATA_A1, + WDATA_B1, + RDATA_A1, + RDATA_B1, + FLUSH1, + SYNC_FIFO1, + RMODE_A1, + RMODE_B1, + WMODE_A1, + WMODE_B1, + FMODE1, + POWERDN1, + SLEEP1, + PROTECT1, + UPAE1, + UPAF1, + WEN_A2, + WEN_B2, + REN_A2, + REN_B2, + CLK_A2, + CLK_B2, + BE_A2, + BE_B2, + ADDR_A2, + ADDR_B2, + WDATA_A2, + WDATA_B2, + RDATA_A2, + RDATA_B2, + FLUSH2, + SYNC_FIFO2, + RMODE_A2, + RMODE_B2, + WMODE_A2, + WMODE_B2, + FMODE2, + POWERDN2, + SLEEP2, + PROTECT2, + UPAE2, + UPAF2, + SPLIT, + RAM_ID_i, + PL_INIT_i, + PL_ENA_i, + PL_REN_i, + PL_CLK_i, + PL_WEN_i, + PL_ADDR_i, + PL_DATA_i, + PL_INIT_o, + PL_ENA_o, + PL_REN_o, + PL_CLK_o, + PL_WEN_o, + PL_ADDR_o, + PL_DATA_o ); - parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INITP_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_40 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_41 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_42 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_43 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_44 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_45 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_46 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_47 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_48 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_49 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_4F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_50 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_51 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_52 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_53 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_54 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_55 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_56 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_57 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_58 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_59 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_5F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_60 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_61 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_62 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_63 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_64 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_65 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_66 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_67 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_68 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_69 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_6F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_70 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_71 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_72 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_73 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_74 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_75 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_76 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_77 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_78 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_79 = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7A = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7B = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7C = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7D = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7E = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter INIT_7F = 256'h0000000000000000000000000000000000000000000000000000000000000000; - parameter integer READ_WIDTH_A = 0; - parameter integer READ_WIDTH_B = 0; - parameter integer WRITE_WIDTH_A = 0; - parameter integer WRITE_WIDTH_B = 0; - + input wire WEN_A1; + input wire WEN_B1; + input wire REN_A1; + input wire REN_B1; + input wire CLK_A1; + input wire CLK_B1; + input wire [1:0] BE_A1; + input wire [1:0] BE_B1; + input wire [14:0] ADDR_A1; + input wire [14:0] ADDR_B1; + input wire [17:0] WDATA_A1; + input wire [17:0] WDATA_B1; + output reg [17:0] RDATA_A1; + output reg [17:0] RDATA_B1; + input wire FLUSH1; + input wire SYNC_FIFO1; + input wire [2:0] RMODE_A1; + input wire [2:0] RMODE_B1; + input wire [2:0] WMODE_A1; + input wire [2:0] WMODE_B1; + input wire FMODE1; + input wire POWERDN1; + input wire SLEEP1; + input wire PROTECT1; + input wire [10:0] UPAE1; + input wire [10:0] UPAF1; + input wire WEN_A2; + input wire WEN_B2; + input wire REN_A2; + input wire REN_B2; + input wire CLK_A2; + input wire CLK_B2; + input wire [1:0] BE_A2; + input wire [1:0] BE_B2; + input wire [13:0] ADDR_A2; + input wire [13:0] ADDR_B2; + input wire [17:0] WDATA_A2; + input wire [17:0] WDATA_B2; + output reg [17:0] RDATA_A2; + output reg [17:0] RDATA_B2; + input wire FLUSH2; + input wire SYNC_FIFO2; + input wire [2:0] RMODE_A2; + input wire [2:0] RMODE_B2; + input wire [2:0] WMODE_A2; + input wire [2:0] WMODE_B2; + input wire FMODE2; + input wire POWERDN2; + input wire SLEEP2; + input wire PROTECT2; + input wire [10:0] UPAE2; + input wire [10:0] UPAF2; + input SPLIT; + input [8:0] RAM_ID_i; + input wire PL_INIT_i; + input wire PL_ENA_i; + input wire PL_REN_i; + input wire PL_CLK_i; + input wire [1:0] PL_WEN_i; + input wire [23:0] PL_ADDR_i; + input wire [35:0] PL_DATA_i; + output reg PL_INIT_o; + output reg PL_ENA_o; + output reg PL_REN_o; + output reg PL_CLK_o; + output reg [1:0] PL_WEN_o; + output reg [23:0] PL_ADDR_o; + output wire [35:0] PL_DATA_o; + wire EMPTY2; + wire EPO2; + wire EWM2; + wire FULL2; + wire FMO2; + wire FWM2; + wire EMPTY1; + wire EPO1; + wire EWM1; + wire FULL1; + wire FMO1; + wire FWM1; + wire UNDERRUN1; + wire OVERRUN1; + wire UNDERRUN2; + wire OVERRUN2; + wire UNDERRUN3; + wire OVERRUN3; + wire EMPTY3; + wire EPO3; + wire EWM3; + wire FULL3; + wire FMO3; + wire FWM3; + wire ram_fmode1; + wire ram_fmode2; + wire [17:0] ram_rdata_a1; + wire [17:0] ram_rdata_b1; + wire [17:0] ram_rdata_a2; + wire [17:0] ram_rdata_b2; + reg [17:0] ram_wdata_a1; + reg [17:0] ram_wdata_b1; + reg [17:0] ram_wdata_a2; + reg [17:0] ram_wdata_b2; + reg [14:0] laddr_a1; + reg [14:0] laddr_b1; + wire [13:0] ram_addr_a1; + wire [13:0] ram_addr_b1; + wire [13:0] ram_addr_a2; + wire [13:0] ram_addr_b2; + wire smux_clk_a1; + wire smux_clk_b1; + wire smux_clk_a2; + wire smux_clk_b2; + reg [1:0] ram_be_a1; + reg [1:0] ram_be_a2; + reg [1:0] ram_be_b1; + reg [1:0] ram_be_b2; + reg [2:0] ram_rmode_a1; + reg [2:0] ram_wmode_a1; + reg [2:0] ram_rmode_b1; + reg [2:0] ram_wmode_b1; + reg [2:0] ram_rmode_a2; + reg [2:0] ram_wmode_a2; + reg [2:0] ram_rmode_b2; + reg [2:0] ram_wmode_b2; + wire ram_ren_a1; + wire ram_ren_b1; + wire ram_ren_a2; + wire ram_ren_b2; + wire ram_wen_a1; + wire ram_wen_b1; + wire ram_wen_a2; + wire ram_wen_b2; + wire ren_o; + wire [11:0] ff_raddr; + wire [11:0] ff_waddr; + reg [35:0] fifo_rdata; + reg [1:0] fifo_rmode; + reg [1:0] fifo_wmode; + wire [1:0] bwl; + assign ram_fmode1 = FMODE1 & SPLIT; + assign ram_fmode2 = FMODE2 & SPLIT; + assign smux_clk_a1 = CLK_A1; + assign smux_clk_b1 = (FMODE1 ? (SYNC_FIFO1 ? CLK_A1 : CLK_B1) : CLK_B1); + assign smux_clk_a2 = (SPLIT ? CLK_A2 : CLK_A1); + assign smux_clk_b2 = (SPLIT ? CLK_B2 : (FMODE1 ? (SYNC_FIFO1 ? CLK_A1 : CLK_B1) : CLK_B1)); + assign ram_ren_a1 = (SPLIT ? REN_A1 : (FMODE1 ? 0 : REN_A1)); + assign ram_ren_a2 = (SPLIT ? REN_A2 : (FMODE1 ? 0 : REN_A1)); + assign ram_ren_b1 = (SPLIT ? REN_B1 : (FMODE1 ? ren_o : REN_B1)); + assign ram_ren_b2 = (SPLIT ? REN_B2 : (FMODE1 ? ren_o : REN_B1)); + assign ram_wen_a1 = (SPLIT ? WEN_A1 : (FMODE1 ? ~FULL3 & WEN_A1 : WEN_A1 & ~ADDR_A1[4])); + assign ram_wen_a2 = (SPLIT ? WEN_A2 : (FMODE1 ? ~FULL3 & WEN_A1 : WEN_A1 & ADDR_A1[4])); + localparam MODE_36 = 3'b111; + assign ram_wen_b1 = (SPLIT ? WEN_B1 : (WMODE_B1 == MODE_36 ? WEN_B1 : WEN_B1 & ~ADDR_B1[4])); + assign ram_wen_b2 = (SPLIT ? WEN_B2 : (WMODE_B1 == MODE_36 ? WEN_B1 : WEN_B1 & ADDR_B1[4])); + assign ram_addr_a1 = (SPLIT ? ADDR_A1[13:0] : (FMODE1 ? {ff_waddr[11:2], ff_waddr[0], 3'b000} : {ADDR_A1[14:5], ADDR_A1[3:0]})); + assign ram_addr_b1 = (SPLIT ? ADDR_B1[13:0] : (FMODE1 ? {ff_raddr[11:2], ff_raddr[0], 3'b000} : {ADDR_B1[14:5], ADDR_B1[3:0]})); + assign ram_addr_a2 = (SPLIT ? ADDR_A2[13:0] : (FMODE1 ? {ff_waddr[11:2], ff_waddr[0], 3'b000} : {ADDR_A1[14:5], ADDR_A1[3:0]})); + assign ram_addr_b2 = (SPLIT ? ADDR_B2[13:0] : (FMODE1 ? {ff_raddr[11:2], ff_raddr[0], 3'b000} : {ADDR_B1[14:5], ADDR_B1[3:0]})); + assign bwl = (SPLIT ? ADDR_A1[4:3] : (FMODE1 ? ff_waddr[1:0] : ADDR_A1[4:3])); + localparam MODE_18 = 3'b110; + localparam MODE_9 = 3'b101; + always @(*) begin : WDATA_SEL + case (SPLIT) + 1: begin + ram_wdata_a1 = WDATA_A1; + ram_wdata_a2 = WDATA_A2; + ram_wdata_b1 = WDATA_B1; + ram_wdata_b2 = WDATA_B2; + ram_be_a2 = BE_A2; + ram_be_b2 = BE_B2; + ram_be_a1 = BE_A1; + ram_be_b1 = BE_B1; + end + 0: begin + case (WMODE_A1) + MODE_36: begin + ram_wdata_a1 = {WDATA_A2[15:14], WDATA_A1[15:0]}; + ram_wdata_a2 = {WDATA_A2[17:16], WDATA_A2[13:0], WDATA_A1[17:16]}; + ram_be_a2 = (FMODE1 ? 2'b11 : BE_A2); + ram_be_a1 = (FMODE1 ? 2'b11 : BE_A1); + end + MODE_18: begin + ram_wdata_a1 = WDATA_A1; + ram_wdata_a2 = WDATA_A1; + ram_be_a1 = (FMODE1 ? (ff_waddr[1] ? 2'b00 : 2'b11) : BE_A1); + ram_be_a2 = (FMODE1 ? (ff_waddr[1] ? 2'b11 : 2'b00) : BE_A1); + end + MODE_9: + case (bwl) + 0: begin + {ram_wdata_a1[16], ram_wdata_a1[7:0]} = WDATA_A1[8:0]; + {ram_wdata_a1[17], ram_wdata_a1[15:8]} = 9'b000000000; + {ram_wdata_a2[16], ram_wdata_a2[7:0]} = 9'b000000000; + {ram_wdata_a2[17], ram_wdata_a2[15:8]} = 9'b000000000; + ram_be_a1[0] = (FMODE1 ? (ff_waddr[1:0] == 0 ? 1'b1 : 1'b0) : 1'b1); + ram_be_a1[1] = (FMODE1 ? (ff_waddr[1:0] == 1 ? 1'b1 : 1'b0) : 1'b0); + ram_be_a2[0] = (FMODE1 ? (ff_waddr[1:0] == 2 ? 1'b1 : 1'b0) : 1'b0); + ram_be_a2[1] = (FMODE1 ? (ff_waddr[1:0] == 3 ? 1'b1 : 1'b0) : 1'b0); + end + 1: begin + {ram_wdata_a1[16], ram_wdata_a1[7:0]} = 9'b000000000; + {ram_wdata_a1[17], ram_wdata_a1[15:8]} = {WDATA_A1[8:0]}; + {ram_wdata_a2[16], ram_wdata_a2[7:0]} = 9'b000000000; + {ram_wdata_a2[17], ram_wdata_a2[15:8]} = 9'b000000000; + {ram_be_a2, ram_be_a1} = 4'b0010; + end + 2: begin + {ram_wdata_a1[16], ram_wdata_a1[7:0]} = 9'b000000000; + {ram_wdata_a1[17], ram_wdata_a1[15:8]} = 9'b000000000; + {ram_wdata_a2[16], ram_wdata_a2[7:0]} = {WDATA_A1[8:0]}; + {ram_wdata_a2[17], ram_wdata_a2[15:8]} = 9'b000000000; + {ram_be_a2, ram_be_a1} = 4'b0100; + end + 3: begin + {ram_wdata_a1[16], ram_wdata_a1[7:0]} = 9'b000000000; + {ram_wdata_a1[17], ram_wdata_a1[15:8]} = 9'b000000000; + {ram_wdata_a2[16], ram_wdata_a2[7:0]} = 9'b000000000; + {ram_wdata_a2[17], ram_wdata_a2[15:8]} = {WDATA_A1[8:0]}; + {ram_be_a2, ram_be_a1} = 4'b1000; + end + endcase + endcase + case (WMODE_B1) + MODE_36: begin + ram_wdata_b1 = (FMODE1 ? 18'b000000000000000000 : {WDATA_B2[15:14], WDATA_B1[15:0]}); + ram_wdata_b2 = (FMODE1 ? 18'b000000000000000000 : {WDATA_B2[17:16], WDATA_B2[13:0], WDATA_B1[17:16]}); + ram_be_b2 = BE_B2; + ram_be_b1 = BE_B1; + end + MODE_18: begin + ram_wdata_b1 = (FMODE1 ? 18'b000000000000000000 : WDATA_B1); + ram_wdata_b2 = (FMODE1 ? 18'b000000000000000000 : WDATA_B1); + ram_be_b1 = BE_B1; + ram_be_b2 = BE_B1; + end + MODE_9: + case (ram_addr_b1[4:3]) + 0: begin + {ram_wdata_b1[16], ram_wdata_b1[7:0]} = {ram_wdata_b1[16], ram_wdata_b1[7:0]}; + {ram_wdata_b1[17], ram_wdata_b1[15:8]} = 9'b000000000; + {ram_wdata_b2[16], ram_wdata_b2[7:0]} = 9'b000000000; + {ram_wdata_b2[17], ram_wdata_b2[15:8]} = 9'b000000000; + {ram_be_b2, ram_be_b1} = 4'b0001; + end + 1: begin + {ram_wdata_b1[16], ram_wdata_b1[7:0]} = 9'b000000000; + {ram_wdata_b1[17], ram_wdata_b1[15:8]} = {ram_wdata_b1[16], ram_wdata_b1[7:0]}; + {ram_wdata_b2[16], ram_wdata_b2[7:0]} = 9'b000000000; + {ram_wdata_b2[17], ram_wdata_b2[15:8]} = 9'b000000000; + {ram_be_b2, ram_be_b1} = 4'b0010; + end + 2: begin + {ram_wdata_b1[16], ram_wdata_b1[7:0]} = 9'b000000000; + {ram_wdata_b1[17], ram_wdata_b1[15:8]} = 9'b000000000; + {ram_wdata_b2[16], ram_wdata_b2[7:0]} = {ram_wdata_b1[16], ram_wdata_b1[7:0]}; + {ram_wdata_b2[17], ram_wdata_b2[15:8]} = 9'b000000000; + {ram_be_b2, ram_be_b1} = 4'b0100; + end + 3: begin + {ram_wdata_b1[16], ram_wdata_b1[7:0]} = 9'b000000000; + {ram_wdata_b1[17], ram_wdata_b1[15:8]} = 9'b000000000; + {ram_wdata_b2[16], ram_wdata_b2[7:0]} = 9'b000000000; + {ram_wdata_b2[17], ram_wdata_b2[15:8]} = {ram_wdata_b1[16], ram_wdata_b1[7:0]}; + {ram_be_b2, ram_be_b1} = 4'b1000; + end + endcase + endcase + end + endcase + end + always @(*) + case (SPLIT) + 0: begin + ram_rmode_a1 = (RMODE_A1 == MODE_36 ? MODE_18 : RMODE_A1); + ram_rmode_a2 = (RMODE_A1 == MODE_36 ? MODE_18 : RMODE_A1); + ram_wmode_a1 = (WMODE_A1 == MODE_36 ? MODE_18 : (FMODE1 ? MODE_18 : WMODE_A1)); + ram_wmode_a2 = (WMODE_A1 == MODE_36 ? MODE_18 : (FMODE1 ? MODE_18 : WMODE_A1)); + ram_rmode_b1 = (RMODE_B1 == MODE_36 ? MODE_18 : (FMODE1 ? MODE_18 : RMODE_B1)); + ram_rmode_b2 = (RMODE_B1 == MODE_36 ? MODE_18 : (FMODE1 ? MODE_18 : RMODE_B1)); + ram_wmode_b1 = (WMODE_B1 == MODE_36 ? MODE_18 : WMODE_B1); + ram_wmode_b2 = (WMODE_B1 == MODE_36 ? MODE_18 : RMODE_B1); + end + 1: begin + ram_rmode_a1 = (RMODE_A1 == MODE_36 ? MODE_18 : RMODE_A1); + ram_rmode_a2 = (RMODE_A2 == MODE_36 ? MODE_18 : RMODE_A2); + ram_wmode_a1 = (WMODE_A1 == MODE_36 ? MODE_18 : WMODE_A1); + ram_wmode_a2 = (WMODE_A2 == MODE_36 ? MODE_18 : WMODE_A2); + ram_rmode_b1 = (RMODE_B1 == MODE_36 ? MODE_18 : RMODE_B1); + ram_rmode_b2 = (RMODE_B2 == MODE_36 ? MODE_18 : RMODE_B2); + ram_wmode_b1 = (WMODE_B1 == MODE_36 ? MODE_18 : WMODE_B1); + ram_wmode_b2 = (WMODE_B2 == MODE_36 ? MODE_18 : WMODE_B2); + end + endcase + always @(*) begin : FIFO_READ_SEL + case (RMODE_B1) + MODE_36: fifo_rdata = {ram_rdata_b2[17:16], ram_rdata_b1[17:16], ram_rdata_b2[15:0], ram_rdata_b1[15:0]}; + MODE_18: fifo_rdata = (ff_raddr[1] ? {18'b000000000000000000, ram_rdata_b2} : {18'b000000000000000000, ram_rdata_b1}); + MODE_9: + case (ff_raddr[1:0]) + 0: fifo_rdata = {27'b000000000000000000000000000, ram_rdata_b1[16], ram_rdata_b1[7:0]}; + 1: fifo_rdata = {27'b000000000000000000000000000, ram_rdata_b1[17], ram_rdata_b1[15:8]}; + 2: fifo_rdata = {27'b000000000000000000000000000, ram_rdata_b2[16], ram_rdata_b2[7:0]}; + 3: fifo_rdata = {27'b000000000000000000000000000, ram_rdata_b2[17], ram_rdata_b2[15:8]}; + endcase + endcase + end + localparam MODE_1 = 3'b001; + localparam MODE_2 = 3'b010; + localparam MODE_4 = 3'b100; + always @(*) begin : RDATA_SEL + case (SPLIT) + 1: begin + RDATA_A1 = (FMODE1 ? {10'b0000000000, EMPTY1, EPO1, EWM1, UNDERRUN1, FULL1, FMO1, FWM1, OVERRUN1} : ram_rdata_a1); + RDATA_B1 = ram_rdata_b1; + RDATA_A2 = (FMODE2 ? {10'b0000000000, EMPTY2, EPO2, EWM2, UNDERRUN2, FULL2, FMO2, FWM2, OVERRUN2} : ram_rdata_a2); + RDATA_B2 = ram_rdata_b2; + end + 0: begin + if (FMODE1) begin + RDATA_A1 = {10'b0000000000, EMPTY3, EPO3, EWM3, UNDERRUN3, FULL3, FMO3, FWM3, OVERRUN3}; + RDATA_A2 = 18'b000000000000000000; + end + else + case (RMODE_A1) + MODE_36: begin + RDATA_A1 = {ram_rdata_a2[1:0], ram_rdata_a1[15:0]}; + RDATA_A2 = {ram_rdata_a2[17:16], ram_rdata_a1[17:16], ram_rdata_a2[15:2]}; + end + MODE_18: begin + RDATA_A1 = (laddr_a1[4] ? ram_rdata_a2 : ram_rdata_a1); + RDATA_A2 = 18'b000000000000000000; + end + MODE_9: begin + RDATA_A1 = (laddr_a1[4] ? {9'b000000000, ram_rdata_a2[8:0]} : {9'b000000000, ram_rdata_a1[8:0]}); + RDATA_A2 = 18'b000000000000000000; + end + MODE_4: begin + RDATA_A2 = 18'b000000000000000000; + RDATA_A1[17:4] = 14'b00000000000000; + RDATA_A1[3:0] = (laddr_a1[4] ? ram_rdata_a2[3:0] : ram_rdata_a1[3:0]); + end + MODE_2: begin + RDATA_A2 = 18'b000000000000000000; + RDATA_A1[17:2] = 16'b0000000000000000; + RDATA_A1[1:0] = (laddr_a1[4] ? ram_rdata_a2[1:0] : ram_rdata_a1[1:0]); + end + MODE_1: begin + RDATA_A2 = 18'b000000000000000000; + RDATA_A1[17:1] = 17'b00000000000000000; + RDATA_A1[0] = (laddr_a1[4] ? ram_rdata_a2[0] : ram_rdata_a1[0]); + end + endcase + case (RMODE_B1) + MODE_36: begin + RDATA_B1 = {ram_rdata_b2[1:0], ram_rdata_b1[15:0]}; + RDATA_B2 = {ram_rdata_b2[17:16], ram_rdata_b1[17:16], ram_rdata_b2[15:2]}; + end + MODE_18: begin + RDATA_B1 = (FMODE1 ? fifo_rdata[17:0] : (laddr_b1[4] ? ram_rdata_b2 : ram_rdata_b1)); + RDATA_B2 = 18'b000000000000000000; + end + MODE_9: begin + RDATA_B1 = (FMODE1 ? {9'b000000000, fifo_rdata[8:0]} : (laddr_b1[4] ? {9'b000000000, ram_rdata_b2[8:0]} : {9'b000000000, ram_rdata_b1[8:0]})); + RDATA_B2 = 18'b000000000000000000; + end + MODE_4: begin + RDATA_B2 = 18'b000000000000000000; + RDATA_B1[17:4] = 14'b00000000000000; + RDATA_B1[3:0] = (laddr_b1[4] ? ram_rdata_b2[3:0] : ram_rdata_b1[3:0]); + end + MODE_2: begin + RDATA_B2 = 18'b000000000000000000; + RDATA_B1[17:2] = 16'b0000000000000000; + RDATA_B1[1:0] = (laddr_b1[4] ? ram_rdata_b2[1:0] : ram_rdata_b1[1:0]); + end + MODE_1: begin + RDATA_B2 = 18'b000000000000000000; + RDATA_B1[17:1] = 17'b00000000000000000; + RDATA_B1[0] = (laddr_b1[4] ? ram_rdata_b2[0] : ram_rdata_b1[0]); + end + endcase + end + endcase + end + always @(posedge CLK_A1) laddr_a1 <= ADDR_A1; + always @(posedge CLK_B1) laddr_b1 <= ADDR_B1; + always @(*) begin + case (WMODE_A1) + default: fifo_wmode = 2'b00; + MODE_36: fifo_wmode = 2'b00; + MODE_18: fifo_wmode = 2'b01; + MODE_9: fifo_wmode = 2'b10; + endcase + case (RMODE_B1) + default: fifo_rmode = 2'b00; + MODE_36: fifo_rmode = 2'b00; + MODE_18: fifo_rmode = 2'b01; + MODE_9: fifo_rmode = 2'b10; + endcase + end + fifo_ctl #( + .ADDR_WIDTH(12), + .FIFO_WIDTH(3'd4) + ) fifo36_ctl( + .rclk(smux_clk_b1), + .rst_R_n(~FLUSH1), + .wclk(smux_clk_a1), + .rst_W_n(~FLUSH1), + .ren(REN_B1), + .wen(ram_wen_a1), + .sync(SYNC_FIFO1), + .depth(3'b111), + .rmode(fifo_rmode), + .wmode(fifo_wmode), + .ren_o(ren_o), + .fflags({FULL3, FMO3, FWM3, OVERRUN3, EMPTY3, EPO3, EWM3, UNDERRUN3}), + .raddr(ff_raddr), + .waddr(ff_waddr), + .upaf({1'b0, UPAF1}), + .upae({1'b0, UPAE1}) + ); + TDP18Kx18_FIFO u1( + .RMODE_A(ram_rmode_a1), + .RMODE_B(ram_rmode_b1), + .WMODE_A(ram_wmode_a1), + .WMODE_B(ram_wmode_b1), + .WEN_A(ram_wen_a1), + .WEN_B(ram_wen_b1), + .REN_A(ram_ren_a1), + .REN_B(ram_ren_b1), + .CLK_A(smux_clk_a1), + .CLK_B(smux_clk_b1), + .BE_A(ram_be_a1), + .BE_B(ram_be_b1), + .ADDR_A(ram_addr_a1), + .ADDR_B(ram_addr_b1), + .WDATA_A(ram_wdata_a1), + .WDATA_B(ram_wdata_b1), + .RDATA_A(ram_rdata_a1), + .RDATA_B(ram_rdata_b1), + .EMPTY(EMPTY1), + .EPO(EPO1), + .EWM(EWM1), + .UNDERRUN(UNDERRUN1), + .FULL(FULL1), + .FMO(FMO1), + .FWM(FWM1), + .OVERRUN(OVERRUN1), + .FLUSH(FLUSH1), + .FMODE(ram_fmode1), + .UPAF(UPAF1), + .UPAE(UPAE1), + .SYNC_FIFO(SYNC_FIFO1), + .POWERDN(POWERDN1), + .SLEEP(SLEEP1), + .PROTECT(PROTECT1), + .PL_INIT(PL_INIT_i), + .PL_ENA(PL_ENA_i), + .PL_WEN(PL_WEN_i[0]), + .PL_REN(PL_REN_i), + .PL_CLK(PL_CLK_i), + .PL_ADDR(PL_ADDR_i), + .PL_DATA_IN({PL_DATA_i[33:32], PL_DATA_i[15:0]}), + .PL_DATA_OUT({PL_DATA_o[33:32], PL_DATA_o[15:0]}), + .RAM_ID({RAM_ID_i}) + ); + TDP18Kx18_FIFO u2( + .RMODE_A(ram_rmode_a2), + .RMODE_B(ram_rmode_b2), + .WMODE_A(ram_wmode_a2), + .WMODE_B(ram_wmode_b2), + .WEN_A(ram_wen_a2), + .WEN_B(ram_wen_b2), + .REN_A(ram_ren_a2), + .REN_B(ram_ren_b2), + .CLK_A(smux_clk_a2), + .CLK_B(smux_clk_b2), + .BE_A(ram_be_a2), + .BE_B(ram_be_b2), + .ADDR_A(ram_addr_a2), + .ADDR_B(ram_addr_b2), + .WDATA_A(ram_wdata_a2), + .WDATA_B(ram_wdata_b2), + .RDATA_A(ram_rdata_a2), + .RDATA_B(ram_rdata_b2), + .EMPTY(EMPTY2), + .EPO(EPO2), + .EWM(EWM2), + .UNDERRUN(UNDERRUN2), + .FULL(FULL2), + .FMO(FMO2), + .FWM(FWM2), + .OVERRUN(OVERRUN2), + .FLUSH(FLUSH2), + .FMODE(ram_fmode2), + .UPAF(UPAF2), + .UPAE(UPAE2), + .SYNC_FIFO(SYNC_FIFO2), + .POWERDN(POWERDN2), + .SLEEP(SLEEP2), + .PROTECT(PROTECT2), + .PL_INIT(PL_INIT_i), + .PL_ENA(PL_ENA_i), + .PL_WEN(PL_WEN_i[1]), + .PL_REN(PL_REN_i), + .PL_CLK(PL_CLK_i), + .PL_ADDR(PL_ADDR_i), + .PL_DATA_IN({PL_DATA_i[35:34], PL_DATA_i[31:16]}), + .PL_DATA_OUT({PL_DATA_o[35:34], PL_DATA_o[31:16]}), + .RAM_ID(RAM_ID_i) + ); + always @(*) begin + PL_ADDR_o = PL_ADDR_i; + PL_INIT_o = PL_INIT_i; + PL_ENA_o = PL_ENA_i; + PL_WEN_o = PL_WEN_i; + PL_REN_o = PL_REN_i; + PL_CLK_o = PL_CLK_i; + end endmodule (* blackbox *)
diff --git a/ql-qlf-plugin/qlf_k6n10f/sram1024x18.v b/ql-qlf-plugin/qlf_k6n10f/sram1024x18.v new file mode 100644 index 0000000..79e5ae7 --- /dev/null +++ b/ql-qlf-plugin/qlf_k6n10f/sram1024x18.v
@@ -0,0 +1,122 @@ +// Copyright (C) 2020-2021 The SymbiFlow Authors. +// +// Use of this source code is governed by a ISC-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/ISC +// +// SPDX-License-Identifier:ISC + +module sram1024x18 ( + clk_a, + cen_a, + wen_a, + addr_a, + wmsk_a, + wdata_a, + rdata_a, + clk_b, + cen_b, + wen_b, + addr_b, + wmsk_b, + wdata_b, + rdata_b +); + input wire clk_a; + input wire cen_a; + input wire wen_a; + input wire [9:0] addr_a; + input wire [17:0] wmsk_a; + input wire [17:0] wdata_a; + output reg [17:0] rdata_a; + input wire clk_b; + input wire cen_b; + input wire wen_b; + input wire [9:0] addr_b; + input wire [17:0] wmsk_b; + input wire [17:0] wdata_b; + output reg [17:0] rdata_b; + reg [17:0] ram [1023:0]; + reg [9:0] laddr_a; + reg [9:0] laddr_b; + reg lcen_a; + reg lwen_a; + reg [17:0] lwdata_a; + reg lcen_b; + reg lwen_b; + reg [17:0] lwdata_b; + reg [17:0] lwmsk_a; + reg [17:0] lwmsk_b; + always @(posedge clk_a) begin + laddr_a <= addr_a; + lwdata_a <= wdata_a; + lwmsk_a <= wmsk_a; + lcen_a <= cen_a; + lwen_a <= wen_a; + end + always @(posedge clk_b) begin + laddr_b <= addr_b; + lwdata_b <= wdata_b; + lwmsk_b <= wmsk_b; + lcen_b <= cen_b; + lwen_b <= wen_b; + end + always @(*) begin + if ((lwen_b == 0) && (lcen_b == 0)) begin + ram[laddr_b][0] = (lwmsk_b[0] ? ram[laddr_b][0] : lwdata_b[0]); + ram[laddr_b][1] = (lwmsk_b[1] ? ram[laddr_b][1] : lwdata_b[1]); + ram[laddr_b][2] = (lwmsk_b[2] ? ram[laddr_b][2] : lwdata_b[2]); + ram[laddr_b][3] = (lwmsk_b[3] ? ram[laddr_b][3] : lwdata_b[3]); + ram[laddr_b][4] = (lwmsk_b[4] ? ram[laddr_b][4] : lwdata_b[4]); + ram[laddr_b][5] = (lwmsk_b[5] ? ram[laddr_b][5] : lwdata_b[5]); + ram[laddr_b][6] = (lwmsk_b[6] ? ram[laddr_b][6] : lwdata_b[6]); + ram[laddr_b][7] = (lwmsk_b[7] ? ram[laddr_b][7] : lwdata_b[7]); + ram[laddr_b][8] = (lwmsk_b[8] ? ram[laddr_b][8] : lwdata_b[8]); + ram[laddr_b][9] = (lwmsk_b[9] ? ram[laddr_b][9] : lwdata_b[9]); + ram[laddr_b][10] = (lwmsk_b[10] ? ram[laddr_b][10] : lwdata_b[10]); + ram[laddr_b][11] = (lwmsk_b[11] ? ram[laddr_b][11] : lwdata_b[11]); + ram[laddr_b][12] = (lwmsk_b[12] ? ram[laddr_b][12] : lwdata_b[12]); + ram[laddr_b][13] = (lwmsk_b[13] ? ram[laddr_b][13] : lwdata_b[13]); + ram[laddr_b][14] = (lwmsk_b[14] ? ram[laddr_b][14] : lwdata_b[14]); + ram[laddr_b][15] = (lwmsk_b[15] ? ram[laddr_b][15] : lwdata_b[15]); + ram[laddr_b][16] = (lwmsk_b[16] ? ram[laddr_b][16] : lwdata_b[16]); + ram[laddr_b][17] = (lwmsk_b[17] ? ram[laddr_b][17] : lwdata_b[17]); + lwen_b = 1; + end + if (lcen_b == 0) begin + rdata_b = ram[laddr_b]; + lcen_b = 1; + end + else + rdata_b = rdata_b; + end + always @(*) begin + if ((lwen_a == 0) && (lcen_a == 0)) begin + ram[laddr_a][0] = (lwmsk_a[0] ? ram[laddr_a][0] : lwdata_a[0]); + ram[laddr_a][1] = (lwmsk_a[1] ? ram[laddr_a][1] : lwdata_a[1]); + ram[laddr_a][2] = (lwmsk_a[2] ? ram[laddr_a][2] : lwdata_a[2]); + ram[laddr_a][3] = (lwmsk_a[3] ? ram[laddr_a][3] : lwdata_a[3]); + ram[laddr_a][4] = (lwmsk_a[4] ? ram[laddr_a][4] : lwdata_a[4]); + ram[laddr_a][5] = (lwmsk_a[5] ? ram[laddr_a][5] : lwdata_a[5]); + ram[laddr_a][6] = (lwmsk_a[6] ? ram[laddr_a][6] : lwdata_a[6]); + ram[laddr_a][7] = (lwmsk_a[7] ? ram[laddr_a][7] : lwdata_a[7]); + ram[laddr_a][8] = (lwmsk_a[8] ? ram[laddr_a][8] : lwdata_a[8]); + ram[laddr_a][9] = (lwmsk_a[9] ? ram[laddr_a][9] : lwdata_a[9]); + ram[laddr_a][10] = (lwmsk_a[10] ? ram[laddr_a][10] : lwdata_a[10]); + ram[laddr_a][11] = (lwmsk_a[11] ? ram[laddr_a][11] : lwdata_a[11]); + ram[laddr_a][12] = (lwmsk_a[12] ? ram[laddr_a][12] : lwdata_a[12]); + ram[laddr_a][13] = (lwmsk_a[13] ? ram[laddr_a][13] : lwdata_a[13]); + ram[laddr_a][14] = (lwmsk_a[14] ? ram[laddr_a][14] : lwdata_a[14]); + ram[laddr_a][15] = (lwmsk_a[15] ? ram[laddr_a][15] : lwdata_a[15]); + ram[laddr_a][16] = (lwmsk_a[16] ? ram[laddr_a][16] : lwdata_a[16]); + ram[laddr_a][17] = (lwmsk_a[17] ? ram[laddr_a][17] : lwdata_a[17]); + lwen_a = 1; + end + if (lcen_a == 0) begin + rdata_a = ram[laddr_a]; + lcen_a = 1; + end + else + rdata_a = rdata_a; + end +endmodule
diff --git a/ql-qlf-plugin/qlf_k6n10f/ufifo_ctl.v b/ql-qlf-plugin/qlf_k6n10f/ufifo_ctl.v new file mode 100644 index 0000000..ad26b22 --- /dev/null +++ b/ql-qlf-plugin/qlf_k6n10f/ufifo_ctl.v
@@ -0,0 +1,623 @@ +// Copyright (C) 2020-2021 The SymbiFlow Authors. +// +// Use of this source code is governed by a ISC-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/ISC +// +// SPDX-License-Identifier:ISC + +module fifo_ctl ( + raddr, + waddr, + fflags, + ren_o, + sync, + depth, + rmode, + wmode, + rclk, + rst_R_n, + wclk, + rst_W_n, + ren, + wen, + upaf, + upae +); + parameter ADDR_WIDTH = 11; + parameter FIFO_WIDTH = 3'd2; + output wire [ADDR_WIDTH - 1:0] raddr; + output wire [ADDR_WIDTH - 1:0] waddr; + output wire [7:0] fflags; + output wire ren_o; + input wire sync; + input wire [2:0] depth; + input wire [1:0] rmode; + input wire [1:0] wmode; + input wire rclk; + input wire rst_R_n; + input wire wclk; + input wire rst_W_n; + input wire ren; + input wire wen; + input wire [ADDR_WIDTH - 1:0] upaf; + input wire [ADDR_WIDTH - 1:0] upae; + reg [ADDR_WIDTH:0] pushtopop1; + reg [ADDR_WIDTH:0] pushtopop2; + reg [ADDR_WIDTH:0] poptopush1; + reg [ADDR_WIDTH:0] poptopush2; + wire [ADDR_WIDTH:0] pushtopop0; + wire [ADDR_WIDTH:0] poptopush0; + wire [ADDR_WIDTH:0] smux_poptopush; + wire [ADDR_WIDTH:0] smux_pushtopop; + assign smux_poptopush = (sync ? poptopush0 : poptopush2); + assign smux_pushtopop = (sync ? pushtopop0 : pushtopop2); + always @(posedge rclk or negedge rst_R_n) + if (~rst_R_n) begin + pushtopop1 <= #(1) 12'h000; + pushtopop2 <= #(1) 12'h000; + end + else begin + pushtopop1 <= #(1) pushtopop0; + pushtopop2 <= #(1) pushtopop1; + end + always @(posedge wclk or negedge rst_W_n) + if (~rst_W_n) begin + poptopush1 <= #(1) 12'h000; + poptopush2 <= #(1) 12'h000; + end + else begin + poptopush1 <= #(1) poptopush0; + poptopush2 <= #(1) poptopush1; + end + fifo_push #(.ADDR_WIDTH(ADDR_WIDTH)) u_fifo_push( + .wclk(wclk), + .wen(wen), + .rst_n(rst_W_n), + .rmode(rmode), + .wmode(wmode), + .gcout(pushtopop0), + .gcin(smux_poptopush), + .ff_waddr(waddr), + .depth(depth), + .pushflags(fflags[7:4]), + .upaf(upaf) + ); + fifo_pop #( + .ADDR_WIDTH(ADDR_WIDTH), + .FIFO_WIDTH(FIFO_WIDTH) + ) u_fifo_pop( + .rclk(rclk), + .ren_in(ren), + .rst_n(rst_R_n), + .rmode(rmode), + .wmode(wmode), + .ren_o(ren_o), + .gcout(poptopush0), + .gcin(smux_pushtopop), + .out_raddr(raddr), + .depth(depth), + .popflags(fflags[3:0]), + .upae(upae) + ); +endmodule +module fifo_push ( + pushflags, + gcout, + ff_waddr, + rst_n, + wclk, + wen, + rmode, + wmode, + depth, + gcin, + upaf +); + parameter ADDR_WIDTH = 11; + output wire [3:0] pushflags; + output wire [ADDR_WIDTH:0] gcout; + output wire [ADDR_WIDTH - 1:0] ff_waddr; + input rst_n; + input wclk; + input wen; + input [1:0] rmode; + input [1:0] wmode; + input [2:0] depth; + input [ADDR_WIDTH:0] gcin; + input [ADDR_WIDTH - 1:0] upaf; + reg full_next; + reg full; + reg paf_next; + reg paf; + reg fmo; + reg fmo_next; + reg overflow; + reg p1; + reg p2; + reg f1; + reg f2; + reg q1; + reg q2; + reg [1:0] gmode; + reg [ADDR_WIDTH:0] waddr; + reg [ADDR_WIDTH:0] raddr; + reg [ADDR_WIDTH:0] gcout_reg; + reg [ADDR_WIDTH:0] gcout_next; + reg [ADDR_WIDTH:0] raddr_next; + reg [ADDR_WIDTH - 1:0] paf_thresh; + wire overflow_next; + wire [ADDR_WIDTH:0] waddr_next; + wire [ADDR_WIDTH:0] gc8out_next; + wire [ADDR_WIDTH - 1:0] gc16out_next; + wire [ADDR_WIDTH - 2:0] gc32out_next; + wire [ADDR_WIDTH:0] tmp; + wire [ADDR_WIDTH:0] next_count; + wire [ADDR_WIDTH:0] count; + reg [ADDR_WIDTH:0] fbytes; + genvar i; + assign next_count = fbytes - (waddr_next >= raddr_next ? waddr_next - raddr_next : (~raddr_next + waddr_next) + 1); + assign count = fbytes - (waddr >= raddr ? waddr - raddr : (~raddr + waddr) + 1); + always @(*) begin + case (depth) + 3'b000: fbytes = 12'd2048; + 3'b001: fbytes = 12'd1024; + 3'b010: fbytes = 12'd512; + 3'b011: fbytes = 12'd256; + 3'b100: fbytes = 12'd128; + 3'b101: fbytes = 12'd64; + 3'b110: fbytes = 12'd32; + 3'b111: fbytes = 13'd4096; + endcase + paf_thresh = (wmode ? (wmode[0] ? upaf << 1 : upaf) : upaf << 2); + end + always @(*) + case (wmode) + 2'h0, 2'h1, 2'h2: begin + full_next = (wen ? f1 : f2); + fmo_next = (wen ? p1 : p2); + paf_next = (wen ? q1 : q2); + end + default: begin + full_next = 1'b0; + fmo_next = 1'b0; + paf_next = 1'b0; + end + endcase + always @(*) begin : PUSH_FULL_FLAGS + f1 = 1'b0; + f2 = 1'b0; + p1 = 1'b0; + p2 = 1'b0; + q1 = next_count < paf_thresh; + q2 = count < paf_thresh; + case (wmode) + 2'h0: + case (depth) + 3'h0: begin + f1 = {~waddr_next[11], waddr_next[10:2]} == raddr_next[11:2]; + f2 = {~waddr[11], waddr[10:2]} == raddr_next[11:2]; + p1 = ((waddr_next[10:2] + 1) & 9'h1ff) == raddr_next[10:2]; + p2 = ((waddr[10:2] + 1) & 9'h1ff) == raddr_next[10:2]; + end + 3'h1: begin + f1 = {~waddr_next[10], waddr_next[9:2]} == raddr_next[10:2]; + f2 = {~waddr[10], waddr[9:2]} == raddr_next[10:2]; + p1 = ((waddr_next[9:2] + 1) & 8'hff) == raddr_next[9:2]; + p2 = ((waddr[9:2] + 1) & 8'hff) == raddr_next[9:2]; + end + 3'h2: begin + f1 = {~waddr_next[9], waddr_next[8:2]} == raddr_next[9:2]; + f2 = {~waddr[9], waddr[8:2]} == raddr_next[9:2]; + p1 = ((waddr_next[8:2] + 1) & 7'h7f) == raddr_next[8:2]; + p2 = ((waddr[8:2] + 1) & 7'h7f) == raddr_next[8:2]; + end + 3'h3: begin + f1 = {~waddr_next[8], waddr_next[7:2]} == raddr_next[8:2]; + f2 = {~waddr[8], waddr[7:2]} == raddr_next[8:2]; + p1 = ((waddr_next[7:2] + 1) & 6'h3f) == raddr_next[7:2]; + p2 = ((waddr[7:2] + 1) & 6'h3f) == raddr_next[7:2]; + end + 3'h4: begin + f1 = {~waddr_next[7], waddr_next[6:2]} == raddr_next[7:2]; + f2 = {~waddr[7], waddr[6:2]} == raddr_next[7:2]; + p1 = ((waddr_next[6:2] + 1) & 5'h1f) == raddr_next[6:2]; + p2 = ((waddr[6:2] + 1) & 5'h1f) == raddr_next[6:2]; + end + 3'h5: begin + f1 = {~waddr_next[6], waddr_next[5:2]} == raddr_next[6:2]; + f2 = {~waddr[6], waddr[5:2]} == raddr_next[6:2]; + p1 = ((waddr_next[5:2] + 1) & 4'hf) == raddr_next[5:2]; + p2 = ((waddr[5:2] + 1) & 4'hf) == raddr_next[5:2]; + end + 3'h6: begin + f1 = {~waddr_next[5], waddr_next[4:2]} == raddr_next[5:2]; + f2 = {~waddr[5], waddr[4:2]} == raddr_next[5:2]; + p1 = ((waddr_next[4:2] + 1) & 3'h7) == raddr_next[4:2]; + p2 = ((waddr[4:2] + 1) & 3'h7) == raddr_next[4:2]; + end + 3'h7: begin + f1 = {~waddr_next[ADDR_WIDTH], waddr_next[ADDR_WIDTH - 1:2]} == raddr_next[ADDR_WIDTH:2]; + f2 = {~waddr[ADDR_WIDTH], waddr[10:2]} == raddr_next[ADDR_WIDTH:2]; + p1 = ((waddr_next[ADDR_WIDTH - 1:2] + 1) & {ADDR_WIDTH - 2 {1'b1}}) == raddr_next[ADDR_WIDTH - 1:2]; + p2 = ((waddr[ADDR_WIDTH - 1:2] + 1) & {ADDR_WIDTH - 2 {1'b1}}) == raddr_next[ADDR_WIDTH - 1:2]; + end + endcase + 2'h1: + case (depth) + 3'h0: begin + f1 = {~waddr_next[11], waddr_next[10:1]} == raddr_next[11:1]; + f2 = {~waddr[11], waddr[10:1]} == raddr_next[11:1]; + p1 = ((waddr_next[10:1] + 1) & 10'h3ff) == raddr_next[10:1]; + p2 = ((waddr[10:1] + 1) & 10'h3ff) == raddr_next[10:1]; + end + 3'h1: begin + f1 = {~waddr_next[10], waddr_next[9:1]} == raddr_next[10:1]; + f2 = {~waddr[10], waddr[9:1]} == raddr_next[10:1]; + p1 = ((waddr_next[9:1] + 1) & 9'h1ff) == raddr_next[9:1]; + p2 = ((waddr[9:1] + 1) & 9'h1ff) == raddr_next[9:1]; + end + 3'h2: begin + f1 = {~waddr_next[9], waddr_next[8:1]} == raddr_next[9:1]; + f2 = {~waddr[9], waddr[8:1]} == raddr_next[9:1]; + p1 = ((waddr_next[8:1] + 1) & 8'hff) == raddr_next[8:1]; + p2 = ((waddr[8:1] + 1) & 8'hff) == raddr_next[8:1]; + end + 3'h3: begin + f1 = {~waddr_next[8], waddr_next[7:1]} == raddr_next[8:1]; + f2 = {~waddr[8], waddr[7:1]} == raddr_next[8:1]; + p1 = ((waddr_next[7:1] + 1) & 7'h7f) == raddr_next[7:1]; + p2 = ((waddr[7:1] + 1) & 7'h7f) == raddr_next[7:1]; + end + 3'h4: begin + f1 = {~waddr_next[7], waddr_next[6:1]} == raddr_next[7:1]; + f2 = {~waddr[7], waddr[6:1]} == raddr_next[7:1]; + p1 = ((waddr_next[6:1] + 1) & 6'h3f) == raddr_next[6:1]; + p2 = ((waddr[6:1] + 1) & 6'h3f) == raddr_next[6:1]; + end + 3'h5: begin + f1 = {~waddr_next[6], waddr_next[5:1]} == raddr_next[6:1]; + f2 = {~waddr[6], waddr[5:1]} == raddr_next[6:1]; + p1 = ((waddr_next[5:1] + 1) & 5'h1f) == raddr_next[5:1]; + p2 = ((waddr[5:1] + 1) & 5'h1f) == raddr_next[5:1]; + end + 3'h6: begin + f1 = {~waddr_next[5], waddr_next[4:1]} == raddr_next[5:1]; + f2 = {~waddr[5], waddr[4:1]} == raddr_next[5:1]; + p1 = ((waddr_next[4:1] + 1) & 4'hf) == raddr_next[4:1]; + p2 = ((waddr[4:1] + 1) & 4'hf) == raddr_next[4:1]; + end + 3'h7: begin + f1 = {~waddr_next[ADDR_WIDTH], waddr_next[ADDR_WIDTH - 1:1]} == raddr_next[ADDR_WIDTH:1]; + f2 = {~waddr[11], waddr[ADDR_WIDTH - 1:1]} == raddr_next[ADDR_WIDTH:1]; + p1 = ((waddr_next[ADDR_WIDTH - 1:1] + 1) & {ADDR_WIDTH - 1 {1'b1}}) == raddr_next[ADDR_WIDTH - 1:1]; + p2 = ((waddr[ADDR_WIDTH - 1:1] + 1) & {ADDR_WIDTH - 1 {1'b1}}) == raddr_next[ADDR_WIDTH - 1:1]; + end + endcase + 2'h2: + case (depth) + 3'h0: begin + f1 = {~waddr_next[11], waddr_next[10:0]} == raddr_next[11:0]; + f2 = {~waddr[11], waddr[10:0]} == raddr_next[11:0]; + p1 = ((waddr_next[10:0] + 1) & 11'h7ff) == raddr_next[10:0]; + p2 = ((waddr[10:0] + 1) & 11'h7ff) == raddr_next[10:0]; + end + 3'h1: begin + f1 = {~waddr_next[10], waddr_next[9:0]} == raddr_next[10:0]; + f2 = {~waddr[10], waddr[9:0]} == raddr_next[10:0]; + p1 = ((waddr_next[9:0] + 1) & 10'h3ff) == raddr_next[9:0]; + p2 = ((waddr[9:0] + 1) & 10'h3ff) == raddr_next[9:0]; + end + 3'h2: begin + f1 = {~waddr_next[9], waddr_next[8:0]} == raddr_next[9:0]; + f2 = {~waddr[9], waddr[8:0]} == raddr_next[9:0]; + p1 = ((waddr_next[8:0] + 1) & 9'h1ff) == raddr_next[8:0]; + p2 = ((waddr[8:0] + 1) & 9'h1ff) == raddr_next[8:0]; + end + 3'h3: begin + f1 = {~waddr_next[8], waddr_next[7:0]} == raddr_next[8:0]; + f2 = {~waddr[8], waddr[7:0]} == raddr_next[8:0]; + p1 = ((waddr_next[7:0] + 1) & 8'hff) == raddr_next[7:0]; + p2 = ((waddr[7:0] + 1) & 8'hff) == raddr_next[7:0]; + end + 3'h4: begin + f1 = {~waddr_next[7], waddr_next[6:0]} == raddr_next[7:0]; + f2 = {~waddr[7], waddr[6:0]} == raddr_next[7:0]; + p1 = ((waddr_next[6:0] + 1) & 7'h7f) == raddr_next[6:0]; + p2 = ((waddr[6:0] + 1) & 7'h7f) == raddr_next[6:0]; + end + 3'h5: begin + f1 = {~waddr_next[6], waddr_next[5:0]} == raddr_next[6:0]; + f2 = {~waddr[6], waddr[5:0]} == raddr_next[6:0]; + p1 = ((waddr_next[5:0] + 1) & 6'h3f) == raddr_next[5:0]; + p2 = ((waddr[5:0] + 1) & 6'h3f) == raddr_next[5:0]; + end + 3'h6: begin + f1 = {~waddr_next[5], waddr_next[4:0]} == raddr_next[5:0]; + f2 = {~waddr[5], waddr[4:0]} == raddr_next[5:0]; + p1 = ((waddr_next[4:0] + 1) & 5'h1f) == raddr_next[4:0]; + p2 = ((waddr[4:0] + 1) & 5'h1f) == raddr_next[4:0]; + end + 3'h7: begin + f1 = {~waddr_next[ADDR_WIDTH], waddr_next[ADDR_WIDTH - 1:0]} == raddr_next[ADDR_WIDTH:0]; + f2 = {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH - 1:0]} == raddr_next[ADDR_WIDTH:0]; + p1 = ((waddr_next[ADDR_WIDTH - 1:0] + 1) & {ADDR_WIDTH {1'b1}}) == raddr_next[ADDR_WIDTH - 1:0]; + p2 = ((waddr[ADDR_WIDTH - 1:0] + 1) & {ADDR_WIDTH {1'b1}}) == raddr_next[ADDR_WIDTH - 1:0]; + end + endcase + 2'h3: begin + f1 = 1'b0; + f2 = 1'b0; + p1 = 1'b0; + p2 = 1'b0; + end + endcase + end + always @(*) + case (wmode) + 2'h0: gmode = 2'h0; + 2'h1: gmode = (rmode == 2'h0 ? 2'h0 : 2'h1); + 2'h2: gmode = (rmode == 2'h2 ? 2'h2 : rmode); + 2'h3: gmode = 2'h3; + endcase + assign gc8out_next = (waddr_next >> 1) ^ waddr_next; + assign gc16out_next = (waddr_next >> 2) ^ (waddr_next >> 1); + assign gc32out_next = (waddr_next >> 3) ^ (waddr_next >> 2); + always @(*) + if (wen) + case (gmode) + 2'h2: gcout_next = gc8out_next; + 2'h1: gcout_next = {1'b0, gc16out_next}; + 2'h0: gcout_next = {2'b00, gc32out_next}; + default: gcout_next = 12'h000; + endcase + else + gcout_next = 12'h000; + always @(posedge wclk or negedge rst_n) + if (~rst_n) begin + full <= #(1) 1'b0; + fmo <= #(1) 1'b0; + paf <= #(1) 1'b0; + raddr <= #(1) ADDR_WIDTH + 1'h0; + end + else begin + full <= #(1) full_next; + fmo <= #(1) fmo_next; + paf <= #(1) paf_next; + case (gmode) + 0: raddr <= #(1) raddr_next & {{ADDR_WIDTH - 1 {1'b1}}, 2'b00}; + 1: raddr <= #(1) raddr_next & {{ADDR_WIDTH {1'b1}}, 1'b0}; + 2: raddr <= #(1) raddr_next & {ADDR_WIDTH + 1 {1'b1}}; + 3: raddr <= #(1) 12'h000; + endcase + end + assign overflow_next = full & wen; + always @(posedge wclk or negedge rst_n) + if (~rst_n) + overflow <= #(1) 1'b0; + else if (wen == 1'b1) + overflow <= #(1) overflow_next; + always @(posedge wclk or negedge rst_n) + if (~rst_n) begin + waddr <= #(1) {ADDR_WIDTH + 1 {1'b0}}; + gcout_reg <= #(1) {ADDR_WIDTH + 1 {1'b0}}; + end + else if (wen == 1'b1) begin + waddr <= #(1) waddr_next; + gcout_reg <= #(1) gcout_next; + end + assign gcout = gcout_reg; + generate + for (i = 0; i < (ADDR_WIDTH + 1); i = i + 1) begin : genblk1 + assign tmp[i] = ^(gcin >> i); + end + endgenerate + always @(*) + case (gmode) + 2'h0: raddr_next = {tmp[ADDR_WIDTH - 2:0], 2'b00} & {{ADDR_WIDTH - 1 {1'b1}}, 2'b00}; + 2'h1: raddr_next = {tmp[ADDR_WIDTH - 1:0], 1'b0} & {{ADDR_WIDTH {1'b1}}, 1'b0}; + 2'h2: raddr_next = {tmp[ADDR_WIDTH:0]} & {ADDR_WIDTH + 1 {1'b1}}; + default: raddr_next = {ADDR_WIDTH + 1 {1'b0}}; + endcase + assign ff_waddr = waddr[ADDR_WIDTH - 1:0]; + assign pushflags = (rst_n ? {full, fmo, paf, overflow} : 4'b1111); + assign waddr_next = waddr + (wmode == 2'h0 ? 'h4 : (wmode == 2'h1 ? 'h2 : 'h1)); +endmodule +module fifo_pop ( + ren_o, + popflags, + out_raddr, + gcout, + rst_n, + rclk, + ren_in, + rmode, + wmode, + gcin, + depth, + upae +); + parameter ADDR_WIDTH = 11; + parameter FIFO_WIDTH = 3'd2; + output wire ren_o; + output wire [3:0] popflags; + output reg [ADDR_WIDTH - 1:0] out_raddr; + output wire [ADDR_WIDTH:0] gcout; + input rst_n; + input rclk; + input ren_in; + input [1:0] rmode; + input [1:0] wmode; + input [ADDR_WIDTH:0] gcin; + input [ADDR_WIDTH - 1:0] upae; + input [2:0] depth; + reg empty; + reg epo; + reg pae; + reg underflow; + reg e1; + reg e2; + reg o1; + reg o2; + reg q1; + reg q2; + reg [1:0] bwl_sel; + reg [1:0] gmode; + reg [ADDR_WIDTH - 1:0] ff_raddr; + reg [ADDR_WIDTH:0] waddr; + reg [ADDR_WIDTH:0] raddr; + reg [ADDR_WIDTH:0] gcout_reg; + reg [ADDR_WIDTH:0] gcout_next; + reg [ADDR_WIDTH:0] waddr_next; + reg [ADDR_WIDTH - 1:0] pae_thresh; + wire ren_out; + wire empty_next; + wire pae_next; + wire epo_next; + wire [ADDR_WIDTH - 2:0] gc32out_next; + wire [ADDR_WIDTH - 1:0] gc16out_next; + wire [ADDR_WIDTH:0] gc8out_next; + wire [ADDR_WIDTH:0] raddr_next; + wire [ADDR_WIDTH - 1:0] ff_raddr_next; + wire [ADDR_WIDTH:0] tmp; + wire [ADDR_WIDTH:0] next_count; + wire [ADDR_WIDTH:0] count; + reg [ADDR_WIDTH:0] fbytes; + genvar i; + assign next_count = waddr - raddr_next; + assign count = waddr - raddr; + always @(*) + case (depth) + 3'b000: fbytes = 'd2048; + 3'b001: fbytes = 'd1024; + 3'b010: fbytes = 'd512; + 3'b011: fbytes = 'd256; + 3'b100: fbytes = 'd128; + 3'b101: fbytes = 'd64; + 3'b110: fbytes = 'd32; + 3'b111: fbytes = 'd4096; + endcase + always @(*) pae_thresh = (rmode ? (rmode[0] ? upae < 1 : upae) : upae << 2); + assign ren_out = (empty ? 1'b1 : ren_in); + always @(*) + case (rmode) + 2'h0: gmode = 2'h0; + 2'h1: gmode = (wmode == 2'h0 ? 2'h0 : 2'h1); + 2'h2: gmode = (wmode == 2'h2 ? 2'h2 : wmode); + 2'h3: gmode = 2'h3; + endcase + always @(*) begin + e1 = 1'b0; + e2 = 1'b0; + o1 = 1'b0; + o2 = 1'b0; + q1 = next_count < pae_thresh; + q2 = count < pae_thresh; + case (rmode) + 2'h0: begin + e1 = raddr_next[ADDR_WIDTH:2] == waddr_next[ADDR_WIDTH:2]; + e2 = raddr[ADDR_WIDTH:2] == waddr_next[ADDR_WIDTH:2]; + o1 = (raddr_next[ADDR_WIDTH:2] + 1) == waddr_next[ADDR_WIDTH:2]; + o2 = (raddr[ADDR_WIDTH:2] + 1) == waddr_next[ADDR_WIDTH:2]; + end + 2'h1: begin + e1 = raddr_next[ADDR_WIDTH:1] == waddr_next[ADDR_WIDTH:1]; + e2 = raddr[ADDR_WIDTH:1] == waddr_next[ADDR_WIDTH:1]; + o1 = (raddr_next[ADDR_WIDTH:1] + 1) == waddr_next[ADDR_WIDTH:1]; + o2 = (raddr[ADDR_WIDTH:1] + 1) == waddr_next[ADDR_WIDTH:1]; + end + 2'h2: begin + e1 = raddr_next[ADDR_WIDTH:0] == waddr_next[ADDR_WIDTH:0]; + e2 = raddr[ADDR_WIDTH:0] == waddr_next[ADDR_WIDTH:0]; + o1 = (raddr_next[ADDR_WIDTH:0] + 1) == waddr_next[ADDR_WIDTH:0]; + o2 = (raddr[ADDR_WIDTH:0] + 1) == waddr_next[11:0]; + end + 2'h3: begin + e1 = 1'b0; + e2 = 1'b0; + o1 = 1'b0; + o2 = 1'b0; + end + endcase + end + assign empty_next = (ren_in & !empty ? e1 : e2); + assign epo_next = (ren_in & !empty ? o1 : o2); + assign pae_next = (ren_in & !empty ? q1 : q2); + always @(posedge rclk or negedge rst_n) + if (~rst_n) begin + empty <= #(1) 1'b1; + pae <= #(1) 1'b1; + epo <= #(1) 1'b0; + end + else begin + empty <= #(1) empty_next; + pae <= #(1) pae_next; + epo <= #(1) epo_next; + end + assign gc8out_next = (raddr_next >> 1) ^ raddr_next; + assign gc16out_next = (raddr_next >> 2) ^ (raddr_next >> 1); + assign gc32out_next = (raddr_next >> 3) ^ (raddr_next >> 2); + always @(*) + if (ren_in) + case (gmode) + 2'h2: gcout_next = gc8out_next; + 2'h1: gcout_next = {1'b0, gc16out_next}; + 2'h0: gcout_next = {2'b00, gc32out_next}; + default: gcout_next = 'h0; + endcase + else + gcout_next = 'h0; + always @(posedge rclk or negedge rst_n) + if (~rst_n) + waddr <= #(1) 12'h000; + else + waddr <= #(1) waddr_next; + always @(posedge rclk or negedge rst_n) + if (~rst_n) begin + underflow <= #(1) 1'b0; + bwl_sel <= #(1) 2'h0; + gcout_reg <= #(1) 12'h000; + end + else if (ren_in) begin + underflow <= #(1) empty; + if (!empty) begin + bwl_sel <= #(1) raddr_next[1:0]; + gcout_reg <= #(1) gcout_next; + end + end + generate + for (i = 0; i < (ADDR_WIDTH + 1); i = i + 1) begin : genblk1 + assign tmp[i] = ^(gcin >> i); + end + endgenerate + always @(*) + case (gmode) + 2'h0: waddr_next = {tmp[9:0], 2'b00} & 12'hffc; + 2'h1: waddr_next = {tmp[10:0], 1'b0} & 12'hffe; + 2'h2: waddr_next = {tmp[11:0]} & 12'hfff; + default: waddr_next = 12'h000; + endcase + assign ff_raddr_next = ff_raddr + (rmode == 2'h0 ? 'h4 : (rmode == 2'h1 ? 'h2 : 'h1)); + assign raddr_next = raddr + (rmode == 2'h0 ? 'h4 : (rmode == 2'h1 ? 'h2 : 'h1)); + always @(posedge rclk or negedge rst_n) + if (~rst_n) + ff_raddr <= #(1) 1'sb0; + else if (empty & ~empty_next) + ff_raddr <= #(1) raddr_next[10:0]; + else if ((ren_in & !empty) & ~empty_next) + ff_raddr <= #(1) ff_raddr_next; + always @(posedge rclk or negedge rst_n) + if (~rst_n) + raddr <= #(1) 12'h000; + else if (ren_in & !empty) + raddr <= #(1) raddr_next; + always @(*) + case (FIFO_WIDTH) + default: out_raddr = ff_raddr[ADDR_WIDTH - 1:0]; + 2: out_raddr = {ff_raddr[ADDR_WIDTH - 1:1], bwl_sel[0]}; + 4: out_raddr = {ff_raddr[ADDR_WIDTH - 1:2], bwl_sel}; + endcase + assign ren_o = ren_out; + assign gcout = gcout_reg; + assign popflags = {empty, epo, pae, underflow}; +endmodule