blob: d887a1c141bb1d19b60f68fa097acc9d621f7978 [file] [log] [blame]
//****************************************************************************
//
// Copyright 2017-2023 Vivante Corporation
//
// 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.
//
//****************************************************************************
// Auto-generated file on 11/03/2023.
//
//****************************************************************************
module upsize_wr_cntrl
(
awfifo_ready, wready_s, merge, merge_clear, data_select, wvalid_m,
wdata_m, wstrb_m, wlast_m, wuser_m, wid_m,
aclk, aresetn, awfifo_valid, awfifo_data, wvalid_s, wlast, wuser,
wid, strb_skid_valid, wdata_merged, wstrb_merged, wready_m
);
`include "Axi.v"
parameter ARID_WIDTH=4;
parameter AWID_WIDTH=4;
parameter ADDR_WIDTH=32;
parameter US_DATA_WIDTH=256;
parameter DS_DATA_WIDTH=128;
parameter USER_WIDTH=4;
localparam DS_WSTRB_WIDTH=DS_DATA_WIDTH/8;
localparam US_WSTRB_WIDTH=US_DATA_WIDTH/8;
localparam DS_ADDR_AL_WIDTH=$clog2(DS_WSTRB_WIDTH);
localparam US_ADDR_AL_WIDTH=$clog2(US_WSTRB_WIDTH);
localparam ARFMT_WIDTH=4+DS_ADDR_AL_WIDTH+US_ADDR_AL_WIDTH+3;
localparam AWFMT_WIDTH=AWID_WIDTH+1+4+1+DS_ADDR_AL_WIDTH*2+3+1;
localparam US_AW_WIDTH=4+USER_WIDTH+AWID_WIDTH+ADDR_WIDTH+8+3+2+2+4+4+3+1;
localparam US_AR_WIDTH=4+USER_WIDTH+ARID_WIDTH+ADDR_WIDTH+8+3+2+2+4+4+3+1;
localparam US_R_WIDTH=USER_WIDTH+ARID_WIDTH+US_DATA_WIDTH+2+1;
localparam US_W_WIDTH=USER_WIDTH+AWID_WIDTH+US_DATA_WIDTH+US_WSTRB_WIDTH+1;
localparam US_B_WIDTH=USER_WIDTH+AWID_WIDTH+2;
localparam AW_IDB_WIDTH=US_AW_WIDTH+US_ADDR_AL_WIDTH-DS_ADDR_AL_WIDTH;
localparam AR_IDB_WIDTH=US_AR_WIDTH+ARFMT_WIDTH;
localparam W_IDB_WIDTH=USER_WIDTH+US_DATA_WIDTH+US_WSTRB_WIDTH+1;
localparam R_IDB_WIDTH=USER_WIDTH+ARID_WIDTH+US_DATA_WIDTH+2+1+DS_ADDR_AL_WIDTH;
localparam B_IDB_WIDTH=USER_WIDTH+2+AWID_WIDTH;
localparam DATA_RATIO=(DS_DATA_WIDTH/US_DATA_WIDTH);
input aclk;
input aresetn;
output awfifo_ready;
input awfifo_valid;
input [AWFMT_WIDTH-1:0] awfifo_data;
input wvalid_s;
output wready_s;
input wlast;
input [USER_WIDTH-1:0] wuser;
input [AWID_WIDTH-1:0] wid;
output merge;
output merge_clear;
output [DATA_RATIO-1:0] data_select;
input strb_skid_valid;
input [DS_DATA_WIDTH-1:0] wdata_merged;
input [DS_WSTRB_WIDTH-1:0] wstrb_merged;
output wvalid_m;
input wready_m;
output [DS_DATA_WIDTH-1:0] wdata_m;
output [DS_WSTRB_WIDTH-1:0] wstrb_m;
output wlast_m;
output [USER_WIDTH-1:0] wuser_m;
output [AWID_WIDTH-1:0] wid_m;
wire slavew_hndshk;
wire wfifo_hndshk;
wire awfifo_hndshk;
wire bypass_in;
wire [2:0] write_size;
wire [DS_ADDR_AL_WIDTH-1:0] write_addr;
wire [DS_ADDR_AL_WIDTH-1:0] write_addr_mask;
wire [3:0] write_len_tb;
wire bypass;
wire [2:0] a_size;
wire [DS_ADDR_AL_WIDTH-1:0] addr_mask;
wire [DS_ADDR_AL_WIDTH-1:0] addr_internal;
wire [3:0] beat_count;
wire [DS_ADDR_AL_WIDTH:0] addr_incr;
wire [DS_ADDR_AL_WIDTH-1:0] store_addr;
wire [3:0] beat_reg_next;
wire beat_reg_wr_en;
wire wrap_fits_in;
wire wrap_fits;
wire split_wrap;
wire split_wrap_in;
wire split_wrap_reg_en;
wire split_wrap_reg_next;
wire cross_boundary;
wire cross_boundary_sel;
wire idle;
wire insert_extra_wlast;
wire wlast_sel;
wire wfifo_valid_next;
wire wfifo_should_push;
wire busy_reg_next;
wire reg_wr_en;
wire reg_update;
wire [AWID_WIDTH-1:0] wid_in;
reg [DS_ADDR_AL_WIDTH-1:0] addr_reg;
reg [DS_ADDR_AL_WIDTH-1:0] addr_mask_reg;
reg cross_boundary_reg;
reg [2:0] size_reg;
reg bypass_reg;
reg [3:0] beat_reg;
reg split_wrap_reg;
reg wrap_fits_reg;
reg [6:0] size_incr;
reg [DS_ADDR_AL_WIDTH-1:0] addr_reg_nxt;
wire [DATA_RATIO-1:0] data_select;
reg wfifo_valid_reg;
reg busy_reg;
reg merge_clear;
reg wlast_reg;
reg [USER_WIDTH-1:0] wuser_reg;
reg [AWID_WIDTH-1:0] wid_reg;
assign slavew_hndshk = wvalid_s && wready_s;
assign wfifo_hndshk = wvalid_m && wready_m;
assign awfifo_hndshk = awfifo_valid && awfifo_ready;
assign merge = slavew_hndshk;
always @(posedge aclk or negedge aresetn)
begin : last_clear_p
if (!aresetn)
merge_clear <= 1'b0;
else if (merge || wfifo_hndshk)
merge_clear <= wfifo_hndshk;
end
assign idle = (~awfifo_valid && ~busy_reg);
genvar i;
generate
for(i=0;i<DATA_RATIO;i=i+1) begin: for_data_select
assign data_select[i]=(idle) ? 1'h1 : (addr_internal[DS_ADDR_AL_WIDTH-1:US_ADDR_AL_WIDTH]==i);
end
endgenerate
assign wready_s = ~strb_skid_valid & ~wfifo_valid_reg;
assign awfifo_ready = ~busy_reg;
assign wfifo_valid_next = ((wvalid_m & ~wready_m) || wfifo_valid_reg) & ~wfifo_hndshk;
always @(posedge aclk or negedge aresetn)
begin : wfifo_valid_seq
if (!aresetn)
wfifo_valid_reg <= 1'b0;
else
wfifo_valid_reg <= wfifo_valid_next;
end
assign wfifo_should_push = (bypass || wlast_sel || cross_boundary_sel) & (busy_reg || awfifo_hndshk);
assign wvalid_m = wfifo_should_push & (wfifo_valid_reg || merge || strb_skid_valid);
assign reg_update = slavew_hndshk || (busy_reg_next && strb_skid_valid);
always @(posedge aclk or negedge aresetn)
begin : wfifo_data_int_seq
if (!aresetn) begin
wlast_reg <= 1'b0;
wuser_reg <= {USER_WIDTH{1'b0}};
end else if (slavew_hndshk) begin
wlast_reg <= wlast;
wuser_reg <= wuser;
end
end
always @(posedge aclk or negedge aresetn)
begin : cross_boundary_reg_seq
if (!aresetn) begin
cross_boundary_reg <= 1'b0;
end else if (reg_update) begin
cross_boundary_reg <= cross_boundary;
end
end
assign wlast_sel = (wready_s) ? (wlast & wvalid_s) : wlast_reg;
assign cross_boundary_sel = (wfifo_valid_reg) ? cross_boundary_reg : cross_boundary;
assign busy_reg_next = ((awfifo_hndshk & ~(strb_skid_valid & wfifo_valid_reg) & ~(wlast_sel & wfifo_hndshk))) ? 1'b1 :
((wfifo_hndshk & wlast_sel) ? 1'b0 : busy_reg);
always @(posedge aclk or negedge aresetn)
begin : busy_seq
if (!aresetn)
busy_reg <= 1'b0;
else
busy_reg <= busy_reg_next;
end
assign {
wid_in,
split_wrap_in,
write_len_tb,
wrap_fits_in,
write_addr_mask,
write_addr,
write_size,
bypass_in
} = awfifo_data;
assign wlast_m = wlast_sel || insert_extra_wlast;
assign wid_m = (awfifo_valid ? wid_in : wid_reg);
assign wuser_m = (wfifo_valid_reg || strb_skid_valid) ? wuser_reg : wuser;
assign wdata_m = wdata_merged;
assign wstrb_m = wstrb_merged;
assign insert_extra_wlast = (~|beat_count & ~bypass & split_wrap);
assign beat_reg_next = (|beat_count & wfifo_hndshk) ? beat_count - 4'b1 : beat_count;
assign beat_reg_wr_en = (wfifo_hndshk || awfifo_hndshk)& split_wrap;
always @(posedge aclk or negedge aresetn)
begin : beat_cnt_p
if (!aresetn)
beat_reg <= 4'b0;
else if (beat_reg_wr_en)
beat_reg <= beat_reg_next;
end
assign split_wrap_reg_en = awfifo_hndshk || (insert_extra_wlast & wfifo_hndshk);
assign split_wrap_reg_next = split_wrap & ~(insert_extra_wlast & wfifo_hndshk);
always @(posedge aclk or negedge aresetn)
begin : unaligned_p
if (!aresetn)
split_wrap_reg <= 1'b0;
else if (split_wrap_reg_en)
split_wrap_reg <= split_wrap_reg_next;
end
assign addr_internal = (awfifo_hndshk) ? write_addr : addr_reg;
assign addr_mask = (awfifo_hndshk) ? write_addr_mask : addr_mask_reg;
assign bypass = (awfifo_hndshk) ? bypass_in : bypass_reg;
assign a_size = (awfifo_hndshk) ? write_size : size_reg;
assign wrap_fits = (awfifo_hndshk) ? wrap_fits_in : wrap_fits_reg;
assign beat_count = (awfifo_hndshk) ? write_len_tb : beat_reg;
assign split_wrap = (awfifo_hndshk) ? split_wrap_in : split_wrap_reg;
always @(*)
begin : size_incr_p
case (a_size)
`AXI_ASIZE_8 : size_incr = {6'b0, 1'b1};
`AXI_ASIZE_16 : size_incr = {5'b0, 2'b10};
`AXI_ASIZE_32 : size_incr = {4'b0, 3'b100};
`AXI_ASIZE_64 : size_incr = {3'b0, 4'b1000};
`AXI_ASIZE_128 : size_incr = {2'b0, 5'b10000};
`AXI_ASIZE_256 : size_incr = {1'b0, 6'b100000};
`AXI_ASIZE_512 : size_incr = {7'b1000000};
default : size_incr = {7'bx};
endcase
end
assign addr_incr = {1'b0, addr_internal} + size_incr[DS_ADDR_AL_WIDTH:0];
always @(*)
begin : addr_reg_nxt_p
integer index_i;
for (index_i = 0; index_i < DS_ADDR_AL_WIDTH ; index_i = index_i + 1)
begin
if (addr_mask[index_i] == 1'b1)
addr_reg_nxt[index_i] = addr_incr[index_i];
else
addr_reg_nxt[index_i] = addr_internal[index_i];
end
end
assign store_addr = (reg_update) ? addr_reg_nxt : addr_internal;
assign reg_wr_en = merge || awfifo_hndshk;
always @(posedge aclk or negedge aresetn)
begin : addr_seq
if (!aresetn)
addr_reg <= {DS_ADDR_AL_WIDTH{1'b0}};
else if (reg_wr_en)
addr_reg <= store_addr;
end
always @(posedge aclk or negedge aresetn)
begin : store_seq
if (!aresetn) begin
addr_mask_reg <= {DS_ADDR_AL_WIDTH{1'b0}};
wid_reg <= {AWID_WIDTH{1'b0}};
bypass_reg <= 1'b0;
size_reg <= 3'b0;
wrap_fits_reg <= 1'b0;
end else if (awfifo_hndshk) begin
addr_mask_reg <= write_addr_mask;
wid_reg <= wid_in;
bypass_reg <= bypass_in;
size_reg <= write_size;
wrap_fits_reg <= wrap_fits_in;
end
end
assign cross_boundary = (|((addr_incr ^ {1'b0, addr_internal}) & ({1'b1, ~addr_mask} ))) & ~(wrap_fits);
endmodule
`include "Axi_undefs.v"