diff --git a/rtl/dma_if_mux.v b/rtl/dma_if_mux.v index 85caeaac3..9d2382624 100644 --- a/rtl/dma_if_mux.v +++ b/rtl/dma_if_mux.v @@ -143,6 +143,7 @@ module dma_if_mux # input wire [SEG_COUNT*SEG_DATA_WIDTH-1:0] if_ram_wr_cmd_data, input wire [SEG_COUNT-1:0] if_ram_wr_cmd_valid, output wire [SEG_COUNT-1:0] if_ram_wr_cmd_ready, + output wire [SEG_COUNT-1:0] if_ram_wr_done, input wire [SEG_COUNT*M_RAM_SEL_WIDTH-1:0] if_ram_rd_cmd_sel, input wire [SEG_COUNT*SEG_ADDR_WIDTH-1:0] if_ram_rd_cmd_addr, input wire [SEG_COUNT-1:0] if_ram_rd_cmd_valid, @@ -160,6 +161,7 @@ module dma_if_mux # output wire [PORTS*SEG_COUNT*SEG_DATA_WIDTH-1:0] ram_wr_cmd_data, output wire [PORTS*SEG_COUNT-1:0] ram_wr_cmd_valid, input wire [PORTS*SEG_COUNT-1:0] ram_wr_cmd_ready, + input wire [PORTS*SEG_COUNT-1:0] ram_wr_done, output wire [PORTS*SEG_COUNT*S_RAM_SEL_WIDTH-1:0] ram_rd_cmd_sel, output wire [PORTS*SEG_COUNT*SEG_ADDR_WIDTH-1:0] ram_rd_cmd_addr, output wire [PORTS*SEG_COUNT-1:0] ram_rd_cmd_valid, @@ -232,6 +234,7 @@ dma_if_mux_rd_inst ( .if_ram_wr_cmd_data(if_ram_wr_cmd_data), .if_ram_wr_cmd_valid(if_ram_wr_cmd_valid), .if_ram_wr_cmd_ready(if_ram_wr_cmd_ready), + .if_ram_wr_done(if_ram_wr_done), /* * RAM interface @@ -241,7 +244,8 @@ dma_if_mux_rd_inst ( .ram_wr_cmd_addr(ram_wr_cmd_addr), .ram_wr_cmd_data(ram_wr_cmd_data), .ram_wr_cmd_valid(ram_wr_cmd_valid), - .ram_wr_cmd_ready(ram_wr_cmd_ready) + .ram_wr_cmd_ready(ram_wr_cmd_ready), + .ram_wr_done(ram_wr_done) ); dma_if_mux_wr #( diff --git a/rtl/dma_if_mux_rd.v b/rtl/dma_if_mux_rd.v index ae5a565dc..98f13a56d 100644 --- a/rtl/dma_if_mux_rd.v +++ b/rtl/dma_if_mux_rd.v @@ -109,6 +109,7 @@ module dma_if_mux_rd # input wire [SEG_COUNT*SEG_DATA_WIDTH-1:0] if_ram_wr_cmd_data, input wire [SEG_COUNT-1:0] if_ram_wr_cmd_valid, output wire [SEG_COUNT-1:0] if_ram_wr_cmd_ready, + output wire [SEG_COUNT-1:0] if_ram_wr_done, /* * RAM interface @@ -118,13 +119,16 @@ module dma_if_mux_rd # output wire [PORTS*SEG_COUNT*SEG_ADDR_WIDTH-1:0] ram_wr_cmd_addr, output wire [PORTS*SEG_COUNT*SEG_DATA_WIDTH-1:0] ram_wr_cmd_data, output wire [PORTS*SEG_COUNT-1:0] ram_wr_cmd_valid, - input wire [PORTS*SEG_COUNT-1:0] ram_wr_cmd_ready + input wire [PORTS*SEG_COUNT-1:0] ram_wr_cmd_ready, + input wire [PORTS*SEG_COUNT-1:0] ram_wr_done ); parameter CL_PORTS = $clog2(PORTS); parameter S_RAM_SEL_WIDTH_INT = S_RAM_SEL_WIDTH > 0 ? S_RAM_SEL_WIDTH : 1; +parameter FIFO_ADDR_WIDTH = 5; + // check configuration initial begin if (M_TAG_WIDTH < S_TAG_WIDTH+$clog2(PORTS)) begin @@ -321,6 +325,22 @@ genvar n, p; for (n = 0; n < SEG_COUNT; n = n + 1) begin + // FIFO to maintain response ordering + reg [FIFO_ADDR_WIDTH+1-1:0] fifo_wr_ptr_reg = 0; + reg [FIFO_ADDR_WIDTH+1-1:0] fifo_rd_ptr_reg = 0; + reg [CL_PORTS-1:0] fifo_sel[(2**FIFO_ADDR_WIDTH)-1:0]; + + wire fifo_empty = fifo_wr_ptr_reg == fifo_rd_ptr_reg; + wire fifo_full = fifo_wr_ptr_reg == (fifo_rd_ptr_reg ^ (1 << FIFO_ADDR_WIDTH)); + + integer i; + + initial begin + for (i = 0; i < 2**FIFO_ADDR_WIDTH; i = i + 1) begin + fifo_sel[i] = 0; + end + end + // RAM write command demux wire [M_RAM_SEL_WIDTH-1:0] seg_if_ram_wr_cmd_sel = if_ram_wr_cmd_sel[M_RAM_SEL_WIDTH*n +: M_RAM_SEL_WIDTH]; @@ -357,16 +377,27 @@ for (n = 0; n < SEG_COUNT; n = n + 1) begin reg seg_ram_wr_cmd_ready_int_reg = 1'b0; wire seg_ram_wr_cmd_ready_int_early; - assign seg_if_ram_wr_cmd_ready = seg_ram_wr_cmd_ready_int_reg; + assign seg_if_ram_wr_cmd_ready = seg_ram_wr_cmd_ready_int_reg && !fifo_full; - wire [CL_PORTS-1:0] select = PORTS > 1 ? (seg_if_ram_wr_cmd_sel >> (M_RAM_SEL_WIDTH - CL_PORTS)) : 0; + wire [CL_PORTS-1:0] select_cmd = PORTS > 1 ? (seg_if_ram_wr_cmd_sel >> (M_RAM_SEL_WIDTH - CL_PORTS)) : 0; always @* begin seg_ram_wr_cmd_sel_int = seg_if_ram_wr_cmd_sel; seg_ram_wr_cmd_be_int = seg_if_ram_wr_cmd_be; seg_ram_wr_cmd_addr_int = seg_if_ram_wr_cmd_addr; seg_ram_wr_cmd_data_int = seg_if_ram_wr_cmd_data; - seg_ram_wr_cmd_valid_int = (seg_if_ram_wr_cmd_valid && seg_if_ram_wr_cmd_ready) << select; + seg_ram_wr_cmd_valid_int = (seg_if_ram_wr_cmd_valid && seg_if_ram_wr_cmd_ready) << select_cmd; + end + + always @(posedge clk) begin + if (seg_if_ram_wr_cmd_valid && seg_if_ram_wr_cmd_ready) begin + fifo_sel[fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= select_cmd; + fifo_wr_ptr_reg <= fifo_wr_ptr_reg + 1; + end + + if (rst) begin + fifo_wr_ptr_reg <= 0; + end end // output datapath logic @@ -456,6 +487,58 @@ for (n = 0; n < SEG_COUNT; n = n + 1) begin end end + // RAM write done mux + + wire [PORTS-1:0] seg_ram_wr_done; + wire [PORTS-1:0] seg_ram_wr_done_sel; + wire seg_if_ram_wr_done; + + for (p = 0; p < PORTS; p = p + 1) begin + assign seg_ram_wr_done[p] = ram_wr_done[p*SEG_COUNT+n]; + end + + assign if_ram_wr_done[n] = seg_if_ram_wr_done; + + wire [CL_PORTS-1:0] select_resp = fifo_sel[fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]]; + + for (p = 0; p < PORTS; p = p + 1) begin + reg [FIFO_ADDR_WIDTH+1-1:0] done_count_reg = 0; + reg done_reg = 1'b0; + + assign seg_ram_wr_done_sel[p] = done_reg; + + always @(posedge clk) begin + if (select_resp == p && (done_count_reg != 0 || seg_ram_wr_done[p])) begin + done_reg <= 1'b1; + if (!seg_ram_wr_done[p]) begin + done_count_reg <= done_count_reg - 1; + end + end else begin + done_reg <= 1'b0; + if (seg_ram_wr_done[p]) begin + done_count_reg <= done_count_reg + 1; + end + end + + if (rst) begin + done_count_reg <= 0; + done_reg <= 1'b0; + end + end + end + + assign seg_if_ram_wr_done = seg_ram_wr_done_sel != 0; + + always @(posedge clk) begin + if (seg_if_ram_wr_done && !fifo_empty) begin + fifo_rd_ptr_reg <= fifo_rd_ptr_reg + 1; + end + + if (rst) begin + fifo_rd_ptr_reg <= 0; + end + end + end endgenerate