blob: ab3fbf2fd112f62776d56b0daa5d56138653bfa5 [file] [log] [blame] [edit]
//****************************************************************************
//
// 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.
//
//****************************************************************************
//=========================================================================
//==maskcntl: mask the incoming transctions to garantee the outgoing outstanding transactions
//====meet the outstanding configs
//=========================================================================
module maskcntl
(
// Master Interface address channel handshake signals
awvalid_m,
awready_m,
arvalid_m,
arready_m,
// Lock control signals
pre_awvalid,
pre_arvalid,
awlock,
arlock,
lock_seq,
// QoS input signals
aw_qos_s,
ar_qos_s,
// Master Interface return channel handshake signals
bvalid_m,
bready_m,
rvalid_m,
rready_m,
// Mask signals
wr_cnt_empty,
mask_w,
mask_r,
// QoS output signals
aw_qos_m,
ar_qos_m,
// Miscellaneous connections
aclk,
aresetn
);
// ---------------------------------------------------------------------------
// parameters
// ---------------------------------------------------------------------------
//read outstanding issues
parameter RD_ISS=8;
//write outstanding issues
parameter WR_ISS=8;
localparam RCNT_WIDTH=$clog2(RD_ISS+1);
localparam WCNT_WIDTH=$clog2(WR_ISS+1);
localparam COMBCNT_WIDTH=(RCNT_WIDTH>WCNT_WIDTH) ? (RCNT_WIDTH+1) : (WCNT_WIDTH+1);
// ---------------------------------------------------------------------------
// Port definitions
// ---------------------------------------------------------------------------
// Master Interface address channel handshake signals
input awvalid_m;
input awready_m;
input arvalid_m;
input arready_m;
// Lock control signals
input pre_awvalid;
input pre_arvalid;
input awlock;
input arlock;
// QoS input signals
input [3:0] aw_qos_s;
input [3:0] ar_qos_s;
// Master Interface return channel handshake signals
input bvalid_m;
input bready_m;
input rvalid_m;
input rready_m;
// Mask signals
output wr_cnt_empty;
output mask_w;
output mask_r;
// QoS output signals
output [3:0] aw_qos_m;
output [3:0] ar_qos_m;
// Lock sequence signal
output lock_seq;
// Miscelaneous connections
input aclk;
input aresetn;
//------------------------------------------------------------------------------
// Wires
//------------------------------------------------------------------------------
wire push_rd; // Read address accepted;
wire push_wr; // Write address accepted
wire pop_rd; // Last read beat accepted
wire pop_wr; // Write transaction accepted
wire next_wr_cnt_empty; // Next Write counter empty
wire wr_cnt_en;
wire rd_cnt_en;
wire comb_cnt_en;
wire wr_mask_en;
wire rd_mask_en;
wire [RCNT_WIDTH-1:0] next_rd_cnt; // next outstanding reads count
wire [WCNT_WIDTH-1:0] next_wr_cnt; // next outstanding writes count
reg [COMBCNT_WIDTH-1:0] next_comb_cnt; // next outstanding trans count
reg [WCNT_WIDTH-1:0] wr_iss_d;
reg [RCNT_WIDTH-1:0] rd_iss_d;
reg next_mask_w;
reg next_mask_r;
wire nxt_lock_seq;
wire lock_seq_en;
wire [3:0] aw_qos_s;
wire [3:0] ar_qos_s;
//------------------------------------------------------------------------------
// Registers
//------------------------------------------------------------------------------
reg [RCNT_WIDTH-1:0] rd_cnt; // outstanding reads count
reg [WCNT_WIDTH-1:0] wr_cnt; // outstanding writes count
reg [COMBCNT_WIDTH-1:0] comb_cnt; // outstanding trans count
reg lock_seq;
reg wr_cnt_empty; // Write counter empty
reg reg_mask_w;
reg reg_mask_r;
// ---------------------------------------------------------------------------
// start of code
// ---------------------------------------------------------------------------
//---------------------------- Drive QoS outputs ----------------------------
// Pass through input Qos Value
assign aw_qos_m = aw_qos_s;
assign ar_qos_m = ar_qos_s;
//-------------------- Outstanding transaction counters ---------------------
assign push_rd = arvalid_m & arready_m;
assign push_wr = awvalid_m & awready_m;
assign pop_rd = rvalid_m & rready_m;
assign pop_wr = bvalid_m & bready_m;
// Determine next outstanding read counter
assign next_rd_cnt = (push_rd & ~pop_rd) ? rd_cnt + 1'b1
: ((~push_rd & pop_rd) ? rd_cnt - 1'b1
: rd_cnt);
// Determine next outstanding write counter
assign next_wr_cnt = (push_wr & ~pop_wr) ? wr_cnt + 1'b1
: ((~push_wr & pop_wr) ? wr_cnt - 1'b1
: wr_cnt);
// Determine next combined outstanding counter
always @(*)
begin : p_next_comb
case({push_wr, push_rd, pop_wr, pop_rd})
4'b0001,
4'b0010,
4'b0111,
4'b1011 : next_comb_cnt = (comb_cnt - 2'h1);
4'b0011 : next_comb_cnt = (comb_cnt - 2'h2);
4'b0100,
4'b1000,
4'b1101,
4'b1110 : next_comb_cnt = (comb_cnt + 2'h1);
4'b1100 : next_comb_cnt = (comb_cnt + 2'h2);
default : next_comb_cnt = comb_cnt;
endcase
end // p_next_comb
assign wr_cnt_en = push_wr ^ pop_wr;
assign rd_cnt_en = push_rd ^ pop_rd;
assign comb_cnt_en = push_wr | push_rd | pop_wr | pop_rd;
assign next_wr_cnt_empty = (next_wr_cnt == 1'b0);
always @(posedge aclk or negedge aresetn)
begin : p_wr_cnt_seq
if (!aresetn)
begin
wr_cnt <= {WCNT_WIDTH{1'b0}};
wr_cnt_empty <= 1'b1;
rd_cnt <= {RCNT_WIDTH{1'b0}};
comb_cnt <= {3{1'b0}};
end
else
begin
if (wr_cnt_en)
begin
wr_cnt <= next_wr_cnt;
wr_cnt_empty <= next_wr_cnt_empty;
end
if (rd_cnt_en)
begin
rd_cnt <= next_rd_cnt;
end
if (comb_cnt_en)
begin
comb_cnt <= next_comb_cnt;
end
end
end // p_wr_cnt_seq
//--------------------------- Mask Generation -------------------------------
always @(next_wr_cnt or next_rd_cnt)
begin : p_mask_comb
wr_iss_d = WR_ISS;
rd_iss_d = RD_ISS;
next_mask_w = 1'b0;
next_mask_r = 1'b0;
// If the next write count will be reached then
// mask all the write slave interfaces
if (next_wr_cnt == wr_iss_d )
next_mask_w = 1'b1;
// If the next read count will be reached then
// mask all the read slave interfaces
if (next_rd_cnt == rd_iss_d )
next_mask_r = 1'b1;
end // p_mask_comb
assign wr_mask_en =push_wr | pop_wr;
assign rd_mask_en = push_rd | pop_rd;
always @(posedge aclk or negedge aresetn)
begin : p_wr_mask_seq
if (!aresetn)
begin
reg_mask_w <= 1'b0;
end
else if (wr_mask_en)
begin
reg_mask_w <= next_mask_w;
end
end // p_wr_mask_seq
assign mask_w = reg_mask_w;
always @(posedge aclk or negedge aresetn)
begin : p_rd_mask_seq
if (!aresetn)
begin
reg_mask_r <= 1'b0;
end
else if (rd_mask_en)
begin
reg_mask_r <= next_mask_r;
end
end // p_rd_mask_seq
assign mask_r = reg_mask_r;
//--------------------------- Lock Seq Register -------------------------------
assign nxt_lock_seq = ((pre_awvalid & awlock) | (pre_arvalid & arlock))
? 1'b1
: (((pre_awvalid & ~awlock) | (pre_arvalid & ~arlock)) & ~|comb_cnt
? 1'b0
: lock_seq);
assign lock_seq_en = pre_awvalid || pre_arvalid;
always @(posedge aclk or negedge aresetn)
begin : p_lock_seq
if (!aresetn)
begin
lock_seq <= 1'b0;
end
else if (lock_seq_en)
begin
lock_seq <= nxt_lock_seq;
end
end // p_lock_seq
endmodule