1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00
corundum/rtl/pcie_tlp_fifo_raw.v

837 lines
38 KiB
Coq
Raw Normal View History

/*
Copyright (c) 2022 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* PCIe TLP FIFO (raw output)
*/
module pcie_tlp_fifo_raw #
(
// FIFO depth
parameter DEPTH = 2048,
// TLP data width
parameter TLP_DATA_WIDTH = 256,
// TLP strobe width (input)
parameter TLP_STRB_WIDTH = TLP_DATA_WIDTH/32,
// TLP header width
parameter TLP_HDR_WIDTH = 128,
// Sequence number width
parameter SEQ_NUM_WIDTH = 6,
// TLP segment count (input)
parameter IN_TLP_SEG_COUNT = 1,
// TLP segment count (output)
parameter OUT_TLP_SEG_COUNT = 1,
// Segment select width
parameter SEG_SEL_WIDTH = $clog2(OUT_TLP_SEG_COUNT),
// Watermark level
parameter WATERMARK = DEPTH/2,
// Use control output
parameter CTRL_OUT_EN = 0
)
(
input wire clk,
input wire rst,
/*
* TLP input
*/
input wire [TLP_DATA_WIDTH-1:0] in_tlp_data,
input wire [TLP_STRB_WIDTH-1:0] in_tlp_strb,
input wire [IN_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] in_tlp_hdr,
input wire [IN_TLP_SEG_COUNT*SEQ_NUM_WIDTH-1:0] in_tlp_seq,
input wire [IN_TLP_SEG_COUNT*3-1:0] in_tlp_bar_id,
input wire [IN_TLP_SEG_COUNT*8-1:0] in_tlp_func_num,
input wire [IN_TLP_SEG_COUNT*4-1:0] in_tlp_error,
input wire [IN_TLP_SEG_COUNT-1:0] in_tlp_valid,
input wire [IN_TLP_SEG_COUNT-1:0] in_tlp_sop,
input wire [IN_TLP_SEG_COUNT-1:0] in_tlp_eop,
output wire in_tlp_ready,
/*
* TLP output
*/
output wire [TLP_DATA_WIDTH-1:0] out_tlp_data,
output wire [TLP_STRB_WIDTH-1:0] out_tlp_strb,
output wire [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] out_tlp_hdr,
output wire [OUT_TLP_SEG_COUNT*SEQ_NUM_WIDTH-1:0] out_tlp_seq,
output wire [OUT_TLP_SEG_COUNT*3-1:0] out_tlp_bar_id,
output wire [OUT_TLP_SEG_COUNT*8-1:0] out_tlp_func_num,
output wire [OUT_TLP_SEG_COUNT*4-1:0] out_tlp_error,
output wire [OUT_TLP_SEG_COUNT-1:0] out_tlp_valid,
output wire [OUT_TLP_SEG_COUNT-1:0] out_tlp_sop,
output wire [OUT_TLP_SEG_COUNT-1:0] out_tlp_eop,
output wire [SEG_SEL_WIDTH-1:0] out_seg_offset,
output wire [SEG_SEL_WIDTH+1-1:0] out_seg_count,
input wire out_read_en,
input wire [SEG_SEL_WIDTH+1-1:0] out_read_seg_count,
output wire [TLP_STRB_WIDTH-1:0] out_ctrl_tlp_strb,
output wire [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] out_ctrl_tlp_hdr,
output wire [OUT_TLP_SEG_COUNT-1:0] out_ctrl_tlp_valid,
output wire [OUT_TLP_SEG_COUNT-1:0] out_ctrl_tlp_sop,
output wire [OUT_TLP_SEG_COUNT-1:0] out_ctrl_tlp_eop,
output wire [SEG_SEL_WIDTH-1:0] out_ctrl_seg_offset,
output wire [SEG_SEL_WIDTH+1-1:0] out_ctrl_seg_count,
input wire out_ctrl_read_en,
input wire [SEG_SEL_WIDTH+1-1:0] out_ctrl_read_seg_count,
/*
* Status
*/
output wire half_full,
output wire watermark
);
parameter IN_TLP_SEG_DATA_WIDTH = TLP_DATA_WIDTH / IN_TLP_SEG_COUNT;
parameter IN_TLP_SEG_STRB_WIDTH = TLP_STRB_WIDTH / IN_TLP_SEG_COUNT;
parameter OUT_TLP_SEG_DATA_WIDTH = TLP_DATA_WIDTH / OUT_TLP_SEG_COUNT;
parameter OUT_TLP_SEG_STRB_WIDTH = TLP_STRB_WIDTH / OUT_TLP_SEG_COUNT;
parameter SEG_RATIO = OUT_TLP_SEG_COUNT / IN_TLP_SEG_COUNT;
parameter ADDR_WIDTH = $clog2(DEPTH/TLP_STRB_WIDTH);
parameter PTR_WIDTH = ADDR_WIDTH+SEG_SEL_WIDTH;
// check configuration
initial begin
if (OUT_TLP_SEG_COUNT < IN_TLP_SEG_COUNT) begin
$error("Error: Output segment count must be not be less than input segment count (instance %m)");
$finish;
end
if (TLP_HDR_WIDTH != 128) begin
$error("Error: TLP segment header width must be 128 (instance %m)");
$finish;
end
if (TLP_STRB_WIDTH*32 != TLP_DATA_WIDTH) begin
$error("Error: PCIe interface requires dword (32-bit) granularity (instance %m)");
$finish;
end
end
reg [PTR_WIDTH:0] wr_ptr_reg = 0, wr_ptr_next;
reg [PTR_WIDTH:0] wr_ptr_cur_reg = 0, wr_ptr_cur_next;
reg [PTR_WIDTH:0] rd_ptr_reg = 0, rd_ptr_next;
reg [PTR_WIDTH:0] rd_ptr_ctrl_reg = 0, rd_ptr_ctrl_next;
reg [OUT_TLP_SEG_COUNT-1:0] mem_rd_data_valid_reg = 0, mem_rd_data_valid_next;
reg [OUT_TLP_SEG_COUNT-1:0] ctrl_mem_rd_data_valid_reg = 0, ctrl_mem_rd_data_valid_next;
reg [TLP_DATA_WIDTH-1:0] int_tlp_data;
reg [TLP_STRB_WIDTH-1:0] int_tlp_strb;
reg [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] int_tlp_hdr;
reg [OUT_TLP_SEG_COUNT*SEQ_NUM_WIDTH-1:0] int_tlp_seq;
reg [OUT_TLP_SEG_COUNT*3-1:0] int_tlp_bar_id;
reg [OUT_TLP_SEG_COUNT*8-1:0] int_tlp_func_num;
reg [OUT_TLP_SEG_COUNT*4-1:0] int_tlp_error;
reg [OUT_TLP_SEG_COUNT-1:0] int_tlp_valid;
reg [OUT_TLP_SEG_COUNT-1:0] int_tlp_sop;
reg [OUT_TLP_SEG_COUNT-1:0] int_tlp_eop;
reg [TLP_DATA_WIDTH-1:0] seg_mem_wr_data;
reg [TLP_STRB_WIDTH-1:0] seg_mem_wr_strb;
reg [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] seg_mem_wr_hdr;
reg [OUT_TLP_SEG_COUNT*SEQ_NUM_WIDTH-1:0] seg_mem_wr_seq;
reg [OUT_TLP_SEG_COUNT*3-1:0] seg_mem_wr_bar_id;
reg [OUT_TLP_SEG_COUNT*8-1:0] seg_mem_wr_func_num;
reg [OUT_TLP_SEG_COUNT*4-1:0] seg_mem_wr_error;
reg [OUT_TLP_SEG_COUNT*1-1:0] seg_mem_wr_valid;
reg [OUT_TLP_SEG_COUNT*1-1:0] seg_mem_wr_sop;
reg [OUT_TLP_SEG_COUNT*1-1:0] seg_mem_wr_eop;
reg [OUT_TLP_SEG_COUNT*ADDR_WIDTH-1:0] seg_mem_wr_addr_reg = 0, seg_mem_wr_addr_next;
reg [OUT_TLP_SEG_COUNT-1:0] seg_mem_wr_en;
reg [OUT_TLP_SEG_COUNT*SEG_SEL_WIDTH-1:0] seg_mem_wr_sel;
wire [TLP_DATA_WIDTH-1:0] seg_mem_rd_data;
wire [TLP_STRB_WIDTH-1:0] seg_mem_rd_strb;
wire [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] seg_mem_rd_hdr;
wire [OUT_TLP_SEG_COUNT*SEQ_NUM_WIDTH-1:0] seg_mem_rd_seq;
wire [OUT_TLP_SEG_COUNT*3-1:0] seg_mem_rd_bar_id;
wire [OUT_TLP_SEG_COUNT*8-1:0] seg_mem_rd_func_num;
wire [OUT_TLP_SEG_COUNT*4-1:0] seg_mem_rd_error;
wire [OUT_TLP_SEG_COUNT*1-1:0] seg_mem_rd_sop;
wire [OUT_TLP_SEG_COUNT*1-1:0] seg_mem_rd_eop;
reg [OUT_TLP_SEG_COUNT*ADDR_WIDTH-1:0] seg_mem_rd_addr_reg = 0, seg_mem_rd_addr_next;
reg [OUT_TLP_SEG_COUNT-1:0] seg_mem_rd_en;
wire [TLP_STRB_WIDTH-1:0] seg_ctrl_mem_rd_strb;
wire [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] seg_ctrl_mem_rd_hdr;
wire [OUT_TLP_SEG_COUNT*1-1:0] seg_ctrl_mem_rd_sop;
wire [OUT_TLP_SEG_COUNT*1-1:0] seg_ctrl_mem_rd_eop;
reg [OUT_TLP_SEG_COUNT*ADDR_WIDTH-1:0] seg_ctrl_mem_rd_addr_reg = 0, seg_ctrl_mem_rd_addr_next;
reg [OUT_TLP_SEG_COUNT-1:0] seg_ctrl_mem_rd_en;
reg full_cur_reg = 1'b0;
reg half_full_reg = 1'b0;
reg watermark_reg = 1'b0;
reg [PTR_WIDTH:0] count_reg = 0;
reg full_cur_ctrl_reg = 1'b0;
reg half_full_ctrl_reg = 1'b0;
reg watermark_ctrl_reg = 1'b0;
reg [PTR_WIDTH:0] count_ctrl_reg = 0;
reg [TLP_DATA_WIDTH-1:0] out_tlp_data_reg = 0, out_tlp_data_next;
reg [TLP_STRB_WIDTH-1:0] out_tlp_strb_reg = 0, out_tlp_strb_next;
reg [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] out_tlp_hdr_reg = 0, out_tlp_hdr_next;
reg [OUT_TLP_SEG_COUNT*SEQ_NUM_WIDTH-1:0] out_tlp_seq_reg = 0, out_tlp_seq_next;
reg [OUT_TLP_SEG_COUNT*3-1:0] out_tlp_bar_id_reg = 0, out_tlp_bar_id_next;
reg [OUT_TLP_SEG_COUNT*8-1:0] out_tlp_func_num_reg = 0, out_tlp_func_num_next;
reg [OUT_TLP_SEG_COUNT*4-1:0] out_tlp_error_reg = 0, out_tlp_error_next;
reg [OUT_TLP_SEG_COUNT-1:0] out_tlp_valid_reg = 0, out_tlp_valid_next;
reg [OUT_TLP_SEG_COUNT-1:0] out_tlp_sop_reg = 0, out_tlp_sop_next;
reg [OUT_TLP_SEG_COUNT-1:0] out_tlp_eop_reg = 0, out_tlp_eop_next;
reg [SEG_SEL_WIDTH-1:0] out_seg_offset_reg = 0, out_seg_offset_next;
reg [SEG_SEL_WIDTH+1-1:0] out_seg_count_reg = 0, out_seg_count_next;
reg [TLP_STRB_WIDTH-1:0] out_ctrl_tlp_strb_reg = 0, out_ctrl_tlp_strb_next;
reg [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] out_ctrl_tlp_hdr_reg = 0, out_ctrl_tlp_hdr_next;
reg [OUT_TLP_SEG_COUNT-1:0] out_ctrl_tlp_valid_reg = 0, out_ctrl_tlp_valid_next;
reg [OUT_TLP_SEG_COUNT-1:0] out_ctrl_tlp_sop_reg = 0, out_ctrl_tlp_sop_next;
reg [OUT_TLP_SEG_COUNT-1:0] out_ctrl_tlp_eop_reg = 0, out_ctrl_tlp_eop_next;
reg [SEG_SEL_WIDTH-1:0] out_ctrl_seg_offset_reg = 0, out_ctrl_seg_offset_next;
reg [SEG_SEL_WIDTH+1-1:0] out_ctrl_seg_count_reg = 0, out_ctrl_seg_count_next;
reg [OUT_TLP_SEG_COUNT-1:0] out_ctrl_tlp_ready_int_reg = 0, out_ctrl_tlp_ready_int_next;
reg [TLP_STRB_WIDTH-1:0] temp_out_ctrl_tlp_strb_reg = 0, temp_out_ctrl_tlp_strb_next;
reg [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] temp_out_ctrl_tlp_hdr_reg = 0, temp_out_ctrl_tlp_hdr_next;
reg [OUT_TLP_SEG_COUNT-1:0] temp_out_ctrl_tlp_valid_reg = 0, temp_out_ctrl_tlp_valid_next;
reg [OUT_TLP_SEG_COUNT-1:0] temp_out_ctrl_tlp_sop_reg = 0, temp_out_ctrl_tlp_sop_next;
reg [OUT_TLP_SEG_COUNT-1:0] temp_out_ctrl_tlp_eop_reg = 0, temp_out_ctrl_tlp_eop_next;
reg [TLP_STRB_WIDTH-1:0] pipe_out_ctrl_tlp_strb_reg = 0, pipe_out_ctrl_tlp_strb_next;
reg [OUT_TLP_SEG_COUNT*TLP_HDR_WIDTH-1:0] pipe_out_ctrl_tlp_hdr_reg = 0, pipe_out_ctrl_tlp_hdr_next;
reg [OUT_TLP_SEG_COUNT-1:0] pipe_out_ctrl_tlp_valid_reg = 0, pipe_out_ctrl_tlp_valid_next;
reg [OUT_TLP_SEG_COUNT-1:0] pipe_out_ctrl_tlp_sop_reg = 0, pipe_out_ctrl_tlp_sop_next;
reg [OUT_TLP_SEG_COUNT-1:0] pipe_out_ctrl_tlp_eop_reg = 0, pipe_out_ctrl_tlp_eop_next;
assign in_tlp_ready = !(full_cur_reg | (CTRL_OUT_EN ? full_cur_ctrl_reg : 0));
assign out_tlp_data = out_tlp_data_reg;
assign out_tlp_strb = out_tlp_strb_reg;
assign out_tlp_hdr = out_tlp_hdr_reg;
assign out_tlp_seq = out_tlp_seq_reg;
assign out_tlp_bar_id = out_tlp_bar_id_reg;
assign out_tlp_func_num = out_tlp_func_num_reg;
assign out_tlp_error = out_tlp_error_reg;
assign out_tlp_valid = out_tlp_valid_reg;
assign out_tlp_sop = out_tlp_sop_reg;
assign out_tlp_eop = out_tlp_eop_reg;
assign out_seg_offset = out_seg_offset_reg;
assign out_seg_count = out_seg_count_reg;
assign out_ctrl_tlp_strb = out_ctrl_tlp_strb_reg;
assign out_ctrl_tlp_hdr = out_ctrl_tlp_hdr_reg;
assign out_ctrl_tlp_valid = out_ctrl_tlp_valid_reg;
assign out_ctrl_tlp_sop = out_ctrl_tlp_sop_reg;
assign out_ctrl_tlp_eop = out_ctrl_tlp_eop_reg;
assign out_ctrl_seg_offset = out_ctrl_seg_offset_reg;
assign out_ctrl_seg_count = out_ctrl_seg_count_reg;
assign half_full = half_full_reg | (CTRL_OUT_EN ? half_full_ctrl_reg : 0);
assign watermark = watermark_reg | (CTRL_OUT_EN ? watermark_ctrl_reg : 0);
generate
genvar n;
for (n = 0; n < OUT_TLP_SEG_COUNT; n = n + 1) begin : seg_ram
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg [OUT_TLP_SEG_DATA_WIDTH-1:0] seg_mem_data[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg [OUT_TLP_SEG_STRB_WIDTH-1:0] seg_mem_strb[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg [TLP_HDR_WIDTH-1:0] seg_mem_hdr[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg [SEQ_NUM_WIDTH-1:0] seg_mem_seq[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg [2:0] seg_mem_bar_id[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg [7:0] seg_mem_func_num[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg [3:0] seg_mem_error[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg seg_mem_sop[2**ADDR_WIDTH-1:0];
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
reg seg_mem_eop[2**ADDR_WIDTH-1:0];
wire wr_en = seg_mem_wr_en[n];
wire [ADDR_WIDTH-1:0] wr_addr = seg_mem_wr_addr_reg[n*ADDR_WIDTH +: ADDR_WIDTH];
wire [OUT_TLP_SEG_DATA_WIDTH-1:0] wr_data = seg_mem_wr_data[n*OUT_TLP_SEG_DATA_WIDTH +: OUT_TLP_SEG_DATA_WIDTH];
wire [OUT_TLP_SEG_STRB_WIDTH-1:0] wr_strb = seg_mem_wr_strb[n*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH];
wire [TLP_HDR_WIDTH-1:0] wr_hdr = seg_mem_wr_hdr[n*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
wire [SEQ_NUM_WIDTH-1:0] wr_seq = seg_mem_wr_seq[n*SEQ_NUM_WIDTH +: SEQ_NUM_WIDTH];
wire [2:0] wr_bar_id = seg_mem_wr_bar_id[n*3 +: 3];
wire [7:0] wr_func_num = seg_mem_wr_func_num[n*8 +: 8];
wire [3:0] wr_error = seg_mem_wr_error[n*4 +: 4];
wire wr_sop = seg_mem_wr_sop[n*1 +: 1];
wire wr_eop = seg_mem_wr_eop[n*1 +: 1];
wire rd_en = seg_mem_rd_en[n];
wire [ADDR_WIDTH-1:0] rd_addr = seg_mem_rd_addr_reg[n*ADDR_WIDTH +: ADDR_WIDTH];
reg [OUT_TLP_SEG_DATA_WIDTH-1:0] rd_data_reg = 0;
reg [OUT_TLP_SEG_STRB_WIDTH-1:0] rd_strb_reg = 0;
reg [TLP_HDR_WIDTH-1:0] rd_hdr_reg = 0;
reg [SEQ_NUM_WIDTH-1:0] rd_seq_reg = 0;
reg [2:0] rd_bar_id_reg = 0;
reg [7:0] rd_func_num_reg = 0;
reg [3:0] rd_error_reg = 0;
reg rd_sop_reg = 0;
reg rd_eop_reg = 0;
assign seg_mem_rd_data[n*OUT_TLP_SEG_DATA_WIDTH +: OUT_TLP_SEG_DATA_WIDTH] = rd_data_reg;
assign seg_mem_rd_strb[n*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = rd_strb_reg;
assign seg_mem_rd_hdr[n*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = rd_hdr_reg;
assign seg_mem_rd_seq[n*SEQ_NUM_WIDTH +: SEQ_NUM_WIDTH] = rd_seq_reg;
assign seg_mem_rd_bar_id[n*3 +: 3] = rd_bar_id_reg;
assign seg_mem_rd_func_num[n*8 +: 8] = rd_func_num_reg;
assign seg_mem_rd_error[n*4 +: 4] = rd_error_reg;
assign seg_mem_rd_sop[n*1 +: 1] = rd_sop_reg;
assign seg_mem_rd_eop[n*1 +: 1] = rd_eop_reg;
always @(posedge clk) begin
if (wr_en) begin
seg_mem_data[wr_addr] <= wr_data;
seg_mem_strb[wr_addr] <= wr_strb;
seg_mem_hdr[wr_addr] <= wr_hdr;
seg_mem_seq[wr_addr] <= wr_seq;
seg_mem_bar_id[wr_addr] <= wr_bar_id;
seg_mem_func_num[wr_addr] <= wr_func_num;
seg_mem_error[wr_addr] <= wr_error;
seg_mem_sop[wr_addr] <= wr_sop;
seg_mem_eop[wr_addr] <= wr_eop;
end
end
always @(posedge clk) begin
if (rd_en) begin
rd_data_reg <= seg_mem_data[rd_addr];
rd_strb_reg <= seg_mem_strb[rd_addr];
rd_hdr_reg <= seg_mem_hdr[rd_addr];
rd_seq_reg <= seg_mem_seq[rd_addr];
rd_bar_id_reg <= seg_mem_bar_id[rd_addr];
rd_func_num_reg <= seg_mem_func_num[rd_addr];
rd_error_reg <= seg_mem_error[rd_addr];
rd_sop_reg <= seg_mem_sop[rd_addr];
rd_eop_reg <= seg_mem_eop[rd_addr];
end
end
if (CTRL_OUT_EN) begin
wire ctrl_rd_en = seg_ctrl_mem_rd_en[n];
wire [ADDR_WIDTH-1:0] ctrl_rd_addr = seg_ctrl_mem_rd_addr_reg[n*ADDR_WIDTH +: ADDR_WIDTH];
reg [OUT_TLP_SEG_STRB_WIDTH-1:0] ctrl_rd_strb_reg = 0;
reg [TLP_HDR_WIDTH-1:0] ctrl_rd_hdr_reg = 0;
reg ctrl_rd_sop_reg = 0;
reg ctrl_rd_eop_reg = 0;
assign seg_ctrl_mem_rd_strb[n*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = ctrl_rd_strb_reg;
assign seg_ctrl_mem_rd_hdr[n*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = ctrl_rd_hdr_reg;
assign seg_ctrl_mem_rd_sop[n*1 +: 1] = ctrl_rd_sop_reg;
assign seg_ctrl_mem_rd_eop[n*1 +: 1] = ctrl_rd_eop_reg;
always @(posedge clk) begin
if (ctrl_rd_en) begin
ctrl_rd_strb_reg <= seg_mem_strb[ctrl_rd_addr];
ctrl_rd_hdr_reg <= seg_mem_hdr[ctrl_rd_addr];
ctrl_rd_sop_reg <= seg_mem_sop[ctrl_rd_addr];
ctrl_rd_eop_reg <= seg_mem_eop[ctrl_rd_addr];
end
end
end
end
endgenerate
// limits
always @(posedge clk) begin
full_cur_reg <= $unsigned(wr_ptr_cur_reg - rd_ptr_reg) >= DEPTH/TLP_STRB_WIDTH*OUT_TLP_SEG_COUNT-OUT_TLP_SEG_COUNT*2;
half_full_reg <= $unsigned(wr_ptr_cur_reg - rd_ptr_reg) >= DEPTH/TLP_STRB_WIDTH*OUT_TLP_SEG_COUNT/2;
watermark_reg <= $unsigned(wr_ptr_cur_reg - rd_ptr_reg) >= WATERMARK/TLP_STRB_WIDTH*OUT_TLP_SEG_COUNT;
full_cur_ctrl_reg <= $unsigned(wr_ptr_cur_reg - rd_ptr_ctrl_reg) >= DEPTH/TLP_STRB_WIDTH*OUT_TLP_SEG_COUNT-OUT_TLP_SEG_COUNT*2;
half_full_ctrl_reg <= $unsigned(wr_ptr_cur_reg - rd_ptr_ctrl_reg) >= DEPTH/TLP_STRB_WIDTH*OUT_TLP_SEG_COUNT/2;
watermark_ctrl_reg <= $unsigned(wr_ptr_cur_reg - rd_ptr_ctrl_reg) >= WATERMARK/TLP_STRB_WIDTH*OUT_TLP_SEG_COUNT;
if (rst) begin
full_cur_reg <= 1'b0;
half_full_reg <= 1'b0;
watermark_reg <= 1'b0;
full_cur_ctrl_reg <= 1'b0;
half_full_ctrl_reg <= 1'b0;
watermark_ctrl_reg <= 1'b0;
end
end
// Split input segments
integer si, so;
always @* begin
int_tlp_data = in_tlp_data;
int_tlp_strb = in_tlp_strb;
if (IN_TLP_SEG_COUNT != OUT_TLP_SEG_COUNT) begin
for (si = 0; si < IN_TLP_SEG_COUNT; si = si + 1) begin
int_tlp_hdr[si*TLP_HDR_WIDTH*SEG_RATIO +: TLP_HDR_WIDTH*SEG_RATIO] = in_tlp_hdr[si*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
int_tlp_seq[si*SEQ_NUM_WIDTH*SEG_RATIO +: SEQ_NUM_WIDTH*SEG_RATIO] = in_tlp_seq[si*SEQ_NUM_WIDTH +: SEQ_NUM_WIDTH];
int_tlp_bar_id[si*3*SEG_RATIO +: 3*SEG_RATIO] = in_tlp_bar_id[si*3 +: 3];
int_tlp_func_num[si*8*SEG_RATIO +: 8*SEG_RATIO] = in_tlp_func_num[si*8 +: 8];
int_tlp_error[si*4*SEG_RATIO +: 4*SEG_RATIO] = in_tlp_error[si*4 +: 4];
int_tlp_valid[si*SEG_RATIO +: SEG_RATIO] = in_tlp_valid[si +: 1];
int_tlp_sop[si*SEG_RATIO +: SEG_RATIO] = in_tlp_sop[si +: 1];
int_tlp_eop[si*SEG_RATIO +: SEG_RATIO] = in_tlp_eop[si +: 1];
for (so = 0; so < SEG_RATIO; so = so + 1) begin
if (in_tlp_strb[si*IN_TLP_SEG_STRB_WIDTH+so*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH]) begin
int_tlp_valid[si*SEG_RATIO+so] = in_tlp_valid[si +: 1];
int_tlp_eop[si*SEG_RATIO +: SEG_RATIO] = in_tlp_eop[si +: 1] << so;
end
end
end
end else begin
int_tlp_hdr = in_tlp_hdr;
int_tlp_seq = in_tlp_seq;
int_tlp_bar_id = in_tlp_bar_id;
int_tlp_func_num = in_tlp_func_num;
int_tlp_error = in_tlp_error;
int_tlp_valid = in_tlp_valid;
int_tlp_sop = in_tlp_sop;
int_tlp_eop = in_tlp_eop;
end
end
// Write logic
integer seg;
reg [SEG_SEL_WIDTH+1-1:0] seg_count;
reg [SEG_SEL_WIDTH-1:0] cur_seg;
reg [SEG_SEL_WIDTH-1:0] eop_seg;
always @* begin
wr_ptr_next = wr_ptr_reg;
wr_ptr_cur_next = wr_ptr_cur_reg;
if (OUT_TLP_SEG_COUNT > 1) begin
// pack segments
seg_mem_wr_valid = 0;
seg_mem_wr_sel = 0;
cur_seg = wr_ptr_cur_reg[SEG_SEL_WIDTH-1:0];
eop_seg = 0;
seg_count = 0;
for (seg = 0; seg < OUT_TLP_SEG_COUNT; seg = seg + 1) begin
if (int_tlp_valid[seg]) begin
seg_mem_wr_valid[cur_seg +: 1] = 1'b1;
seg_mem_wr_sel[cur_seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH] = seg;
cur_seg = cur_seg + 1;
if (int_tlp_eop[seg]) begin
eop_seg = seg_count;
end
seg_count = seg_count + 1;
end
end
for (seg = 0; seg < OUT_TLP_SEG_COUNT; seg = seg + 1) begin
seg_mem_wr_data[seg*OUT_TLP_SEG_DATA_WIDTH +: OUT_TLP_SEG_DATA_WIDTH] = int_tlp_data[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH]*OUT_TLP_SEG_DATA_WIDTH +: OUT_TLP_SEG_DATA_WIDTH];
seg_mem_wr_strb[seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = int_tlp_strb[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH]*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH];
seg_mem_wr_hdr[seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = int_tlp_hdr[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH]*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
seg_mem_wr_seq[seg*SEQ_NUM_WIDTH +: SEQ_NUM_WIDTH] = int_tlp_seq[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH]*SEQ_NUM_WIDTH +: SEQ_NUM_WIDTH];
seg_mem_wr_bar_id[seg*3 +: 3] = int_tlp_bar_id[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH]*3 +: 3];
seg_mem_wr_func_num[seg*8 +: 8] = int_tlp_func_num[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH]*8 +: 8];
seg_mem_wr_error[seg*4 +: 4] = int_tlp_error[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH]*4 +: 4];
seg_mem_wr_sop[seg +: 1] = int_tlp_sop[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH] +: 1];
seg_mem_wr_eop[seg +: 1] = int_tlp_eop[seg_mem_wr_sel[seg*SEG_SEL_WIDTH +: SEG_SEL_WIDTH] +: 1];
end
end else begin
seg_mem_wr_data = in_tlp_data;
seg_mem_wr_strb = in_tlp_strb;
seg_mem_wr_hdr = in_tlp_hdr;
seg_mem_wr_seq = in_tlp_seq;
seg_mem_wr_bar_id = in_tlp_bar_id;
seg_mem_wr_func_num = in_tlp_func_num;
seg_mem_wr_error = in_tlp_error;
seg_mem_wr_sop = in_tlp_sop;
seg_mem_wr_eop = in_tlp_eop;
end
seg_mem_wr_addr_next = seg_mem_wr_addr_reg;
seg_mem_wr_en = 0;
if (in_tlp_ready && in_tlp_valid) begin
// transfer in
if (OUT_TLP_SEG_COUNT == 1) begin
seg_mem_wr_en = 1'b1;
wr_ptr_cur_next = wr_ptr_cur_reg + 1;
seg_mem_wr_addr_next = wr_ptr_cur_next;
if (in_tlp_eop) begin
// end of frame
wr_ptr_next = wr_ptr_cur_next;
end
end else begin
seg_mem_wr_en = seg_mem_wr_valid;
wr_ptr_cur_next = wr_ptr_cur_reg + seg_count;
for (seg = 0; seg < OUT_TLP_SEG_COUNT; seg = seg + 1) begin
seg_mem_wr_addr_next[seg*ADDR_WIDTH +: ADDR_WIDTH] = (wr_ptr_cur_next + (OUT_TLP_SEG_COUNT-1 - seg)) >> SEG_SEL_WIDTH;
end
if (in_tlp_eop & in_tlp_valid) begin
// end of frame
if (IN_TLP_SEG_COUNT > 1) begin
wr_ptr_next = wr_ptr_cur_reg + eop_seg + 1;
end else begin
wr_ptr_next = wr_ptr_cur_next;
end
end
end
end
end
always @(posedge clk) begin
wr_ptr_reg <= wr_ptr_next;
wr_ptr_cur_reg <= wr_ptr_cur_next;
seg_mem_wr_addr_reg <= seg_mem_wr_addr_next;
if (rst) begin
wr_ptr_reg <= 0;
wr_ptr_cur_reg <= 0;
seg_mem_wr_addr_reg <= 0;
end
end
// Read logic
integer rd_seg;
reg [SEG_SEL_WIDTH-1:0] cur_rd_seg;
reg rd_valid;
always @* begin
rd_ptr_next = rd_ptr_reg;
rd_ptr_ctrl_next = rd_ptr_ctrl_reg;
mem_rd_data_valid_next = mem_rd_data_valid_reg;
ctrl_mem_rd_data_valid_next = ctrl_mem_rd_data_valid_reg;
out_tlp_data_next = out_tlp_data_reg;
out_tlp_strb_next = out_tlp_strb_reg;
out_tlp_hdr_next = out_tlp_hdr_reg;
out_tlp_seq_next = out_tlp_seq_reg;
out_tlp_bar_id_next = out_tlp_bar_id_reg;
out_tlp_func_num_next = out_tlp_func_num_reg;
out_tlp_error_next = out_tlp_error_reg;
out_tlp_valid_next = out_tlp_valid_reg;
out_tlp_sop_next = out_tlp_sop_reg;
out_tlp_eop_next = out_tlp_eop_reg;
out_seg_offset_next = out_seg_offset_reg;
out_seg_count_next = out_seg_count_reg;
out_ctrl_tlp_strb_next = out_ctrl_tlp_strb_reg;
out_ctrl_tlp_hdr_next = out_ctrl_tlp_hdr_reg;
out_ctrl_tlp_valid_next = out_ctrl_tlp_valid_reg;
out_ctrl_tlp_sop_next = out_ctrl_tlp_sop_reg;
out_ctrl_tlp_eop_next = out_ctrl_tlp_eop_reg;
out_ctrl_seg_offset_next = out_ctrl_seg_offset_reg;
out_ctrl_seg_count_next = out_ctrl_seg_count_reg;
out_ctrl_tlp_ready_int_next = out_ctrl_tlp_ready_int_reg;
temp_out_ctrl_tlp_strb_next = temp_out_ctrl_tlp_strb_reg;
temp_out_ctrl_tlp_hdr_next = temp_out_ctrl_tlp_hdr_reg;
temp_out_ctrl_tlp_valid_next = temp_out_ctrl_tlp_valid_reg;
temp_out_ctrl_tlp_sop_next = temp_out_ctrl_tlp_sop_reg;
temp_out_ctrl_tlp_eop_next = temp_out_ctrl_tlp_eop_reg;
pipe_out_ctrl_tlp_strb_next = pipe_out_ctrl_tlp_strb_reg;
pipe_out_ctrl_tlp_hdr_next = pipe_out_ctrl_tlp_hdr_reg;
pipe_out_ctrl_tlp_valid_next = pipe_out_ctrl_tlp_valid_reg;
pipe_out_ctrl_tlp_sop_next = pipe_out_ctrl_tlp_sop_reg;
pipe_out_ctrl_tlp_eop_next = pipe_out_ctrl_tlp_eop_reg;
seg_mem_rd_addr_next = seg_mem_rd_addr_reg;
seg_mem_rd_en = 0;
seg_ctrl_mem_rd_addr_next = seg_ctrl_mem_rd_addr_reg;
seg_ctrl_mem_rd_en = 0;
if (OUT_TLP_SEG_COUNT == 1) begin
if (!out_tlp_valid || out_read_en) begin
out_tlp_data_next = seg_mem_rd_data;
out_tlp_strb_next = seg_mem_rd_strb;
out_tlp_hdr_next = seg_mem_rd_hdr;
out_tlp_seq_next = seg_mem_rd_seq;
out_tlp_bar_id_next = seg_mem_rd_bar_id;
out_tlp_func_num_next = seg_mem_rd_func_num;
out_tlp_error_next = seg_mem_rd_error;
out_tlp_valid_next = mem_rd_data_valid_reg;
out_tlp_sop_next = seg_mem_rd_sop;
out_tlp_eop_next = seg_mem_rd_eop;
out_seg_offset_next = 0;
out_seg_count_next = 1;
end
if (!mem_rd_data_valid_reg || (!out_tlp_valid || out_read_en)) begin
if (wr_ptr_reg != rd_ptr_reg) begin
seg_mem_rd_en = 1'b1;
mem_rd_data_valid_next = 1'b1;
rd_ptr_next = rd_ptr_reg + 1;
seg_mem_rd_addr_next = rd_ptr_next;
end else begin
mem_rd_data_valid_next = 1'b0;
end
end
if (CTRL_OUT_EN) begin
if (!out_ctrl_tlp_valid || out_ctrl_read_en) begin
out_ctrl_tlp_strb_next = seg_ctrl_mem_rd_strb;
out_ctrl_tlp_hdr_next = seg_ctrl_mem_rd_hdr;
out_ctrl_tlp_valid_next = ctrl_mem_rd_data_valid_reg;
out_ctrl_tlp_sop_next = seg_ctrl_mem_rd_sop;
out_ctrl_tlp_eop_next = seg_ctrl_mem_rd_eop;
out_ctrl_seg_offset_next = 0;
out_ctrl_seg_count_next = 1;
end
if (!ctrl_mem_rd_data_valid_reg || (!out_ctrl_tlp_valid || out_ctrl_read_en)) begin
if (wr_ptr_reg != rd_ptr_ctrl_reg) begin
seg_ctrl_mem_rd_en = 1'b1;
ctrl_mem_rd_data_valid_next = 1'b1;
rd_ptr_ctrl_next = rd_ptr_ctrl_reg + 1;
seg_ctrl_mem_rd_addr_next = rd_ptr_ctrl_next;
end else begin
ctrl_mem_rd_data_valid_next = 1'b0;
end
end
end
end else begin
// invalidate segments
cur_rd_seg = out_seg_offset_reg;
rd_valid = 1;
if (out_read_en) begin
for (rd_seg = 0; rd_seg < OUT_TLP_SEG_COUNT; rd_seg = rd_seg + 1) begin
if (out_tlp_valid_reg[cur_rd_seg] && rd_seg < out_read_seg_count && rd_valid) begin
out_tlp_valid_next[cur_rd_seg] = 1'b0;
out_seg_offset_next = cur_rd_seg + 1;
end else begin
rd_valid = 0;
end
cur_rd_seg = cur_rd_seg + 1;
end
end
// register segments
out_seg_count_next = 0;
for (rd_seg = 0; rd_seg < OUT_TLP_SEG_COUNT; rd_seg = rd_seg + 1) begin
if (!out_tlp_valid_next[rd_seg]) begin
out_tlp_data_next[rd_seg*OUT_TLP_SEG_DATA_WIDTH +: OUT_TLP_SEG_DATA_WIDTH] = seg_mem_rd_data[rd_seg*OUT_TLP_SEG_DATA_WIDTH +: OUT_TLP_SEG_DATA_WIDTH];
out_tlp_strb_next[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = seg_mem_rd_strb[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH];
out_tlp_hdr_next[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = seg_mem_rd_hdr[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
out_tlp_seq_next[rd_seg*SEQ_NUM_WIDTH +: SEQ_NUM_WIDTH] = seg_mem_rd_seq[rd_seg*SEQ_NUM_WIDTH +: SEQ_NUM_WIDTH];
out_tlp_bar_id_next[rd_seg*3 +: 3] = seg_mem_rd_bar_id[rd_seg*3 +: 3];
out_tlp_func_num_next[rd_seg*8 +: 8] = seg_mem_rd_func_num[rd_seg*8 +: 8];
out_tlp_error_next[rd_seg*4 +: 4] = seg_mem_rd_error[rd_seg*4 +: 4];
out_tlp_valid_next[rd_seg +: 1] = mem_rd_data_valid_reg[rd_seg +: 1];
out_tlp_sop_next[rd_seg +: 1] = seg_mem_rd_sop[rd_seg +: 1];
out_tlp_eop_next[rd_seg +: 1] = seg_mem_rd_eop[rd_seg +: 1];
mem_rd_data_valid_next[rd_seg +: 1] = 1'b0;
end
if (out_tlp_valid_next[rd_seg]) begin
out_seg_count_next = out_seg_count_next + 1;
end
end
// read segments
cur_rd_seg = rd_ptr_reg[SEG_SEL_WIDTH-1:0];
rd_valid = 1;
for (rd_seg = 0; rd_seg < OUT_TLP_SEG_COUNT; rd_seg = rd_seg + 1) begin
if (!mem_rd_data_valid_next[cur_rd_seg] && count_reg > rd_seg && rd_valid) begin
rd_ptr_next = rd_ptr_reg + rd_seg+1;
seg_mem_rd_en[cur_rd_seg] = 1'b1;
seg_mem_rd_addr_next[cur_rd_seg*ADDR_WIDTH +: ADDR_WIDTH] = ((rd_ptr_reg + rd_seg) >> SEG_SEL_WIDTH) + 1;
mem_rd_data_valid_next[cur_rd_seg] = 1'b1;
end else begin
rd_valid = 0;
end
cur_rd_seg = cur_rd_seg + 1;
end
if (CTRL_OUT_EN) begin
// invalidate segments
cur_rd_seg = out_ctrl_seg_offset_reg;
rd_valid = 1;
if (out_ctrl_read_en) begin
for (rd_seg = 0; rd_seg < OUT_TLP_SEG_COUNT; rd_seg = rd_seg + 1) begin
if (out_ctrl_tlp_valid_reg[cur_rd_seg] && rd_seg < out_ctrl_read_seg_count && rd_valid) begin
out_ctrl_tlp_valid_next[cur_rd_seg] = 1'b0;
out_ctrl_seg_offset_next = cur_rd_seg + 1;
end else begin
rd_valid = 0;
end
cur_rd_seg = cur_rd_seg + 1;
end
end
// skid buffer
out_ctrl_seg_count_next = 0;
for (rd_seg = 0; rd_seg < OUT_TLP_SEG_COUNT; rd_seg = rd_seg + 1) begin
out_ctrl_tlp_ready_int_next[rd_seg] = !out_ctrl_tlp_valid_next[rd_seg] || (!temp_out_ctrl_tlp_valid_reg[rd_seg] && (!out_ctrl_tlp_valid_reg[rd_seg] || !pipe_out_ctrl_tlp_valid_reg[rd_seg +: 1]));
if (out_ctrl_tlp_ready_int_reg[rd_seg]) begin
if (!out_ctrl_tlp_valid_next[rd_seg] || !out_ctrl_tlp_valid_reg[rd_seg]) begin
if (pipe_out_ctrl_tlp_valid_reg[rd_seg +: 1]) begin
out_ctrl_tlp_strb_next[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = pipe_out_ctrl_tlp_strb_reg[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH];
out_ctrl_tlp_hdr_next[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = pipe_out_ctrl_tlp_hdr_reg[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
out_ctrl_tlp_valid_next[rd_seg +: 1] = pipe_out_ctrl_tlp_valid_reg[rd_seg +: 1];
out_ctrl_tlp_sop_next[rd_seg +: 1] = pipe_out_ctrl_tlp_sop_reg[rd_seg +: 1];
out_ctrl_tlp_eop_next[rd_seg +: 1] = pipe_out_ctrl_tlp_eop_reg[rd_seg +: 1];
end
end else begin
if (pipe_out_ctrl_tlp_valid_reg[rd_seg +: 1]) begin
temp_out_ctrl_tlp_strb_next[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = pipe_out_ctrl_tlp_strb_reg[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH];
temp_out_ctrl_tlp_hdr_next[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = pipe_out_ctrl_tlp_hdr_reg[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
temp_out_ctrl_tlp_valid_next[rd_seg +: 1] = pipe_out_ctrl_tlp_valid_reg[rd_seg +: 1];
temp_out_ctrl_tlp_sop_next[rd_seg +: 1] = pipe_out_ctrl_tlp_sop_reg[rd_seg +: 1];
temp_out_ctrl_tlp_eop_next[rd_seg +: 1] = pipe_out_ctrl_tlp_eop_reg[rd_seg +: 1];
end
end
end else if (!out_ctrl_tlp_valid_next[rd_seg]) begin
if (temp_out_ctrl_tlp_valid_reg[rd_seg +: 1]) begin
out_ctrl_tlp_strb_next[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = temp_out_ctrl_tlp_strb_reg[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH];
out_ctrl_tlp_hdr_next[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = temp_out_ctrl_tlp_hdr_reg[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
out_ctrl_tlp_valid_next[rd_seg +: 1] = temp_out_ctrl_tlp_valid_reg[rd_seg +: 1];
out_ctrl_tlp_sop_next[rd_seg +: 1] = temp_out_ctrl_tlp_sop_reg[rd_seg +: 1];
out_ctrl_tlp_eop_next[rd_seg +: 1] = temp_out_ctrl_tlp_eop_reg[rd_seg +: 1];
temp_out_ctrl_tlp_valid_next[rd_seg +: 1] = 1'b0;
end
end
if (out_ctrl_tlp_valid_next[rd_seg]) begin
out_ctrl_seg_count_next = out_ctrl_seg_count_next + 1;
end
end
// register segments (RAM output pipeline)
for (rd_seg = 0; rd_seg < OUT_TLP_SEG_COUNT; rd_seg = rd_seg + 1) begin
if (out_ctrl_tlp_ready_int_reg[rd_seg] || !pipe_out_ctrl_tlp_valid_reg[rd_seg +: 1]) begin
pipe_out_ctrl_tlp_strb_next[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH] = seg_ctrl_mem_rd_strb[rd_seg*OUT_TLP_SEG_STRB_WIDTH +: OUT_TLP_SEG_STRB_WIDTH];
pipe_out_ctrl_tlp_hdr_next[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH] = seg_ctrl_mem_rd_hdr[rd_seg*TLP_HDR_WIDTH +: TLP_HDR_WIDTH];
pipe_out_ctrl_tlp_valid_next[rd_seg +: 1] = ctrl_mem_rd_data_valid_reg[rd_seg +: 1];
pipe_out_ctrl_tlp_sop_next[rd_seg +: 1] = seg_ctrl_mem_rd_sop[rd_seg +: 1];
pipe_out_ctrl_tlp_eop_next[rd_seg +: 1] = seg_ctrl_mem_rd_eop[rd_seg +: 1];
ctrl_mem_rd_data_valid_next[rd_seg +: 1] = 1'b0;
end
end
// read segments (RAM read)
cur_rd_seg = rd_ptr_ctrl_reg[SEG_SEL_WIDTH-1:0];
rd_valid = 1;
for (rd_seg = 0; rd_seg < OUT_TLP_SEG_COUNT; rd_seg = rd_seg + 1) begin
if (!ctrl_mem_rd_data_valid_next[cur_rd_seg] && count_ctrl_reg > rd_seg && rd_valid) begin
rd_ptr_ctrl_next = rd_ptr_ctrl_reg + rd_seg+1;
seg_ctrl_mem_rd_en[cur_rd_seg] = 1'b1;
seg_ctrl_mem_rd_addr_next[cur_rd_seg*ADDR_WIDTH +: ADDR_WIDTH] = ((rd_ptr_ctrl_reg + rd_seg) >> SEG_SEL_WIDTH) + 1;
ctrl_mem_rd_data_valid_next[cur_rd_seg] = 1'b1;
end else begin
rd_valid = 0;
end
cur_rd_seg = cur_rd_seg + 1;
end
end
end
end
always @(posedge clk) begin
rd_ptr_reg <= rd_ptr_next;
rd_ptr_ctrl_reg <= rd_ptr_ctrl_next;
count_reg <= wr_ptr_next - rd_ptr_next;
count_ctrl_reg <= wr_ptr_next - rd_ptr_ctrl_next;
seg_mem_rd_addr_reg <= seg_mem_rd_addr_next;
seg_ctrl_mem_rd_addr_reg <= seg_ctrl_mem_rd_addr_next;
mem_rd_data_valid_reg <= mem_rd_data_valid_next;
ctrl_mem_rd_data_valid_reg <= ctrl_mem_rd_data_valid_next;
out_tlp_data_reg <= out_tlp_data_next;
out_tlp_strb_reg <= out_tlp_strb_next;
out_tlp_hdr_reg <= out_tlp_hdr_next;
out_tlp_seq_reg <= out_tlp_seq_next;
out_tlp_bar_id_reg <= out_tlp_bar_id_next;
out_tlp_func_num_reg <= out_tlp_func_num_next;
out_tlp_error_reg <= out_tlp_error_next;
out_tlp_valid_reg <= out_tlp_valid_next;
out_tlp_sop_reg <= out_tlp_sop_next;
out_tlp_eop_reg <= out_tlp_eop_next;
out_seg_offset_reg <= out_seg_offset_next;
out_seg_count_reg <= out_seg_count_next;
out_ctrl_tlp_strb_reg <= out_ctrl_tlp_strb_next;
out_ctrl_tlp_hdr_reg <= out_ctrl_tlp_hdr_next;
out_ctrl_tlp_valid_reg <= out_ctrl_tlp_valid_next;
out_ctrl_tlp_sop_reg <= out_ctrl_tlp_sop_next;
out_ctrl_tlp_eop_reg <= out_ctrl_tlp_eop_next;
out_ctrl_seg_offset_reg <= out_ctrl_seg_offset_next;
out_ctrl_seg_count_reg <= out_ctrl_seg_count_next;
out_ctrl_tlp_ready_int_reg <= out_ctrl_tlp_ready_int_next;
temp_out_ctrl_tlp_strb_reg <= temp_out_ctrl_tlp_strb_next;
temp_out_ctrl_tlp_hdr_reg <= temp_out_ctrl_tlp_hdr_next;
temp_out_ctrl_tlp_valid_reg <= temp_out_ctrl_tlp_valid_next;
temp_out_ctrl_tlp_sop_reg <= temp_out_ctrl_tlp_sop_next;
temp_out_ctrl_tlp_eop_reg <= temp_out_ctrl_tlp_eop_next;
pipe_out_ctrl_tlp_strb_reg <= pipe_out_ctrl_tlp_strb_next;
pipe_out_ctrl_tlp_hdr_reg <= pipe_out_ctrl_tlp_hdr_next;
pipe_out_ctrl_tlp_valid_reg <= pipe_out_ctrl_tlp_valid_next;
pipe_out_ctrl_tlp_sop_reg <= pipe_out_ctrl_tlp_sop_next;
pipe_out_ctrl_tlp_eop_reg <= pipe_out_ctrl_tlp_eop_next;
if (rst) begin
rd_ptr_reg <= 0;
rd_ptr_ctrl_reg <= 0;
count_reg <= 0;
count_ctrl_reg <= 0;
seg_mem_rd_addr_reg <= 0;
seg_ctrl_mem_rd_addr_reg <= 0;
mem_rd_data_valid_reg <= 0;
ctrl_mem_rd_data_valid_reg <= 0;
out_tlp_valid_reg <= 0;
out_seg_offset_reg <= 0;
out_ctrl_tlp_valid_reg <= 0;
out_ctrl_seg_offset_reg <= 0;
out_ctrl_tlp_ready_int_reg <= 0;
temp_out_ctrl_tlp_valid_reg <= 0;
pipe_out_ctrl_tlp_valid_reg <= 0;
end
end
endmodule
`resetall