121 lines
4.5 KiB
Systemverilog
121 lines
4.5 KiB
Systemverilog
`ifndef CALC_SEQ_ITEM_SV
|
|
`define CALC_SEQ_ITEM_SV
|
|
|
|
parameter DATA_WIDTH = 32;
|
|
parameter RESP_WIDTH = 2;
|
|
parameter CMD_WIDTH = 4;
|
|
parameter NUM_PORTS = 4;
|
|
// Max clock cycles to wait for a response before declaring the request lost.
|
|
// A correct Calc1 answers in a handful of cycles; the timeout only fires on a
|
|
// DUT that never responds, so the environment reports an error instead of
|
|
// hanging forever.
|
|
parameter RSP_TIMEOUT = 64;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Calc1 command encoding (see Vezba 5, Tabela 6). All other 4-bit values are
|
|
// treated by the design as "invalid" commands.
|
|
//-----------------------------------------------------------------------------
|
|
typedef enum bit [CMD_WIDTH-1:0] {
|
|
CMD_NOP = 4'b0000, // no operation
|
|
CMD_ADD = 4'b0001, // result = op1 + op2
|
|
CMD_SUB = 4'b0010, // result = op1 - op2
|
|
CMD_SHL = 4'b0101, // result = op1 << op2[4:0]
|
|
CMD_SHR = 4'b0110 // result = op1 >> op2[4:0]
|
|
} calc_cmd_e;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Calc1 response encoding (see Vezba 5, Tabela 8).
|
|
//-----------------------------------------------------------------------------
|
|
typedef enum bit [RESP_WIDTH-1:0] {
|
|
RESP_NONE = 2'b00, // no response this cycle
|
|
RESP_SUCCESS = 2'b01, // operation successful, data on out_dataX
|
|
RESP_ERROR = 2'b10 // overflow / underflow / invalid command
|
|
// 2'b11 is unused
|
|
} calc_resp_e;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sequence item / transaction.
|
|
// - Stimulus (rand) : port, cmd, op1, op2, delay
|
|
// - Observed (non-rand) : resp, result (filled in by the monitor)
|
|
//-----------------------------------------------------------------------------
|
|
class calc_seq_item extends uvm_sequence_item;
|
|
|
|
// --- stimulus fields ---------------------------------------------------
|
|
rand bit [1:0] port; // target port 0..3 (-> req1..req4)
|
|
rand bit [CMD_WIDTH-1:0] cmd; // raw 4-bit command (allows invalid)
|
|
rand bit [DATA_WIDTH-1:0] op1; // operand 1
|
|
rand bit [DATA_WIDTH-1:0] op2; // operand 2
|
|
rand int unsigned delay; // idle cycles before issuing the request
|
|
|
|
// --- observed fields (driven by the monitor) ---------------------------
|
|
bit [RESP_WIDTH-1:0] resp; // observed out_respX
|
|
bit [DATA_WIDTH-1:0] result; // observed out_dataX
|
|
|
|
// --- constraints --------------------------------------------------------
|
|
// A real request always carries a command; NOP would produce no response.
|
|
constraint c_no_nop { cmd != CMD_NOP; }
|
|
|
|
// By default favour the four legal commands, but keep a small probability
|
|
// of an illegal command so the random regression exercises that path too.
|
|
constraint c_cmd_dist {
|
|
cmd dist {
|
|
CMD_ADD := 25,
|
|
CMD_SUB := 25,
|
|
CMD_SHL := 20,
|
|
CMD_SHR := 20,
|
|
[4'h3:4'h4] :/ 5, // illegal
|
|
4'h7 :/ 5 // illegal
|
|
};
|
|
}
|
|
|
|
constraint c_delay { delay inside {[0:6]}; }
|
|
|
|
`uvm_object_utils_begin(calc_seq_item)
|
|
`uvm_field_int (port, UVM_DEFAULT)
|
|
`uvm_field_int (cmd, UVM_DEFAULT)
|
|
`uvm_field_int (op1, UVM_DEFAULT)
|
|
`uvm_field_int (op2, UVM_DEFAULT)
|
|
`uvm_field_int (delay, UVM_DEFAULT | UVM_DEC)
|
|
`uvm_field_int (resp, UVM_DEFAULT)
|
|
`uvm_field_int (result, UVM_DEFAULT)
|
|
`uvm_object_utils_end
|
|
|
|
function new (string name = "calc_seq_item");
|
|
super.new(name);
|
|
endfunction
|
|
|
|
// True when cmd is one of the four legal Calc1 commands.
|
|
function bit is_legal_cmd();
|
|
return (cmd inside {CMD_ADD, CMD_SUB, CMD_SHL, CMD_SHR});
|
|
endfunction
|
|
|
|
// Compact one-line description, handy in logs.
|
|
function string convert2string();
|
|
return $sformatf("port=%0d cmd=%s(0x%0h) op1=0x%08h op2=0x%08h -> resp=%s data=0x%08h",
|
|
port+1, cmd2string(), cmd, op1, op2, resp2string(), result);
|
|
endfunction
|
|
|
|
function string cmd2string();
|
|
case (cmd)
|
|
CMD_NOP : return "NOP";
|
|
CMD_ADD : return "ADD";
|
|
CMD_SUB : return "SUB";
|
|
CMD_SHL : return "SHL";
|
|
CMD_SHR : return "SHR";
|
|
default : return "INVALID";
|
|
endcase
|
|
endfunction
|
|
|
|
function string resp2string();
|
|
case (resp)
|
|
RESP_NONE : return "NONE";
|
|
RESP_SUCCESS : return "SUCCESS";
|
|
RESP_ERROR : return "ERROR";
|
|
default : return "RSVD";
|
|
endcase
|
|
endfunction
|
|
|
|
endclass : calc_seq_item
|
|
|
|
`endif
|