summaryrefslogtreecommitdiff
path: root/midterm
diff options
context:
space:
mode:
Diffstat (limited to 'midterm')
-rw-r--r--midterm/SRC/bfm.sv53
-rw-r--r--midterm/SRC/duv.sv45
-rw-r--r--midterm/SRC/interface.sv19
-rw-r--r--midterm/SRC/macro.svh14
-rw-r--r--midterm/SRC/scoreboard_monitor.sv63
-rw-r--r--midterm/SRC/tb.sv48
-rw-r--r--midterm/SRC/transaction.sv15
-rw-r--r--midterm/SRC/typedef_pkg.sv11
8 files changed, 268 insertions, 0 deletions
diff --git a/midterm/SRC/bfm.sv b/midterm/SRC/bfm.sv
new file mode 100644
index 0000000..2d81ad6
--- /dev/null
+++ b/midterm/SRC/bfm.sv
@@ -0,0 +1,53 @@
+import typedef_pkg::*;
+
+class bfm;
+ localparam int TOTAL_TESTS = 4 * 256 * 256;
+
+ virtual intf alu_if;
+ transaction tr;
+
+ function new(virtual intf alu_if_in, transaction tr_in);
+ alu_if = alu_if_in;
+ tr = tr_in;
+ endfunction
+
+ task drive();
+ for (int op_i = 0; op_i < 4; op_i++) begin
+ for (int a_i = 0; a_i < 256; a_i++) begin
+ for (int b_i = 0; b_i < 256; b_i++) begin
+ automatic operation_t op_val = operation_t'(op_i[1:0]);
+ automatic operand_t a_val = operand_t'(a_i[7:0]);
+ automatic operand_t b_val = operand_t'(b_i[7:0]);
+
+ `RND_CHECK(std::randomize(tr.operation, tr.operand_a, tr.operand_b) with {
+ tr.operation == op_val;
+ tr.operand_a == a_val;
+ tr.operand_b == b_val;
+ })
+ drive_trxn();
+ end
+ end
+ end
+
+ $display("BFM drive complete. Total tests: %0d", TOTAL_TESTS);
+ endtask
+
+ task drive_trxn();
+ @(negedge alu_if.clk);
+
+ alu_if.op_start = 1'b1;
+ alu_if.operation = tr.operation;
+ alu_if.operand_a = tr.operand_a;
+ alu_if.operand_b = tr.operand_b;
+
+ @(negedge alu_if.clk);
+
+ alu_if.op_start = 1'b0;
+
+ @(posedge alu_if.clk);
+ @(posedge alu_if.clk);
+ @(negedge alu_if.clk);
+
+ tr.actual_result = alu_if.result;
+ endtask
+endclass
diff --git a/midterm/SRC/duv.sv b/midterm/SRC/duv.sv
new file mode 100644
index 0000000..f2ae28e
--- /dev/null
+++ b/midterm/SRC/duv.sv
@@ -0,0 +1,45 @@
+module duv (
+ input logic clk,
+ input logic op_start,
+ input logic [1:0] operation,
+ input logic [7:0] operand_a,
+ input logic [7:0] operand_b,
+ output logic [15:0] result
+);
+ logic [1:0] operation_d1;
+ logic [7:0] operand_a_d1;
+ logic [7:0] operand_b_d1;
+ logic valid_d1;
+ logic [1:0] operation_d2;
+ logic [7:0] operand_a_d2;
+ logic [7:0] operand_b_d2;
+ logic valid_d2;
+
+ always_ff @(posedge clk) begin
+ valid_d1 <= op_start;
+
+ if (op_start == 1'b1) begin
+ operation_d1 <= operation;
+ operand_a_d1 <= operand_a;
+ operand_b_d1 <= operand_b;
+ end
+
+ valid_d2 <= valid_d1;
+
+ if (valid_d1 == 1'b1) begin
+ operation_d2 <= operation_d1;
+ operand_a_d2 <= operand_a_d1;
+ operand_b_d2 <= operand_b_d1;
+ end
+
+ if (valid_d2 == 1'b1) begin
+ case (operation_d2)
+ 2'b00: result <= (operand_a_d2 + operand_b_d2) & 16'h01FF;
+ 2'b01: result <= operand_a_d2 * operand_b_d2;
+ 2'b10: result <= (operand_a_d2 | operand_b_d2) & 16'h00FF;
+ 2'b11: result <= (operand_a_d2 & operand_b_d2) & 16'h00FF;
+ default: result <= 16'h0000;
+ endcase
+ end
+ end
+endmodule : duv
diff --git a/midterm/SRC/interface.sv b/midterm/SRC/interface.sv
new file mode 100644
index 0000000..36cb3c2
--- /dev/null
+++ b/midterm/SRC/interface.sv
@@ -0,0 +1,19 @@
+interface intf (
+ input logic clk
+);
+ import typedef_pkg::*;
+
+ logic op_start = 1'b0;
+ operation_t operation = ADD;
+ operand_t operand_a = '0;
+ operand_t operand_b = '0;
+ result_t result;
+
+ clocking cb @(posedge clk);
+ output op_start;
+ output operation;
+ output operand_a;
+ output operand_b;
+ input result;
+ endclocking
+endinterface : intf
diff --git a/midterm/SRC/macro.svh b/midterm/SRC/macro.svh
new file mode 100644
index 0000000..2780a42
--- /dev/null
+++ b/midterm/SRC/macro.svh
@@ -0,0 +1,14 @@
+`ifndef MACRO_SVH
+ `define MACRO_SVH
+
+ `define FAIL_UNLESS_EQUAL(a,b,c="") \
+ if ((a) !== (b)) begin \
+ $display("FAIL_UNLESS_EQUAL[%s]: Expected %h but actual value is %h.", c, a, b); \
+ end
+
+ `define RND_CHECK(a) \
+ if (!(a)) begin \
+ $display("Randomization failure. Simulation halted."); \
+ $finish; \
+ end
+`endif
diff --git a/midterm/SRC/scoreboard_monitor.sv b/midterm/SRC/scoreboard_monitor.sv
new file mode 100644
index 0000000..a51baa0
--- /dev/null
+++ b/midterm/SRC/scoreboard_monitor.sv
@@ -0,0 +1,63 @@
+import typedef_pkg::*;
+
+class scoreboard_monitor;
+ localparam int TOTAL_TESTS = 4 * 256 * 256;
+
+ virtual intf alu_if;
+ transaction tr;
+
+ function result_t compute_expected_value(input operation_t operation, input operand_t operand_a,
+ input operand_t operand_b, input result_t actual_result);
+ automatic result_t expected_result;
+
+ case (operation)
+ ADD: begin
+ expected_result = (operand_a + operand_b) & 16'h01FF;
+ `FAIL_UNLESS_EQUAL(expected_result & 16'h01FF, actual_result & 16'h01FF, $sformatf(
+ "ADD a=%0d b=%0d", operand_a, operand_b))
+ end
+ MULT: begin
+ expected_result = operand_a * operand_b;
+ `FAIL_UNLESS_EQUAL(expected_result, actual_result, $sformatf(
+ "MULT a=%0d b=%0d", operand_a, operand_b))
+ end
+ OR: begin
+ expected_result = (operand_a | operand_b) & 16'h00FF;
+ `FAIL_UNLESS_EQUAL(expected_result & 16'h00FF, actual_result & 16'h00FF, $sformatf(
+ "OR a=%0d b=%0d", operand_a, operand_b))
+ end
+ AND: begin
+ expected_result = (operand_a & operand_b) & 16'h00FF;
+ `FAIL_UNLESS_EQUAL(expected_result & 16'h00FF, actual_result & 16'h00FF, $sformatf(
+ "AND a=%0d b=%0d", operand_a, operand_b))
+ end
+ default: begin
+ expected_result = '0;
+ end
+ endcase
+
+ return expected_result;
+ endfunction
+
+ task check();
+ for (int i = 0; i < TOTAL_TESTS; i++) begin
+ @(posedge alu_if.clk iff (alu_if.op_start == 1'b1));
+
+ tr.operation = alu_if.operation;
+ tr.operand_a = alu_if.operand_a;
+ tr.operand_b = alu_if.operand_b;
+
+ @(posedge alu_if.clk);
+ @(posedge alu_if.clk);
+ @(negedge alu_if.clk);
+
+ tr.actual_result = alu_if.result;
+ tr.expected_result =
+ compute_expected_value(tr.operation, tr.operand_a, tr.operand_b, tr.actual_result);
+
+ tr.print();
+ end
+
+ $display("Scoreboard check complete. Total tests: %0d", TOTAL_TESTS);
+ endtask
+endclass
diff --git a/midterm/SRC/tb.sv b/midterm/SRC/tb.sv
new file mode 100644
index 0000000..2d17084
--- /dev/null
+++ b/midterm/SRC/tb.sv
@@ -0,0 +1,48 @@
+`include "macro.svh"
+`include "typedef_pkg.sv"
+`include "interface.sv"
+`include "transaction.sv"
+`include "scoreboard_monitor.sv"
+`include "bfm.sv"
+
+module tb;
+ localparam int TOTAL_TESTS = 4 * 256 * 256;
+
+ logic clk = 1'b0;
+
+ intf intf0 (.clk(clk));
+
+ transaction tr_drv;
+ transaction tr_mon;
+ bfm bfm0;
+ scoreboard_monitor sb_mon0;
+
+ duv ALU0 (
+ .clk(intf0.clk),
+ .op_start(intf0.op_start),
+ .operation(intf0.operation),
+ .operand_a(intf0.operand_a),
+ .operand_b(intf0.operand_b),
+ .result(intf0.result)
+ );
+
+ always #1ns clk = ~clk;
+
+ initial begin
+ tr_drv = new();
+ tr_mon = new();
+ bfm0 = new(intf0, tr_drv);
+ sb_mon0 = new();
+ sb_mon0.alu_if = intf0;
+ sb_mon0.tr = tr_mon;
+
+ fork
+ bfm0.drive();
+ sb_mon0.check();
+ join
+
+ $display("All tests passed! Total tests: %0d", TOTAL_TESTS);
+ $display("Finished Successfully!");
+ $finish;
+ end
+endmodule : tb
diff --git a/midterm/SRC/transaction.sv b/midterm/SRC/transaction.sv
new file mode 100644
index 0000000..1253fc2
--- /dev/null
+++ b/midterm/SRC/transaction.sv
@@ -0,0 +1,15 @@
+import typedef_pkg::*;
+
+class transaction;
+ rand operation_t operation;
+ rand operand_t operand_a;
+ rand operand_t operand_b;
+
+ result_t expected_result;
+ result_t actual_result;
+
+ function void print();
+ $display("op=%s operand_a=%0d operand_b=%0d expected=%0d actual=%0d", operation.name(),
+ operand_a, operand_b, expected_result, actual_result);
+ endfunction
+endclass
diff --git a/midterm/SRC/typedef_pkg.sv b/midterm/SRC/typedef_pkg.sv
new file mode 100644
index 0000000..fd67002
--- /dev/null
+++ b/midterm/SRC/typedef_pkg.sv
@@ -0,0 +1,11 @@
+package typedef_pkg;
+ typedef enum logic [1:0] {
+ ADD = 2'b00,
+ MULT = 2'b01,
+ OR = 2'b10,
+ AND = 2'b11
+ } operation_t;
+
+ typedef logic [7:0] operand_t;
+ typedef logic [15:0] result_t;
+endpackage : typedef_pkg