diff options
Diffstat (limited to 'midterm')
| -rw-r--r-- | midterm/SRC/bfm.sv | 53 | ||||
| -rw-r--r-- | midterm/SRC/duv.sv | 45 | ||||
| -rw-r--r-- | midterm/SRC/interface.sv | 19 | ||||
| -rw-r--r-- | midterm/SRC/macro.svh | 14 | ||||
| -rw-r--r-- | midterm/SRC/scoreboard_monitor.sv | 63 | ||||
| -rw-r--r-- | midterm/SRC/tb.sv | 48 | ||||
| -rw-r--r-- | midterm/SRC/transaction.sv | 15 | ||||
| -rw-r--r-- | midterm/SRC/typedef_pkg.sv | 11 |
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 |