Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / niu_smx_sm_req_cmdreq.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: niu_smx_sm_req_cmdreq.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
module niu_smx_sm_req_cmdreq(
/*AUTOARG*/
// Outputs
ack, cmdflag, cmdflag_data, early_cmdflag_n, early_cmdflag_data_n,
xtb_wr, xtb_waddr, xtb_wdata, ff_wr, ff_wdata, lnen_ff_wr,
lnen_ff_wdata, cmdreq_idle, cmd_cs,
// Inputs
clk, reset_l, req, req_cmd, req_addr, req_len, req_xid, req_port,
req_dma, req_client, rst_cmdflag, cfg_no_cmdflag,
cfg_no_sameclientck, datareq_idle, xfer_done, rst_xtb_wr, ff_full,
lnen_ff_full, stall_enable, tid_valid_rdata_bus
);
input clk;
input reset_l;
// dmc cmd req if
input req;
input [7:0] req_cmd;
input [63:0] req_addr;
input [13:0] req_len;
input [5:0] req_xid;
input [1:0] req_port;
input [4:0] req_dma;
input [7:0] req_client;
output ack;
// datareq if
output cmdflag;
output [4:0] cmdflag_data;
output early_cmdflag_n;
output [4:0] early_cmdflag_data_n;
input rst_cmdflag;
input cfg_no_cmdflag;
input cfg_no_sameclientck;
input datareq_idle;
// datareq/dv if
input xfer_done; // dmc_comp & nothing in datareq sm (ext logic)
// xtb if
output xtb_wr; // this one also reset curnof64B cnt to 0
output [5:0] xtb_waddr;
output [127:0] xtb_wdata;
input rst_xtb_wr;
// cmd ff if
output ff_wr;
output [65:0] ff_wdata;
input ff_full;
// lnen_ff if
output lnen_ff_wr;
output [4:0] lnen_ff_wdata;
input lnen_ff_full;
// stall_hdlr if
input stall_enable;
output cmdreq_idle;
output [2:0] cmd_cs;
// status
// added 121405
input [63:0] tid_valid_rdata_bus;
/* generate line enable */
function [3:0] gen_eop_line_en;
input[5:0] offset;
// bit0 - line0 (16B), bit1 - line1 (32B)
// bit2 - line2 (48B), bit3 - line3 (64B)
// 0 - no write; 1- write
reg [3:0] line_en;
reg anyone_16B;
begin
anyone_16B= |offset[3:0];
case({offset[5:4]})
2'b00: line_en= (anyone_16B)? 4'b0001 : 4'b1111;
2'b01: line_en= (anyone_16B)? 4'b0011 : 4'b0001;
2'b10: line_en= (anyone_16B)? 4'b0111 : 4'b0011;
2'b11: line_en= (anyone_16B)? 4'b1111 : 4'b0111;
endcase
gen_eop_line_en= line_en;
end
endfunction
function [3:0] gen_sop_line_en;
input[5:0] offset;
reg [3:0] line_en;
begin
case(offset[5:4])
2'b00: line_en= 4'b1111;
2'b01: line_en= 4'b1110;
2'b10: line_en= 4'b1100;
2'b11: line_en= 4'b1000;
endcase
gen_sop_line_en= line_en;
end
endfunction
/*
function [15:0] decode_eop_16b_byte_en_little; // B15,B14..,B1,B0
input [3:0] offset;
reg [15:0] byte_en;
begin
case(offset)
4'h0: byte_en= 16'hffff;
4'h1: byte_en= 16'h1;
4'h2: byte_en= 16'h3;
4'h3: byte_en= 16'h7;
4'h4: byte_en= 16'hf;
4'h5: byte_en= 16'h1f;
4'h6: byte_en= 16'h3f;
4'h7: byte_en= 16'h7f;
4'h8: byte_en= 16'hff;
4'h9: byte_en= 16'h1ff;
4'ha: byte_en= 16'h3ff;
4'hb: byte_en= 16'h7ff;
4'hc: byte_en= 16'hfff;
4'hd: byte_en= 16'h1fff;
4'he: byte_en= 16'h3fff;
4'hf: byte_en= 16'h7fff;
endcase
decode_eop_16b_byte_en_little= byte_en;
end
endfunction
function [15:0] decode_eop_16b_byte_en_big; // B0,B1...,B14,B15
input [3:0] offset;
reg [15:0] byte_en;
begin
case(offset)
4'h0: byte_en= 16'hffff;
4'h1: byte_en= 16'h8000;
4'h2: byte_en= 16'hc000;
4'h3: byte_en= 16'he000;
4'h4: byte_en= 16'hf000;
4'h5: byte_en= 16'hf800;
4'h6: byte_en= 16'hfc00;
4'h7: byte_en= 16'hfe00;
4'h8: byte_en= 16'hff00;
4'h9: byte_en= 16'hff80;
4'ha: byte_en= 16'hffc0;
4'hb: byte_en= 16'hffe0;
4'hc: byte_en= 16'hfff0;
4'hd: byte_en= 16'hfff8;
4'he: byte_en= 16'hfffc;
4'hf: byte_en= 16'hfffe;
endcase
decode_eop_16b_byte_en_big= byte_en;
end
endfunction
function [15:0] decode_sop_16b_byte_en_big; // B0,B1...,B14,B15
input [3:0] offset;
reg [15:0] byte_en;
begin
case(offset)
4'h0: byte_en= 16'hffff;
4'h1: byte_en= 16'h7fff;
4'h2: byte_en= 16'h3fff;
4'h3: byte_en= 16'h1fff;
4'h4: byte_en= 16'h0fff;
4'h5: byte_en= 16'h07ff;
4'h6: byte_en= 16'h03ff;
4'h7: byte_en= 16'h01ff;
4'h8: byte_en= 16'h00ff;
4'h9: byte_en= 16'h007f;
4'ha: byte_en= 16'h003f;
4'hb: byte_en= 16'h001f;
4'hc: byte_en= 16'h000f;
4'hd: byte_en= 16'h0007;
4'he: byte_en= 16'h0003;
4'hf: byte_en= 16'h0001;
endcase
decode_sop_16b_byte_en_big= byte_en;
end
endfunction
*/
function [6:0] xlate_cmd_meta_to_si;
input[7:0] cmd;
reg [6:0] new_cmd; // {err, si_cmd}
begin
case(cmd[`SMX_CMDPOS_CODE])
`SMX_CMD_MEMRD: new_cmd= {1'b0, `SMX_SICMD_RD};
`SMX_CMD_MEMWR: new_cmd= (cmd[`SMX_CMDPOS_POST]==`SMX_CMD_POST)?
{1'b0, `SMX_SICMD_WR_POST} : {1'b0, `SMX_SICMD_WR_NONPOST};
default: new_cmd= {1'b1, 6'h0}; // unrecognized cmd ??
endcase
xlate_cmd_meta_to_si= new_cmd;
end
endfunction
parameter s0= 3'h0,
s1= 3'h1,
s1_1= 3'h4,
s2= 3'h2,
s3= 3'h3;
reg [63:0] req_addr_r;
reg [13:0] req_len_r;
reg [1:0] req_port_r;
reg [4:0] req_dma_r;
reg [7:0] req_cmd_r;
reg [5:0] req_xid_r;
reg [7:0] req_client_r;
/* adjust to 64B aligned */
// wire[14:0] adj_len_n= {9'h0, req_addr[5:0]} + {1'b0, req_len[13:0]}; // no reg in ??
wire[14:0] adj_len_n= {9'h0, req_addr_r[5:0]} + {1'b0, req_len_r[13:0]};
/* generate nof64B for rd/wr resp (store) */
wire anyone_64B_adj_len_n= |adj_len_n[5:0];
wire [9:0] nof64B_n= (anyone_64B_adj_len_n)?
({1'b0, adj_len_n[14:6]} + 1'b1) : {1'b0, adj_len_n[14:6]};
// + ((anyone_64B_adj_len_n)? 1'b1 : 1'b0);
/* generate sop_line_en, eop_line_en for rd resp (store) */
// wire [3:0] sop_line_en_n= gen_sop_line_en(req_addr[5:0]); // no reg in
wire [3:0] sop_line_en_n= gen_sop_line_en(req_addr_r[5:0]);
wire [3:0] eop_line_en_n= gen_eop_line_en(adj_len_n[5:0]);
// also use for line_en in wr side of data req
/* generate sop_byte_en, eop_byte_en for rd resp (store) */
// wire [3:0] ec_sop_byte_en_n= req_addr[3:0]; // encoded ; no reg in??
wire [3:0] ec_sop_byte_en_n= req_addr_r[3:0]; // encoded
wire [3:0] ec_eop_byte_en_n= adj_len_n[3:0];
// wire [15:0] sop_byte_en_n= decode_sop_16b_byte_en_big(ec_sop_byte_en_n);
// wire [15:0] eop_byte_en_n= decode_eop_16b_byte_en_big(ec_eop_byte_en_n);
/*
no reg in ???
wire [127:0] xtb_wdata_n= {10'h0,
req_addr, req_len, req_port, req_dma, req_client,
nof64B_n, sop_line_en_n, eop_line_en_n,
ec_sop_byte_en_n, ec_eop_byte_en_n};
*/
wire [127:0] xtb_wdata_n= {9'h0,
req_addr_r, req_len_r, req_port_r, req_dma_r, req_client_r,
nof64B_n, sop_line_en_n, eop_line_en_n,
ec_sop_byte_en_n, ec_eop_byte_en_n};
// 64, 14, 2, 5, 8,
// 10, 4, 4, 4, 4
reg [127:0] xtb_wdata;
// wire [5:0] xtb_waddr_n= req_xid; // no reg in ??
wire [5:0] xtb_waddr_n= req_xid_r;
reg [5:0] xtb_waddr;
// wire is_nonpost_n= (req_cmd[`SMX_CMDPOS_POST] == `SMX_CMD_NONPOST)? 1'b1 : 1'b0; // no reg in
wire is_nonpost_n= (req_cmd_r[`SMX_CMDPOS_POST] == `SMX_CMD_NONPOST)? 1'b1 : 1'b0;
reg [63:0] curaddr;
reg [9:0] cntof64B;
reg [9:0] nof64B;
// cmd data use in s1; xx_r avail at s1
wire [15:0] si_id= {req_xid_r[5:0], cntof64B[9:0]};
wire [39:0] si_addr= {curaddr[39:6], 6'h0};
wire [2:0] si_err= {3'h0}; // ???
wire si_order= req_cmd_r[`SMX_CMDPOS_ORDER];
// translate meta cmd to sii cmd
wire [6:0] xlate_cmd= xlate_cmd_meta_to_si(req_cmd_r); // ??? handle of non-existence cmd
wire [5:0] si_cmd= xlate_cmd[5:0]; // bit6 is xlate error
reg ff_wr_n;
wire ff_wr= ff_wr_n;
// ff cmd data
wire [65:0] ff_wdata_n= {si_cmd[5:0], si_err[2:0], si_id[15:0], si_addr[39:0], si_order};
// 6, 3, 16, 40, 1
wire [65:0] ff_wdata= ff_wdata_n;
// inc sii start addr (by 64B) per send
wire [57:0] msb_curaddr= curaddr[63:6];
wire [57:0] new_msb_curaddr_n= msb_curaddr+1'b1; // use incrementor rather than add 64B
// inc token LSB (by 1) per send
wire [9:0] new_cntof64B_n= cntof64B + 1'b1;
wire eop_n= (new_cntof64B_n==nof64B)? 1'b1: 1'b0;
wire one64Blen= (nof64B==10'h1);
// assume wr always start at 64B aligned;
// at end of pkt, use eop_line_en, else read 4 lines
reg [3:0] eop_line_en;
wire [4:0] cmdflag_data_n= (eop_n)? {eop_n,eop_line_en} : {eop_n, 4'b1111};
reg [4:0] cmdflag_data;
wire same_client_n= (cfg_no_sameclientck)? 1'b1 : // always bogus same if disable
((req_client_r==req_client)? 1'b1 : 1'b0);
// early version of cmdflag to save 1 cycle at start
reg early_cmdflag_n;
wire [4:0] early_cmdflag_data_n= cmdflag_data_n;
reg ack_n, ack;
reg set_xtb_wr_n, xtb_wr;
reg ld_cdata_n; // flop in meta cmd
reg ld_info_n; // flop in info for cmdflag proc use;
// ie eop_line_en, 64B cnt
reg inc_cntof64B_n;
reg inc_curaddr_n;
reg set_cmdflag_n;
reg cmdflag;
reg [2:0] cmd_cs, cmd_ns;
wire cmdreq_idle= (cmd_cs==s0);
//
// ??? need registered in ? migh have timing problem on xtb_wdata_n gen
// xtb_wr need flag ??? rdreq and wreq arb if use one ram 64 entries;
//
reg lnen_ff_wr_n;
wire lnen_ff_wr= lnen_ff_wr_n;
wire [4:0] lnen_ff_wdata= {eop_n, cmdflag_data_n[3:0]};
// added 121405 - begin
wire tag_is_valid_n= ((cntof64B>10'h4) && cfg_no_cmdflag)?
tid_valid_rdata_bus[req_xid_r] : 1'b1;
// condition tag valid only if in rdreq case (cfg_no_cmdflag is 1)
// and at least 4 dispatched (this is to make time for xtb
// write to go thru since xtb_wr signal arb with wrreq
always @(/*AUTOSENSE*/cmd_cs or cmdflag or datareq_idle or eop_n
or ff_full or is_nonpost_n or lnen_ff_full or one64Blen
or req or same_client_n or stall_enable or tag_is_valid_n
or xfer_done or xtb_wr) begin
ack_n= 1'b0;
set_xtb_wr_n= 1'b0;
ld_cdata_n= 1'b0;
ld_info_n= 1'b0;
inc_cntof64B_n= 1'b0;
inc_curaddr_n= 1'b0;
ff_wr_n= 1'b0;
lnen_ff_wr_n= 1'b0;
set_cmdflag_n= 1'b0;
early_cmdflag_n= 1'b0;
cmd_ns= cmd_cs;
case(cmd_cs)
s0: begin // idle; wait for dmc req
if(req && !stall_enable) begin
ack_n= 1'b1;
ld_cdata_n= 1'b1; // flop in meta cmd data; rst/init working copies
// curaddr init to startaddr, cntof64B rst to 0
// generate xtb_wdata_n, to be written at s1;
// gen nof64B_n, eop_line_en_n (to be used in s1)
// xtb_wr_n= is_nonpost_n; // no reg in ??
cmd_ns= s1;
end
end
s1: begin // cnt= 0; xtb wr; meta_cmd_data_r available;
// xx_r use in rest of state until ld_cdata_n= 1
// generate xtb_wdata_n, to be written at next state;
// gen nof64B_n, eop_line_en_n (to be used in next state)
ld_info_n= 1'b1; // always load info for proc/cmdflag use
if(is_nonpost_n) begin // xtb write only with non-post cmd
if(!xtb_wr) begin // wait till previous write go thru
set_xtb_wr_n= 1'b1;
cmd_ns= s1_1;
end
end else cmd_ns= s1_1;
end
s1_1: begin // cnt= 0; xtb wr; meta_cmd_data_r available;
// xx_r use in rest of state until ld_cdata_n= 1
// check ff_full, flag;
// wrff, wr flag_data; set flag
if(!ff_full && !cmdflag && !lnen_ff_full) begin
if(tag_is_valid_n) begin // added 121405
lnen_ff_wr_n= 1'b1; // line enable ff for dv sm
ff_wr_n= 1'b1; // cmdff
if(datareq_idle) begin // cmdflag
// datareq machine idle; kick it to work; save 1 cycle;
early_cmdflag_n= 1'b1;
end
else begin
set_cmdflag_n= 1'b1;
end
// eop check;
if(eop_n) begin
if(one64Blen) cmd_ns= s3; // req not ready on dmc
// wait one cycle
else begin
if(req && same_client_n && !stall_enable) begin
// cont' to next pkt; same client can burst in datareq
ack_n= 1'b1;
ld_cdata_n= 1'b1;
// xtb_wr_n= is_nonpost_n; // no reg in ??
cmd_ns= s1;
end
else begin // wait data complete before switch to next client
cmd_ns= s2;
end
end
end // eop
else begin
inc_cntof64B_n= 1'b1;
inc_curaddr_n= 1'b1;
cmd_ns= cmd_cs; // continue this pkt
end
end // added 121405
else begin // tag not valid (could be timeout in mid)
cmd_ns= s3; // cont' to next pkt
end
end
end
s2: begin // wait data complete
// xfer done is a pulse that align with dv of end of datareq;
// in wr, since it always has 4 cycles for data, and it takes
// less than 4 cycles from s1 to s2, s2 should be able to
// catch this pulse;
// in rd, xfer_done is hard wired to 1
// check if req with same client
// req can happen while waiting for complete
// try to burst out dv without waiting for
// previous pkt comp of same client
if(req && same_client_n && !stall_enable) begin
// new pkt; same client can burst in datareq
ack_n= 1'b1;
ld_cdata_n= 1'b1;
// xtb_wr_n= is_nonpost_n; // no reg in ?/
cmd_ns= s1;
end
else begin
if(xfer_done) begin
if(req && !stall_enable)begin
ack_n= 1'b1;
ld_cdata_n= 1'b1;
// xtb_wr_n= is_nonpost_n; // no reg in ?/
cmd_ns= s1; // continue to process
end
else
cmd_ns= s0; // no more req; go back to idle
end
end // not same client at req
end
s3: begin // dummy cycle to sample correct dmc_req
if(req && same_client_n && !stall_enable) begin
// new pkt; same client can burst in datareq
ack_n= 1'b1;
ld_cdata_n= 1'b1;
// xtb_wr_n= is_nonpost_n; // no reg in ?/
cmd_ns= s1;
end
else begin // wait data complete before switch to next client
cmd_ns= s2;
end
end
endcase
end
always @ (posedge clk) begin
if(ld_cdata_n) begin
req_cmd_r<= `SMX_PD req_cmd;
req_addr_r<= `SMX_PD req_addr;
req_len_r<= `SMX_PD req_len;
req_xid_r<= `SMX_PD req_xid;
req_port_r<= `SMX_PD req_port;
req_dma_r<= `SMX_PD req_dma;
req_client_r<= `SMX_PD req_client;
end
if(ld_cdata_n)
curaddr<= `SMX_PD {req_addr[63:6], 6'h0}; // always start at 64B boundary
else
if(inc_curaddr_n) curaddr<= `SMX_PD {new_msb_curaddr_n[57:0], 6'h0};
if(ld_cdata_n)
cntof64B<= `SMX_PD 10'h0;
else
if(inc_cntof64B_n) cntof64B<= `SMX_PD new_cntof64B_n;
end
always @ (posedge clk) begin
if(!reset_l)begin
xtb_wr<= `SMX_PD 1'b0;
ack<= `SMX_PD 1'b0;
cmd_cs<= `SMX_PD s0;
cmdflag<= `SMX_PD 1'b0;
end
else begin
if(set_xtb_wr_n)
xtb_wr<= `SMX_PD 1'b1;
else if(rst_xtb_wr)
xtb_wr<= `SMX_PD 1'b0;
ack<= `SMX_PD ack_n;
cmd_cs<= `SMX_PD cmd_ns;
if(cfg_no_cmdflag) begin
cmdflag<= `SMX_PD 1'b0;
end
else begin
if(set_cmdflag_n)
cmdflag<= `SMX_PD 1'b1;
else
if(rst_cmdflag) cmdflag<= `SMX_PD 1'b0;
end
end
end
always @ (posedge clk) begin
if(set_xtb_wr_n) begin
xtb_wdata<= `SMX_PD xtb_wdata_n;
xtb_waddr<= `SMX_PD xtb_waddr_n;
end
if(ld_info_n) begin
nof64B<= `SMX_PD nof64B_n;
eop_line_en<= `SMX_PD eop_line_en_n;
end
if(set_cmdflag_n) cmdflag_data<= `SMX_PD cmdflag_data_n;
end
endmodule