diff --git a/techlibs/quicklogic/Makefile.inc b/techlibs/quicklogic/Makefile.inc index 852a8a77a..58dfc5b45 100644 --- a/techlibs/quicklogic/Makefile.inc +++ b/techlibs/quicklogic/Makefile.inc @@ -37,4 +37,7 @@ $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ffs_map.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_sim.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_map.v)) -$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_final_map.v)) \ No newline at end of file +$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_final_map.v)) +$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v)) +$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v)) +$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v)) \ No newline at end of file diff --git a/techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v b/techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v new file mode 100644 index 000000000..68c2eb0aa --- /dev/null +++ b/techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v @@ -0,0 +1,344 @@ +// Copyright 2020-2022 F4PGA Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype wire +module TDP18K_FIFO ( + RMODE_A_i, + RMODE_B_i, + WMODE_A_i, + WMODE_B_i, + WEN_A_i, + WEN_B_i, + REN_A_i, + REN_B_i, + CLK_A_i, + CLK_B_i, + BE_A_i, + BE_B_i, + ADDR_A_i, + ADDR_B_i, + WDATA_A_i, + WDATA_B_i, + RDATA_A_o, + RDATA_B_o, + EMPTY_o, + EPO_o, + EWM_o, + UNDERRUN_o, + FULL_o, + FMO_o, + FWM_o, + OVERRUN_o, + FLUSH_ni, + FMODE_i, +); + parameter SYNC_FIFO_i = 1'b0; + parameter POWERDN_i = 1'b0; + parameter SLEEP_i = 1'b0; + parameter PROTECT_i = 1'b0; + parameter UPAF_i = 11'b0; + parameter UPAE_i = 11'b0; + parameter [18*1024-1:0] INIT_i = 18431'bx; + + input wire [2:0] RMODE_A_i; + input wire [2:0] RMODE_B_i; + input wire [2:0] WMODE_A_i; + input wire [2:0] WMODE_B_i; + input wire WEN_A_i; + input wire WEN_B_i; + input wire REN_A_i; + input wire REN_B_i; + (* clkbuf_sink *) + input wire CLK_A_i; + (* clkbuf_sink *) + input wire CLK_B_i; + input wire [1:0] BE_A_i; + input wire [1:0] BE_B_i; + input wire [13:0] ADDR_A_i; + input wire [13:0] ADDR_B_i; + input wire [17:0] WDATA_A_i; + input wire [17:0] WDATA_B_i; + output reg [17:0] RDATA_A_o; + output reg [17:0] RDATA_B_o; + output wire EMPTY_o; + output wire EPO_o; + output wire EWM_o; + output wire UNDERRUN_o; + output wire FULL_o; + output wire FMO_o; + output wire FWM_o; + output wire OVERRUN_o; + input wire FLUSH_ni; + input wire FMODE_i; + 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 [3:0] ram_waddr_a; + wire [3:0] ram_waddr_b; + 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; + wire cen_a_n; + wire cen_b_n; + wire ram_wen_a_n; + wire ram_wen_b_n; + localparam MODE_9 = 3'b001; + always @(*) begin + fifo_rmode = (RMODE_B_i == MODE_9 ? 2'b10 : 2'b01); + fifo_wmode = (WMODE_A_i == MODE_9 ? 2'b10 : 2'b01); + end + assign smux_clk_a = CLK_A_i; + assign smux_clk_b = CLK_B_i; + assign real_fmode = FMODE_i; + assign ram_ren_b = real_fmode ? ren_o : REN_B_i; + assign ram_wen_a = FMODE_i ? ~FULL_o & WEN_A_i : WEN_A_i; + assign ram_ren_a = FMODE_i ? 0 : REN_A_i; + assign ram_wen_b = FMODE_i ? 1'b0 : WEN_B_i; + assign cen_b = ram_ren_b | ram_wen_b; + assign cen_a = ram_ren_a | ram_wen_a; + assign ram_waddr_b = real_fmode ? {ff_raddr[0], 3'b000} : ADDR_B_i[3:0]; + assign ram_waddr_a = real_fmode ? {ff_waddr[0], 3'b000} : ADDR_A_i[3:0]; + assign ram_addr_b = real_fmode ? {ff_raddr[10:0], 3'h0} : {ADDR_B_i[13:4], addr_b_d[3:0]}; + assign ram_addr_a = real_fmode ? {ff_waddr[10:0], 3'h0} : {ADDR_A_i[13:4], addr_a_d[3:0]}; + always @(posedge CLK_A_i) addr_a_d[3:0] <= ADDR_A_i[3:0]; + always @(posedge CLK_B_i) addr_b_d[3:0] <= ADDR_B_i[3:0]; + assign cen_a_n = ~cen_a; + assign ram_wen_a_n = ~ram_wen_a; + assign cen_b_n = ~cen_b; + assign ram_wen_b_n = ~ram_wen_b; + + sram1024x18 #( + .init(INIT_i) + ) uram( + .clk_a(smux_clk_a), + .cen_a(cen_a_n), + .wen_a(ram_wen_a_n), + .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_n), + .wen_b(ram_wen_b_n), + .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), + .DEPTH(6) + ) fifo_ctl( + .rclk(smux_clk_b), + .rst_R_n(FLUSH_ni), + .wclk(smux_clk_a), + .rst_W_n(FLUSH_ni), + .ren(REN_B_i), + .wen(ram_wen_a), + .sync(SYNC_FIFO_i), + .rmode(fifo_rmode), + .wmode(fifo_wmode), + .ren_o(ren_o), + .fflags({FULL_o, FMO_o, FWM_o, OVERRUN_o, EMPTY_o, EPO_o, EWM_o, UNDERRUN_o}), + .raddr(ff_raddr), + .waddr(ff_waddr), + .upaf(UPAF_i), + .upae(UPAE_i) + ); + localparam MODE_1 = 3'b101; + localparam MODE_18 = 3'b010; + localparam MODE_2 = 3'b110; + localparam MODE_4 = 3'b100; + always @(*) begin : WDATA_MODE_SEL + if (ram_wen_a == 1) begin + case (WMODE_A_i) + MODE_18: begin + aligned_wdata_a = WDATA_A_i; + {wmsk_a[17], wmsk_a[15:8]} = (FMODE_i ? 9'h000 : (BE_A_i[1] ? 9'h000 : 9'h1ff)); + {wmsk_a[16], wmsk_a[7:0]} = (FMODE_i ? 9'h000 : (BE_A_i[0] ? 9'h000 : 9'h1ff)); + end + MODE_9: begin + aligned_wdata_a = {{2 {WDATA_A_i[16]}}, {2 {WDATA_A_i[7:0]}}}; + {wmsk_a[17], wmsk_a[15:8]} = (ram_waddr_a[3] ? 9'h000 : 9'h1ff); + {wmsk_a[16], wmsk_a[7:0]} = (ram_waddr_a[3] ? 9'h1ff : 9'h000); + end + MODE_4: begin + aligned_wdata_a = {2'b00, {4 {WDATA_A_i[3:0]}}}; + wmsk_a[17:16] = 2'b00; + wmsk_a[15:12] = (ram_waddr_a[3:2] == 2'b11 ? 4'h0 : 4'hf); + wmsk_a[11:8] = (ram_waddr_a[3:2] == 2'b10 ? 4'h0 : 4'hf); + wmsk_a[7:4] = (ram_waddr_a[3:2] == 2'b01 ? 4'h0 : 4'hf); + wmsk_a[3:0] = (ram_waddr_a[3:2] == 2'b00 ? 4'h0 : 4'hf); + end + MODE_2: begin + aligned_wdata_a = {2'b00, {8 {WDATA_A_i[1:0]}}}; + wmsk_a[17:16] = 2'b00; + wmsk_a[15:14] = (ram_waddr_a[3:1] == 3'b111 ? 2'h0 : 2'h3); + wmsk_a[13:12] = (ram_waddr_a[3:1] == 3'b110 ? 2'h0 : 2'h3); + wmsk_a[11:10] = (ram_waddr_a[3:1] == 3'b101 ? 2'h0 : 2'h3); + wmsk_a[9:8] = (ram_waddr_a[3:1] == 3'b100 ? 2'h0 : 2'h3); + wmsk_a[7:6] = (ram_waddr_a[3:1] == 3'b011 ? 2'h0 : 2'h3); + wmsk_a[5:4] = (ram_waddr_a[3:1] == 3'b010 ? 2'h0 : 2'h3); + wmsk_a[3:2] = (ram_waddr_a[3:1] == 3'b001 ? 2'h0 : 2'h3); + wmsk_a[1:0] = (ram_waddr_a[3:1] == 3'b000 ? 2'h0 : 2'h3); + end + MODE_1: begin + aligned_wdata_a = {2'b00, {16 {WDATA_A_i[0]}}}; + wmsk_a = 18'h0ffff; + wmsk_a[{1'b0, ram_waddr_a[3:0]}] = 0; + end + default: wmsk_a = 18'h3ffff; + endcase + end + else begin + aligned_wdata_a = 18'h00000; + wmsk_a = 18'h3ffff; + end + if (ram_wen_b == 1) + case (WMODE_B_i) + MODE_18: begin + aligned_wdata_b = WDATA_B_i; + {wmsk_b[17], wmsk_b[15:8]} = (BE_B_i[1] ? 9'h000 : 9'h1ff); + {wmsk_b[16], wmsk_b[7:0]} = (BE_B_i[0] ? 9'h000 : 9'h1ff); + end + MODE_9: begin + aligned_wdata_b = {{2 {WDATA_B_i[16]}}, {2 {WDATA_B_i[7:0]}}}; + {wmsk_b[17], wmsk_b[15:8]} = (ram_waddr_b[3] ? 9'h000 : 9'h1ff); + {wmsk_b[16], wmsk_b[7:0]} = (ram_waddr_b[3] ? 9'h1ff : 9'h000); + end + MODE_4: begin + aligned_wdata_b = {2'b00, {4 {WDATA_B_i[3:0]}}}; + wmsk_b[17:16] = 2'b00; + wmsk_b[15:12] = (ram_waddr_b[3:2] == 2'b11 ? 4'h0 : 4'hf); + wmsk_b[11:8] = (ram_waddr_b[3:2] == 2'b10 ? 4'h0 : 4'hf); + wmsk_b[7:4] = (ram_waddr_b[3:2] == 2'b01 ? 4'h0 : 4'hf); + wmsk_b[3:0] = (ram_waddr_b[3:2] == 2'b00 ? 4'h0 : 4'hf); + end + MODE_2: begin + aligned_wdata_b = {2'b00, {8 {WDATA_B_i[1:0]}}}; + wmsk_b[17:16] = 2'b00; + wmsk_b[15:14] = (ram_waddr_b[3:1] == 3'b111 ? 2'h0 : 2'h3); + wmsk_b[13:12] = (ram_waddr_b[3:1] == 3'b110 ? 2'h0 : 2'h3); + wmsk_b[11:10] = (ram_waddr_b[3:1] == 3'b101 ? 2'h0 : 2'h3); + wmsk_b[9:8] = (ram_waddr_b[3:1] == 3'b100 ? 2'h0 : 2'h3); + wmsk_b[7:6] = (ram_waddr_b[3:1] == 3'b011 ? 2'h0 : 2'h3); + wmsk_b[5:4] = (ram_waddr_b[3:1] == 3'b010 ? 2'h0 : 2'h3); + wmsk_b[3:2] = (ram_waddr_b[3:1] == 3'b001 ? 2'h0 : 2'h3); + wmsk_b[1:0] = (ram_waddr_b[3:1] == 3'b000 ? 2'h0 : 2'h3); + end + MODE_1: begin + aligned_wdata_b = {2'b00, {16 {WDATA_B_i[0]}}}; + wmsk_b = 18'h0ffff; + wmsk_b[{1'b0, ram_waddr_b[3:0]}] = 0; + end + default: wmsk_b = 18'h3ffff; + endcase + else begin + aligned_wdata_b = 18'b000000000000000000; + wmsk_b = 18'h3ffff; + end + end + always @(*) begin : RDATA_A_MODE_SEL + case (RMODE_A_i) + default: RDATA_A_o = 18'h00000; + MODE_18: RDATA_A_o = ram_rdata_a; + MODE_9: begin + {RDATA_A_o[17], RDATA_A_o[15:8]} = 9'h000; + {RDATA_A_o[16], RDATA_A_o[7: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_o[17:4] = 14'h0000; + case (ram_addr_a[3:2]) + 3: RDATA_A_o[3:0] = ram_rdata_a[15:12]; + 2: RDATA_A_o[3:0] = ram_rdata_a[11:8]; + 1: RDATA_A_o[3:0] = ram_rdata_a[7:4]; + 0: RDATA_A_o[3:0] = ram_rdata_a[3:0]; + endcase + end + MODE_2: begin + RDATA_A_o[17:2] = 16'h0000; + case (ram_addr_a[3:1]) + 7: RDATA_A_o[1:0] = ram_rdata_a[15:14]; + 6: RDATA_A_o[1:0] = ram_rdata_a[13:12]; + 5: RDATA_A_o[1:0] = ram_rdata_a[11:10]; + 4: RDATA_A_o[1:0] = ram_rdata_a[9:8]; + 3: RDATA_A_o[1:0] = ram_rdata_a[7:6]; + 2: RDATA_A_o[1:0] = ram_rdata_a[5:4]; + 1: RDATA_A_o[1:0] = ram_rdata_a[3:2]; + 0: RDATA_A_o[1:0] = ram_rdata_a[1:0]; + endcase + end + MODE_1: begin + RDATA_A_o[17:1] = 17'h00000; + RDATA_A_o[0] = ram_rdata_a[ram_addr_a[3:0]]; + end + endcase + end + always @(*) + case (RMODE_B_i) + default: RDATA_B_o = 18'h15566; + MODE_18: RDATA_B_o = ram_rdata_b; + MODE_9: begin + {RDATA_B_o[17], RDATA_B_o[15:8]} = 9'b000000000; + {RDATA_B_o[16], RDATA_B_o[7:0]} = (ram_addr_b[3] ? {ram_rdata_b[17], ram_rdata_b[15:8]} : {ram_rdata_b[16], ram_rdata_b[7:0]}); + end + MODE_4: + case (ram_addr_b[3:2]) + 3: RDATA_B_o[3:0] = ram_rdata_b[15:12]; + 2: RDATA_B_o[3:0] = ram_rdata_b[11:8]; + 1: RDATA_B_o[3:0] = ram_rdata_b[7:4]; + 0: RDATA_B_o[3:0] = ram_rdata_b[3:0]; + endcase + MODE_2: + case (ram_addr_b[3:1]) + 7: RDATA_B_o[1:0] = ram_rdata_b[15:14]; + 6: RDATA_B_o[1:0] = ram_rdata_b[13:12]; + 5: RDATA_B_o[1:0] = ram_rdata_b[11:10]; + 4: RDATA_B_o[1:0] = ram_rdata_b[9:8]; + 3: RDATA_B_o[1:0] = ram_rdata_b[7:6]; + 2: RDATA_B_o[1:0] = ram_rdata_b[5:4]; + 1: RDATA_B_o[1:0] = ram_rdata_b[3:2]; + 0: RDATA_B_o[1:0] = ram_rdata_b[1:0]; + endcase + MODE_1: RDATA_B_o[0] = ram_rdata_b[{1'b0, ram_addr_b[3:0]}]; + endcase +endmodule +`default_nettype none diff --git a/techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v b/techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v new file mode 100644 index 000000000..86698ffef --- /dev/null +++ b/techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v @@ -0,0 +1,64 @@ +`default_nettype none +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 +); + parameter [1024*18-1:0] init = 18431'bx; + (* clkbuf_sink *) + 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; + (* clkbuf_sink *) + 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]; + integer i; + initial begin + for (i = 0; i < 1024; i = i + 1) begin + ram[i] = init[18*i +: 18]; + end + end + + always @(posedge clk_a) begin + if (!cen_a) begin + if (!wen_a) + for (i = 0; i < 18; i++) begin + if (!wmsk_a[i]) ram[addr_a][i] <= wdata_a[i]; + end + rdata_a <= ram[addr_a]; + end + end + + always @(posedge clk_b) begin + if (!cen_b) begin + if (!wen_b) + for (i = 0; i < 18; i++) begin + if (!wmsk_b[i]) ram[addr_b][i] <= wdata_b[i]; + end + rdata_b <= ram[addr_b]; + end + end + +endmodule + diff --git a/techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v b/techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v new file mode 100644 index 000000000..441f6bc4a --- /dev/null +++ b/techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v @@ -0,0 +1,620 @@ +// Copyright 2020-2022 F4PGA Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype wire +module fifo_ctl ( + raddr, + waddr, + fflags, + ren_o, + sync, + rmode, + wmode, + rclk, + rst_R_n, + wclk, + rst_W_n, + ren, + wen, + upaf, + upae +); + parameter ADDR_WIDTH = 11; + parameter FIFO_WIDTH = 3'd2; + parameter DEPTH = 6; + 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 [1:0] rmode; + input wire [1:0] wmode; + (* clkbuf_sink *) + input wire rclk; + input wire rst_R_n; + (* clkbuf_sink *) + 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; + localparam ADDR_PLUS_ONE = ADDR_WIDTH + 1; + 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 <= 'h0; + pushtopop2 <= 'h0; + end + else begin + pushtopop1 = pushtopop0; + pushtopop2 = pushtopop1; + end + always @(posedge wclk or negedge rst_W_n) + if (~rst_W_n) begin + poptopush1 <= 'h0; + poptopush2 <= 'h0; + end + else begin + poptopush1 <= poptopush0; + poptopush2 <= poptopush1; + end + fifo_push #( + .ADDR_WIDTH(ADDR_WIDTH), + .DEPTH(DEPTH) + ) u_fifo_push( + .wclk(wclk), + .wen(wen), + .rst_n(rst_W_n), + .rmode(rmode), + .wmode(wmode), + .gcout(pushtopop0), + .gcin(smux_poptopush), + .ff_waddr(waddr), + .pushflags(fflags[7:4]), + .upaf(upaf) + ); + fifo_pop #( + .ADDR_WIDTH(ADDR_WIDTH), + .FIFO_WIDTH(FIFO_WIDTH), + .DEPTH(DEPTH) + ) 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), + .popflags(fflags[3:0]), + .upae(upae) + ); +endmodule +module fifo_push ( + pushflags, + gcout, + ff_waddr, + rst_n, + wclk, + wen, + rmode, + wmode, + gcin, + upaf +); + parameter ADDR_WIDTH = 11; + parameter DEPTH = 6; + output wire [3:0] pushflags; + output wire [ADDR_WIDTH:0] gcout; + output wire [ADDR_WIDTH - 1:0] ff_waddr; + input rst_n; + (* clkbuf_sink *) + input wclk; + input wen; + input [1:0] rmode; + input [1:0] wmode; + input [ADDR_WIDTH:0] gcin; + input [ADDR_WIDTH - 1:0] upaf; + localparam ADDR_PLUS_ONE = ADDR_WIDTH + 1; + 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; + wire [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); + assign fbytes = 1 << (DEPTH + 5); + always @(*) begin + paf_thresh = wmode[1] ? upaf : (wmode[0] ? upaf << 1 : 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 < {1'b0, paf_thresh}; + q2 = count < {1'b0, paf_thresh}; + case (wmode) + 2'h0: + case (DEPTH) + 3'h6: 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'h5: 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'h4: 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'h2: 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'h1: 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'h0: 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[ADDR_WIDTH - 1: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'h6: 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'h5: 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'h4: 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'h2: 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'h1: 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'h0: 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[ADDR_WIDTH], 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'h6: 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'h5: 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'h4: 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'h2: 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'h1: 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'h0: 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 = {ADDR_PLUS_ONE {1'b0}}; + endcase + else + gcout_next = {ADDR_PLUS_ONE {1'b0}}; + always @(posedge wclk or negedge rst_n) + if (~rst_n) begin + full <= 1'b0; + fmo <= 1'b0; + paf <= 1'b0; + raddr <= {ADDR_PLUS_ONE {1'b0}}; + end + else begin + full <= full_next; + fmo <= fmo_next; + paf <= paf_next; + case (gmode) + 0: raddr <= raddr_next & {{ADDR_WIDTH - 1 {1'b1}}, 2'b00}; + 1: raddr <= raddr_next & {{ADDR_WIDTH {1'b1}}, 1'b0}; + 2: raddr <= raddr_next & {ADDR_WIDTH + 1 {1'b1}}; + 3: raddr <= 12'h000; + endcase + end + assign overflow_next = full & wen; + always @(posedge wclk or negedge rst_n) + if (~rst_n) + overflow <= 1'b0; + else if (wen == 1'b1) + overflow <= overflow_next; + always @(posedge wclk or negedge rst_n) + if (~rst_n) begin + waddr <= {ADDR_WIDTH + 1 {1'b0}}; + gcout_reg <= {ADDR_WIDTH + 1 {1'b0}}; + end + else if (wen == 1'b1) begin + waddr <= waddr_next; + gcout_reg <= 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 = {full, fmo, paf, overflow}; + 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, + upae +); + parameter ADDR_WIDTH = 11; + parameter FIFO_WIDTH = 3'd2; + parameter DEPTH = 6; + 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; + (* clkbuf_sink *) + input rclk; + input ren_in; + input [1:0] rmode; + input [1:0] wmode; + input [ADDR_WIDTH:0] gcin; + input [ADDR_WIDTH - 1:0] upae; + localparam ADDR_PLUS_ONE = ADDR_WIDTH + 1; + 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_PLUS_ONE:0] next_count; + wire [ADDR_PLUS_ONE:0] count; + wire [ADDR_PLUS_ONE:0] fbytes; + genvar i; + assign next_count = waddr - raddr_next; + assign count = waddr - raddr; + assign fbytes = 1 << (DEPTH + 5); + always @(*) pae_thresh = rmode[1] ? upae : (rmode[0] ? upae << 1 : 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 < {1'b0, pae_thresh}; + q2 = count < {1'b0, 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'b1; + pae <= 1'b1; + epo <= 1'b0; + end + else begin + empty <= empty_next; + pae <= pae_next; + epo <= 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 <= 12'h000; + else + waddr <= waddr_next; + always @(posedge rclk or negedge rst_n) + if (~rst_n) begin + underflow <= 1'b0; + bwl_sel <= 2'h0; + gcout_reg <= 12'h000; + end + else if (ren_in) begin + underflow <= empty; + if (!empty) begin + bwl_sel <= raddr_next[1:0]; + gcout_reg <= 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[ADDR_WIDTH - 2:0], 2'b00} & {{ADDR_WIDTH - 1 {1'b1}}, 2'b00}; + 2'h1: waddr_next = {tmp[ADDR_WIDTH - 1:0], 1'b0} & {{ADDR_WIDTH {1'b1}}, 1'b0}; + 2'h2: waddr_next = {tmp[ADDR_WIDTH:0]} & {ADDR_PLUS_ONE {1'b1}}; + default: waddr_next = {ADDR_PLUS_ONE {1'b0}}; + 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'sb0; + else if (empty & ~empty_next) + ff_raddr <= raddr_next[ADDR_WIDTH - 1:0]; + else if ((ren_in & !empty) & ~empty_next) + ff_raddr <= ff_raddr_next; + always @(posedge rclk or negedge rst_n) + if (~rst_n) + raddr <= 12'h000; + else if (ren_in & !empty) + raddr <= raddr_next; + always @(*) + case (FIFO_WIDTH) + 3'h2: out_raddr = {ff_raddr[ADDR_WIDTH - 1:1], bwl_sel[0]}; + 3'h4: out_raddr = {ff_raddr[ADDR_WIDTH - 1:2], bwl_sel}; + default: out_raddr = ff_raddr[ADDR_WIDTH - 1:0]; + endcase + assign ren_o = ren_out; + assign gcout = gcout_reg; + assign popflags = {empty, epo, pae, underflow}; +endmodule +`default_nettype none diff --git a/tests/arch/quicklogic/qlf_k6n10f/bram_tdp.v b/tests/arch/quicklogic/qlf_k6n10f/bram_tdp.v new file mode 100644 index 000000000..536cce992 --- /dev/null +++ b/tests/arch/quicklogic/qlf_k6n10f/bram_tdp.v @@ -0,0 +1,77 @@ +// Copyright 2020-2022 F4PGA Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +module BRAM_TDP #(parameter AWIDTH = 10, +parameter DWIDTH = 36)( + clk_a, + rce_a, + ra_a, + rq_a, + wce_a, + wa_a, + wd_a, + + clk_b, + rce_b, + ra_b, + rq_b, + wce_b, + wa_b, + wd_b +); + + input clk_a; + input rce_a; + input [AWIDTH-1:0] ra_a; + output reg [DWIDTH-1:0] rq_a; + input wce_a; + input [AWIDTH-1:0] wa_a; + input [DWIDTH-1:0] wd_a; + + input clk_b; + input rce_b; + input [AWIDTH-1:0] ra_b; + output reg [DWIDTH-1:0] rq_b; + input wce_b; + input [AWIDTH-1:0] wa_b; + input [DWIDTH-1:0] wd_b; + + (* no_rw_check = 1 *) + reg [DWIDTH-1:0] memory[0:(1< 0) begin + if($past(rce_a)) + assert(rq_a == rq_a_expected[i]); + if($past(rce_b)) + assert(rq_b == rq_b_expected[i]); + end + i <= i + 1; + end +end +endmodule \ No newline at end of file