`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