Files
fvh_vezbe/code/vezba10/verif/calc_scoreboard.sv

117 lines
4.6 KiB
Systemverilog
Raw Normal View History

2026-06-12 07:53:32 +02:00
`ifndef CALC_SCOREBOARD_SV
`define CALC_SCOREBOARD_SV
//-----------------------------------------------------------------------------
// Calc1 scoreboard (self-checking, reference-model based - Vezba 10).
//
// For every transaction collected by the monitor, the embedded reference model
// (predictor) computes the expected response/result from the stimulus and
// compares it against what the DUT actually produced. Mismatches are reported
// as UVM_ERROR.
//-----------------------------------------------------------------------------
class calc_scoreboard extends uvm_scoreboard;
// control fields
bit checks_enable = 1;
bit coverage_enable = 1;
// TLM port connecting the scoreboard to the monitor
uvm_analysis_imp#(calc_seq_item, calc_scoreboard) item_collected_imp;
// bookkeeping
int unsigned num_of_tr;
int unsigned num_passed;
int unsigned num_failed;
`uvm_component_utils_begin(calc_scoreboard)
`uvm_field_int(checks_enable, UVM_DEFAULT)
`uvm_field_int(coverage_enable, UVM_DEFAULT)
`uvm_component_utils_end
function new(string name = "calc_scoreboard", uvm_component parent = null);
super.new(name,parent);
item_collected_imp = new("item_collected_imp", this);
endfunction : new
//--------------------------------------------------------------------------
// Reference model / predictor.
// Computes the expected response and result for a Calc1 command, following
// the functional specification (Vezba 5, Tabela 6/7/8).
// All arithmetic is unsigned.
//--------------------------------------------------------------------------
function void predict(input bit [CMD_WIDTH-1:0] cmd,
input bit [DATA_WIDTH-1:0] op1,
input bit [DATA_WIDTH-1:0] op2,
output bit [RESP_WIDTH-1:0] exp_resp,
output bit [DATA_WIDTH-1:0] exp_data);
bit [DATA_WIDTH:0] tmp; // one extra bit to catch carry/borrow
exp_data = '0;
case (cmd)
CMD_ADD : begin
tmp = {1'b0, op1} + {1'b0, op2};
if (tmp[DATA_WIDTH]) exp_resp = RESP_ERROR; // overflow
else begin exp_resp = RESP_SUCCESS; exp_data = tmp[DATA_WIDTH-1:0]; end
end
CMD_SUB : begin
if (op1 < op2) exp_resp = RESP_ERROR; // underflow
else begin exp_resp = RESP_SUCCESS; exp_data = op1 - op2; end
end
CMD_SHL : begin
exp_resp = RESP_SUCCESS;
exp_data = op1 << op2[4:0];
end
CMD_SHR : begin
exp_resp = RESP_SUCCESS;
exp_data = op1 >> op2[4:0];
end
default : begin
exp_resp = RESP_ERROR; // invalid command
end
endcase
endfunction : predict
//--------------------------------------------------------------------------
// Analysis-port callback: invoked by the monitor for each collected item.
//--------------------------------------------------------------------------
function void write(calc_seq_item tr);
bit [RESP_WIDTH-1:0] exp_resp;
bit [DATA_WIDTH-1:0] exp_data;
bit ok;
num_of_tr++;
if (!checks_enable) return;
predict(tr.cmd, tr.op1, tr.op2, exp_resp, exp_data);
// The result data is only meaningful for a successful operation.
ok = (tr.resp === exp_resp) &&
((exp_resp !== RESP_SUCCESS) || (tr.result === exp_data));
if (ok) begin
num_passed++;
`uvm_info(get_type_name(),
$sformatf("PASS: %s | expected resp=%0d data=0x%08h",
tr.convert2string(), exp_resp, exp_data), UVM_HIGH)
end
else begin
num_failed++;
`uvm_error(get_type_name(),
$sformatf("MISMATCH on port %0d, cmd=%s op1=0x%08h op2=0x%08h : expected resp=%0d data=0x%08h, got resp=%0d data=0x%08h",
tr.port+1, tr.cmd2string(), tr.op1, tr.op2,
exp_resp, exp_data, tr.resp, tr.result))
end
endfunction : write
function void report_phase(uvm_phase phase);
`uvm_info(get_type_name(),
$sformatf("Scoreboard examined %0d transactions: %0d passed, %0d failed",
num_of_tr, num_passed, num_failed), UVM_LOW)
if (num_failed != 0)
`uvm_warning(get_type_name(),
$sformatf("%0d transaction(s) did NOT match the reference model", num_failed))
endfunction : report_phase
endclass : calc_scoreboard
`endif