diff options
| author | Fuwn <[email protected]> | 2026-02-13 23:23:19 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-13 23:23:19 -0800 |
| commit | 583bec7ffd3c2809ea41aa8a518f53403af3efaa (patch) | |
| tree | 551fa62ee04d40616db4f2375176c362ae6f3cbc | |
| download | cst456-583bec7ffd3c2809ea41aa8a518f53403af3efaa.tar.xz cst456-583bec7ffd3c2809ea41aa8a518f53403af3efaa.zip | |
Initial commit
56 files changed, 1227 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2504eee --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +*.log +*.pb +*.jou +*.wdb +xsim.dir +.Xil +*.zip diff --git a/homework_1/CST456 Embedded System Testing-HW1.md b/homework_1/CST456 Embedded System Testing-HW1.md new file mode 100644 index 0000000..2d1f8f7 --- /dev/null +++ b/homework_1/CST456 Embedded System Testing-HW1.md @@ -0,0 +1,47 @@ +# CST456 Embedded System Testing-HW1 + +**CST456 Embedded System Testing** + +**Homework 1** + +We wish to design a one-input one-output sequence detector (Mealy Machine) that produces an output value 1 every time the sequences 1100 or 1011 is detected and an output value 0 at all other times. Overlapping sequences are accepted; for example, if the input sequence is **11110000101101100** then the corresponding output sequence is **00000100000100101**. a)Draw a state diagram (State diagram must have the minimum number of states). + +b)Write a SystemVerilog code **(duv.sv)** to implement it. + +c)Write a simple SytemVerilog testbench **(tb.sv)** to test it. + +*Design must have an active high reset. The design should be asynchronous. Time step, current state, reset, input, and output must be printed in the **cmd** command window.* + +**Note:** In your simulation use **Vivado** in command line mode. But first create a directory as HW1 and create two more directories under HW1: SRC and SIM. Put your tb.sv and duv.sv codes under SRC directory. + +Create a new file and name it as *xsim_cfg.tcl* with the following content: log_wave -recursive * + +run all + +exit + +and save it under SIM directory. + +Now open up a command prompt (cmd) and change the directory to SIM. In cmd, under SIM directory run the following commands: + +*call C:\Xilinx\Vivado\2023.2\bin\xvlog --sv ../SRC/duv.sv ../SRC/tb.sv* + +*call C:\Xilinx\Vivado\2023.2\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot call C:\Xilinx\Vivado\2023.2\bin\xsim duv_tb_snapshot -R* + +*call C:\Xilinx\Vivado\2023.2\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl* + +*call C:\Xilinx\Vivado\2023.2\bin\xsim --gui duv_tb_snapshot.wdb* + +We also want to check the code coverage of our design for that purpose run the following + +commands in cmd under SIM directory: + +*call C:\Xilinx\Vivado\2023.2\bin\xelab -svlog ../SRC/duv.sv -svlog ../SRC/tb.sv -cc_type sbct* + +- *cc_db DB1 -cc_dir ./cRun1 -R* + +*call C:\Xilinx\Vivado\2023.2\bin\xcrg -cc_db DB1 -cc_dir ./cRun1 -cc_report ./cReport1* + +You can find the coverage report in *./cReport1/dashboard.html* + +Submit your state diagram and HW1 directory. diff --git a/homework_1/CST456 Embedded System Testing-HW1.pdf b/homework_1/CST456 Embedded System Testing-HW1.pdf Binary files differnew file mode 100644 index 0000000..d14f70a --- /dev/null +++ b/homework_1/CST456 Embedded System Testing-HW1.pdf diff --git a/homework_1/SIM/build_simulation.bat b/homework_1/SIM/build_simulation.bat new file mode 100644 index 0000000..b41e8c9 --- /dev/null +++ b/homework_1/SIM/build_simulation.bat @@ -0,0 +1,4 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/duv.sv ../SRC/tb.sv +call C:\Xilinx\Vivado\2022.1\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot +pause diff --git a/homework_1/SIM/run_simulation.bat b/homework_1/SIM/run_simulation.bat new file mode 100644 index 0000000..a1a1417 --- /dev/null +++ b/homework_1/SIM/run_simulation.bat @@ -0,0 +1,7 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/duv.sv ../SRC/tb.sv +call C:\Xilinx\Vivado\2022.1\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot -R +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl +call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb +pause diff --git a/homework_1/SIM/run_waveform.bat b/homework_1/SIM/run_waveform.bat new file mode 100644 index 0000000..b3ddc9a --- /dev/null +++ b/homework_1/SIM/run_waveform.bat @@ -0,0 +1,3 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl +call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb diff --git a/homework_1/SIM/xsim_cfg.tcl b/homework_1/SIM/xsim_cfg.tcl new file mode 100644 index 0000000..b7c49f5 --- /dev/null +++ b/homework_1/SIM/xsim_cfg.tcl @@ -0,0 +1,3 @@ +log_wave -recursive *
+run all
+exit
\ No newline at end of file diff --git a/homework_1/SRC/duv.sv b/homework_1/SRC/duv.sv new file mode 100644 index 0000000..149f574 --- /dev/null +++ b/homework_1/SRC/duv.sv @@ -0,0 +1,51 @@ +module duv ( + input logic clock, + input logic reset, + input logic input_, + output logic output_ +); + localparam S0 = 3'b000, // Initial + S1 = 3'b001, // Seen "1" + S2 = 3'b010, // Seen "11" + S3 = 3'b011, // Seen "10" + S4 = 3'b100, // Seen "110" + S5 = 3'b101; // Seen "101" + + logic [2:0] state, next_state; + + // State register with asynchronous reset + always_ff @(posedge clock or posedge reset) begin + if (reset) state <= S0; + else state <= next_state; + end + + // Next state and output logic + always_comb begin + next_state = state; + output_ = 1'b0; + + case (state) + S0: next_state = input_ ? S1 : S0; + S1: next_state = input_ ? S2 : S3; + S2: next_state = input_ ? S2 : S4; + S3: next_state = input_ ? S5 : S0; + S4: begin + if (input_) begin + next_state = S5; + end else begin + next_state = S0; + output_ = 1'b1; // Detected "1100" + end + end + S5: begin + if (input_) begin + next_state = S2; + output_ = 1'b1; // Detected "1011" + end else begin + next_state = S3; + end + end + default: next_state = S0; + endcase + end +endmodule diff --git a/homework_1/SRC/macro.svh b/homework_1/SRC/macro.svh new file mode 100644 index 0000000..284b9ae --- /dev/null +++ b/homework_1/SRC/macro.svh @@ -0,0 +1,10 @@ +`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); \ + $finish; \ + end +`endif diff --git a/homework_1/SRC/tb.sv b/homework_1/SRC/tb.sv new file mode 100644 index 0000000..89bd1ae --- /dev/null +++ b/homework_1/SRC/tb.sv @@ -0,0 +1,52 @@ +`include "macro.svh" + +module tb; + logic clock = 1'b0; + logic reset; + logic input_; + logic output_; + + localparam int SEQUENCE_LENGTH = 17; + + logic [0:SEQUENCE_LENGTH-1] test_input = 17'b11110000101101100; + logic [0:SEQUENCE_LENGTH-1] expected_output = 17'b00000100000100101; + + duv DUT ( + .clock, + .reset, + .input_, + .output_ + ); + + always #1ns clock = ~clock; + + // Test sequence + initial begin + automatic int test_count = 0; + + // Initialise + reset = 1'b1; + input_ = 1'b0; + + // Hold reset for 2 cycles + repeat (2) @(posedge clock); + + reset = 1'b0; + + // Apply test sequence + for (int i = 0; i < SEQUENCE_LENGTH; i++) begin + input_ = test_input[i]; + + @(posedge clock); + + // Check output + `FAIL_UNLESS_EQUAL(expected_output[i], output_, $sformatf("step=%0d input=%b", i + 1, input_)) + + test_count += 1; + end + + $display("All tests passed! Total tests: %0d", test_count); + $display("Finished successfully!"); + $finish; + end +endmodule diff --git a/homework_1/state_diagram/state_diagram.mmd b/homework_1/state_diagram/state_diagram.mmd new file mode 100644 index 0000000..b1de1e7 --- /dev/null +++ b/homework_1/state_diagram/state_diagram.mmd @@ -0,0 +1,27 @@ +stateDiagram-v2 + [*] --> S0 + + S0: Initial + S1: Seen "1" + S2: Seen "11" + S3: Seen "10" + S4: Seen "110" + S5: Seen "101" + + S0 --> S0: 0/0 + S0 --> S1: 1/0 + + S1 --> S3: 0/0 + S1 --> S2: 1/0 + + S2 --> S4: 0/0 + S2 --> S2: 1/0 + + S3 --> S0: 0/0 + S3 --> S5: 1/0 + + S4 --> S0: 0/1 (1100) + S4 --> S5: 1/0 + + S5 --> S3: 0/0 + S5 --> S2: 1/1 (1011) diff --git a/homework_1/state_diagram/state_diagram.png b/homework_1/state_diagram/state_diagram.png Binary files differnew file mode 100644 index 0000000..cad0643 --- /dev/null +++ b/homework_1/state_diagram/state_diagram.png diff --git a/lab_1/CST456 LAB1.rar b/lab_1/CST456 LAB1.rar Binary files differnew file mode 100644 index 0000000..3fc3009 --- /dev/null +++ b/lab_1/CST456 LAB1.rar diff --git a/lab_1/CST456 Lab1.md b/lab_1/CST456 Lab1.md new file mode 100644 index 0000000..a80ab6e --- /dev/null +++ b/lab_1/CST456 Lab1.md @@ -0,0 +1,57 @@ +# CST456 Lab1 + +**CST456 – Lab 1** + +**Simple Testbench** + +**Objective** + +The objective of this lab is to implement a simple testbench to exhaustively test the operations and operands of a synchronous arithmetic and logic unit (ALU). + +**Design Under Verification (DUV)** The ALU contains the following ports: + +| **Port Name** | **Signal Type** | **Direction** | **Number of Bits** | +| --- | --- | --- | --- | +| clk | Clock | Input | 1 | +| op_start | Control | Input | 1 | +| operation | Control | Input | 2 | +| operand_a | Data | Input | 8 | +| operand_b | Data | Input | 8 | +| result | Data | Output | 16 | + +At the rising edge of the clock, if op_start is asserted (== 1’b1) then the operation, operand_a, and operand_b signals are latched into the ALU. Exactly two clock cycles later the result of the operation is read from the result port. The ALU supports the following operations: + +| **Name** | **Value** | **Description** | +| --- | --- | --- | +| ADD | 2’b00 | operand_a is added to operand_b. Only the lower nine bits of the result are used. | +| MULT | 2’b01 | operand_a is multiplied with operand_b. This is an unsigned operation and all sixteen bits of the result are used. | +| OR | 2’b10 | operand_a is bitwise ORed with operand_b. Only the lower eight bits of the result are used. | +| AND | 2’b11 | operand_a is bitwise ANDed with operand_b. Only the lower eight bits of the result are used. | + +Figure 1 shows a timing diagram for the addition operation, where 1 + 3 = 4. + + + +**Figure 1 - Timing diagram for an addition operation.** + +**Testbench** + +Edit the tb.sv file and create a testbench to exhaustively test all the operations and operand combinations that the ALU supports. To do this, create three nested for-loops. The first for-loop enumerates through all four operations, the second for-loop enumerates through all 256 values for operand_a, and the third for-loop enumerates through all 256 values for operand_b. Use the `FAIL_UNLESS_EQUAL macro to check the expected result with the tested result. The DUV does not contain any bugs, so the testing is expected to be successful. + +Simulate your testbench in Xilinx Vivado (**version 2022.1**) using following commands: + +(simulation commands must be run under SIM directory) + +*call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/tb.sv ../SRC/duv.svp* + +*call C:\Xilinx\Vivado\2022.1\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot* + +*call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot -R* + +*call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl* + +*call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb* + +**Lab Submission** + +Zip all the contents of the lab directory and submit it to Canvas. diff --git a/lab_1/CST456 Lab1.pdf b/lab_1/CST456 Lab1.pdf Binary files differnew file mode 100644 index 0000000..6799032 --- /dev/null +++ b/lab_1/CST456 Lab1.pdf diff --git a/lab_1/SIM/run_simulation.bat b/lab_1/SIM/run_simulation.bat new file mode 100644 index 0000000..7522486 --- /dev/null +++ b/lab_1/SIM/run_simulation.bat @@ -0,0 +1,5 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/tb.sv ../SRC/duv.svp +call C:\Xilinx\Vivado\2022.1\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot -R +pause diff --git a/lab_1/SIM/run_waveform.bat b/lab_1/SIM/run_waveform.bat new file mode 100644 index 0000000..b3ddc9a --- /dev/null +++ b/lab_1/SIM/run_waveform.bat @@ -0,0 +1,3 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl +call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb diff --git a/lab_1/SIM/xsim_cfg.tcl b/lab_1/SIM/xsim_cfg.tcl new file mode 100644 index 0000000..b7c49f5 --- /dev/null +++ b/lab_1/SIM/xsim_cfg.tcl @@ -0,0 +1,3 @@ +log_wave -recursive *
+run all
+exit
\ No newline at end of file diff --git a/lab_1/SRC/duv.svp b/lab_1/SRC/duv.svp new file mode 100644 index 0000000..d898852 --- /dev/null +++ b/lab_1/SRC/duv.svp @@ -0,0 +1,43 @@ +`pragma protect begin_protected +`pragma protect version = 2 +`pragma protect encrypt_agent = "XILINX" +`pragma protect encrypt_agent_info = "Xilinx Encryption Tool 2015" +`pragma protect begin_commonblock +`pragma protect control error_handling = "delegated" +`pragma protect control runtime_visibility = "delegated" +`pragma protect control child_visibility = "delegated" +`pragma protect end_commonblock +`pragma protect begin_toolblock +`pragma protect rights_digest_method="sha256" +`pragma protect key_keyowner = "Xilinx", key_keyname= "xilinxt_2017_05", key_method = "rsa", key_block +wnJhtJ3GIW1M9VKyev/LmAfVO1OKPxKeF/8nWwWO/7l+ueLOJ/EtgGNavipcpgYPcoX/SZH+UTkU +uHmlUF7gSyXa4K4VG1RbCrEnUhg20PGrwJMzSjwXDJvpZx/DIM+nAt5W6nXByiA6gBo3Yh+bCSHd +IRZB3uYufRfb2EgSFpaX2RcL6F8mE2mZfvVr3QdwdRf39ZwaXioorrultMqD0wI9AiSaBjxjR2hF +5oqDFnGkT8r1+e2VCjOc+6iVj1Hulo3KejilS/G4XLHLisTBDG8hkkn4+D/g8vr36KnrX+T3BmQp +8+y/M6FgMRW6iay2WQUiLq4QiX358hh7PZwaFw== + +`pragma protect control xilinx_configuration_visible = "false" +`pragma protect control xilinx_enable_modification = "false" +`pragma protect control xilinx_enable_probing = "false" +`pragma protect end_toolblock="IOTwTA95tg/n6T/LInLo1CH3T13Xu/6VnmWogywXunI=" +`pragma protect data_method = "AES128-CBC" +`pragma protect encoding = (enctype = "BASE64", line_length = 76, bytes = 960) +`pragma protect data_block +R3fS3d9kAiYUf7ZsnVv+neFIuDR53BJsdVJaNnnP4qLJ/UWZephL6sIxC8HkI8qgSzwDOTHGjf6M +WfxDOJuhZYp5BvTAw0WPA58HwODoyc9y7tHJWZ8rynzyDf4oN+S5n6KZoXNo70MJa07ujBqYBEaS +GNolgbeyPfh1KjuYi4+5w7B90TT4/j+p6jpdDRbNQ9rhbaZ7hD1xIg2vOEyjPR/gThWH+NLcLefy +Wtu52X88OCkjxyKQcZUw3SkP01yHptPO5Ozenf8LQz6otOkTsyWNF1kPBpQN6bfnfMjYjQ1bmG1Q +oMwwnP9o1MtsNunuTddCjQL19ylZs+IL+0tQ6Qcct3xfABF4Za19FdptFAEh5wjodp7678nUKAS1 +Pa4hucCPVdRVUzGdpXXQe1m/PRVXczQ6wo0ATtLotzdjtBr6GaLcSggGMCxTSG33q6I9Bb4fH6W6 +jbCmnH6ARbfsaI4bc8+2X6fdppEm/CGWqXoTGGRiVJyooJzEQRc/q0rsvlRNqdjj0CGl5Wu4QmeW +kiyWjrCXhOQX0AaYUkC2K73AlK8H/midffhjvn8O8F4shC/L5tqEinFnkIxadDUgw+m3qWwLUWcZ +jCdXpBh3khpBOLfwjP1DLeWoVGUYUAfoZBjjl17JiFH6ejwmloj98TtDdNUuoj3El8dLvLvZ4Kjz +4x7b5Fc5QDMnrEWeYaxnMWAHx5z0gIFIC/n6ClmSuWaPo8lXdqF8joITLLpSZKn2G0f4oh2So3hC +aHz6P4r/l/eS5dSVI6tJKMtb7xaOV4/k/CcKJym3tlhX3KEJqm+9wCEbI8EhNWjP45iSsOPp5UwG +rtYxqoshs2NlTR4NvYh0COuFd+3a7eo3o0yhZkvvfaCGaoP/ILM9siZZJ4H8Bv/pz51AjoD+E5QI +nDFuJcncF9/tAeyN8Fy9V49D2Z9JMfvoRRGIkOmCVc6431/VumsZ9VA5rP1ZXxd4ivZXMAKZrwiL +6XXD+Q8qSVhW9JiLZoGT+0rljwmzSXceVZm2NLo860jVfVaxqpOYc0QvyQZBYrob6R9NsqWQCYBR +emSfMsUPQOwHF3a8NhIfCcbhE35LM6dbQYBWPM/PyBk+8S2eGtor8IL4OGlKiUqut63f4ONbKKul +lkNrgxFEbDY7Kxn4+H3NHaGRtGXHUXG5eqbZHLZO34vDh0y4+oJ/Key9Ms7kYXCk4/RrMxgcTZSW +EK+lLo23iHrN1wB+mWPqNbJ72zxu2xZKE+P3hOZEMlT5F8iOGreHbvFdOG9DcjhT +`pragma protect end_protected diff --git a/lab_1/SRC/macro.svh b/lab_1/SRC/macro.svh new file mode 100644 index 0000000..284b9ae --- /dev/null +++ b/lab_1/SRC/macro.svh @@ -0,0 +1,10 @@ +`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); \ + $finish; \ + end +`endif diff --git a/lab_1/SRC/tb.sv b/lab_1/SRC/tb.sv new file mode 100644 index 0000000..0230705 --- /dev/null +++ b/lab_1/SRC/tb.sv @@ -0,0 +1,115 @@ +// Contains the FAIL_UNLESS_EQUAL macro. +`include "macro.svh" + +/* [Step 2] Instantiate the DUV module. The module is declared as + + 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 + ); + */ + +module tb; + parameter FULL_TEST = 1; + + // [Step 1] Declare signals. Intialize the clk signal with a value of 1'b0. + + logic clk = 1'b0; + logic op_start; + logic [1:0] operation; + logic [7:0] operand_a; + logic [7:0] operand_b; + logic [15:0] result; + + // [Step 2] Instantiate the DUV module. The module is declared as + + duv ALU0 ( + .clk, + .op_start, + .operation, + .operand_a, + .operand_b, + .result + ); + + // [Step 3] Always block to generate the clock. + + always #1ns clk = ~clk; + + // [Step 4] Test the DUV using an initial block. Be sure to initialize all DUV input variables, and use the $finish system task + + initial begin + automatic logic [15:0] expected_result; + automatic int test_count = 0; + + // Initialise all inputs + op_start = 1'b0; + operation = 2'b00; + operand_a = 8'h00; + operand_b = 8'h00; + + // Wait for initial setup and reset + repeat (3) @(posedge clk); + + // Exhaustively test all combinations + for (int op = 0; op < 4; op++) begin + for (int a = 0; a < (FULL_TEST ? 256 : 16); a++) begin + for (int b = 0; b < (FULL_TEST ? 256 : 16); b++) begin + // Set up inputs and calculate expected result first + operation = op[1:0]; + operand_a = a[7:0]; + operand_b = b[7:0]; + + // Calculate expected result before starting operation + case (operation) + 2'b00: expected_result = (operand_a + operand_b) & 16'h01FF; // ADD + 2'b01: expected_result = operand_a * operand_b; // MULT + 2'b10: expected_result = (operand_a | operand_b) & 16'h00FF; // OR + 2'b11: expected_result = (operand_a & operand_b) & 16'h00FF; // AND + endcase + + // Start the operation + op_start = 1'b1; + + // Wait for rising edge to latch inputs + @(posedge clk); + + op_start = 1'b0; + + // Wait 2 more clock cycles for result + @(posedge clk); + @(posedge clk); + + // Compare only relevant bits based on operation + case (operation) + 2'b00: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h01FF, $sformatf( + "ADD a=%0d b=%0d", operand_a, operand_b)) + 2'b01: + `FAIL_UNLESS_EQUAL(expected_result, result, $sformatf( + "MULT a=%0d b=%0d", operand_a, operand_b)) + 2'b10: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf( + "OR a=%0d b=%0d", operand_a, operand_b)) + 2'b11: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf( + "AND a=%0d b=%0d", operand_a, operand_b)) + endcase + + test_count += 1; + end + end + end + + $display("All tests passed! Total tests: %0d", test_count); + $display("Finished Successfully!"); + $finish; + end // Initial end +endmodule : tb diff --git a/lab_1/image1.png b/lab_1/image1.png Binary files differnew file mode 100644 index 0000000..b337587 --- /dev/null +++ b/lab_1/image1.png diff --git a/lab_2/CST456 LAB2.rar b/lab_2/CST456 LAB2.rar Binary files differnew file mode 100644 index 0000000..b47cfc9 --- /dev/null +++ b/lab_2/CST456 LAB2.rar diff --git a/lab_2/CST456 Lab2.md b/lab_2/CST456 Lab2.md new file mode 100644 index 0000000..3842121 --- /dev/null +++ b/lab_2/CST456 Lab2.md @@ -0,0 +1,81 @@ +# CST456 Lab2 + +**CST456 – Lab 2** + +**Simple Testbench with Data Types and Package** + +**Objective** + +The objective of this lab is to implement a simple testbench to exhaustively test the operations and operands of a synchronous arithmetic and logic unit (ALU) using data types from a package. + +**Design Under Verification (DUV)** The ALU contains the following ports: + +| **Port Name** | **Signal Type** | **Direction** | **Number of Bits** | **Data Type** | +| --- | --- | --- | --- | --- | +| clk | Clock | Input | 1 | logic | +| op_start | Control | Input | 1 | logic | +| operation | Control | Input | 2 | operation_t (enum) | +| operand_a | Data | Input | 8 | operand_t | +| operand_b | Data | Input | 8 | operand_t | +| result | Data | Output | 16 | result_t | + +At the rising edge of the clock, if op_start is asserted (== 1’b1) then the operation, operand_a, and operand_b signals are latched into the ALU. Exactly two clock cycles later the result of the operation is read from the result port. The ALU supports the following operations: + +| **Name** | **Value** | **Description** | +| --- | --- | --- | +| ADD | 2’b00 | operand_a is added to operand_b. Only the lower nine bits of the result are used. | +| MULT | 2’b01 | operand_a is multiplied with operand_b. This is an unsigned operation and all sixteen bits of the result are used. | +| OR | 2’b10 | operand_a is bitwise ORed with operand_b. Only the lower eight bits of the result are used. | +| AND | 2’b11 | operand_a is bitwise ANDed with operand_b. Only the lower eight bits of the result are used. | + +Figure 1 shows a timing diagram for the addition operation, where 1 + + +3 = 4. + + + +**Figure 1 - Timing diagram for an addition operation.** + +**Testbench** + +Edit the tb.sv file and create a testbench to exhaustively test all + +the operations and operand combinations that the ALU supports. The DUV + +uses data types from the typedef_pkg package declared in + +typedef_pkg.sv. + +Create a do-while loop and two nested for-loops. The do-while loop + +enumerates through all four operations, the first for-loop enumerates + +through all 256 values for operand_a, and the second for-loop + +enumerates through all 256 values for operand_b. Use the + +`FAIL_UNLESS_EQUAL macro to check the expected result with the tested + +result. The DUV does not contain any bugs, so the testing is expected + +to be successful. + +Simulate your testbench in Xilinx Vivado (**version 2023.2**) using + +following commands: + +(simulation commands must be run under SIM directory) + +*call C:\Xilinx\Vivado\2023.2\bin\xvlog -nolog -sv ../SRC/tb.sv ../SRC/duv.svp* + +*call C:\Xilinx\Vivado\2023.2\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot* + +*call C:\Xilinx\Vivado\2023.2\bin\xsim duv_tb_snapshot -R* + +*call C:\Xilinx\Vivado\2023.2\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl* + +*call C:\Xilinx\Vivado\2023.2\bin\xsim --gui duv_tb_snapshot.wdb* + +**Lab Submission** + +Zip the entire contents of the lab directory and submit it to Canvas. diff --git a/lab_2/CST456 Lab2.pdf b/lab_2/CST456 Lab2.pdf Binary files differnew file mode 100644 index 0000000..28998c9 --- /dev/null +++ b/lab_2/CST456 Lab2.pdf diff --git a/lab_2/SIM/run_simulation.bat b/lab_2/SIM/run_simulation.bat new file mode 100644 index 0000000..1a1f71f --- /dev/null +++ b/lab_2/SIM/run_simulation.bat @@ -0,0 +1,7 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/typedef_pkg.sv ../SRC/tb.sv ../SRC/duv.sv +call C:\Xilinx\Vivado\2022.1\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot -R +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl +call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb +pause diff --git a/lab_2/SIM/run_waveform.bat b/lab_2/SIM/run_waveform.bat new file mode 100644 index 0000000..b3ddc9a --- /dev/null +++ b/lab_2/SIM/run_waveform.bat @@ -0,0 +1,3 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl +call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb diff --git a/lab_2/SIM/xsim_cfg.tcl b/lab_2/SIM/xsim_cfg.tcl new file mode 100644 index 0000000..b7c49f5 --- /dev/null +++ b/lab_2/SIM/xsim_cfg.tcl @@ -0,0 +1,3 @@ +log_wave -recursive *
+run all
+exit
\ No newline at end of file diff --git a/lab_2/SRC/duv.sv b/lab_2/SRC/duv.sv new file mode 100644 index 0000000..0829654 --- /dev/null +++ b/lab_2/SRC/duv.sv @@ -0,0 +1,28 @@ +
+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 [15:0] result_tmp;
+
+always_ff @(posedge clk)
+begin
+if( op_start == 1'b1)
+begin
+case (operation)
+ 0: result_tmp = operand_a + operand_b;
+ 1: result_tmp = operand_a * operand_b;
+ 2: result_tmp = operand_a | operand_b;
+ 3: result_tmp = operand_a & operand_b;
+ endcase
+ end
+
+ result <= result_tmp;
+end
+
+endmodule : duv
\ No newline at end of file diff --git a/lab_2/SRC/macro.svh b/lab_2/SRC/macro.svh new file mode 100644 index 0000000..284b9ae --- /dev/null +++ b/lab_2/SRC/macro.svh @@ -0,0 +1,10 @@ +`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); \ + $finish; \ + end +`endif diff --git a/lab_2/SRC/tb.sv b/lab_2/SRC/tb.sv new file mode 100644 index 0000000..00daa95 --- /dev/null +++ b/lab_2/SRC/tb.sv @@ -0,0 +1,119 @@ +// Contains the FAIL_UNLESS_EQUAL macro. +`include "macro.svh" + +module tb; + parameter FULL_TEST = 0; + + // [Step 1] Wildcard import the typedef_pkg package. + import typedef_pkg::*; + + // [Step 2] Declare signals. The operation, operand_a, operand_b, and result signals must use the + // data types from the typedef_pkg package. Initialize the clk signal with a value of 1'b0. + + logic clk = 1'b0; + logic op_start; + operation_t operation; + operand_t operand_a; + operand_t operand_b; + result_t result; + + // [Step 3] Instantiate the DUV module. The module is declared as + + /* + module duv + ( + input logic clk, + + input logic op_start, + input operation_t operation, + input operand_t operand_a, + input operand_t operand_b, + + output result_t result + ); + */ + + duv ALU0 ( + .clk, + .op_start, + .operation, + .operand_a, + .operand_b, + .result + ); + + // [Step 4] Always block to generate the clock. + + always #1ns clk = ~clk; + + // [Step 5] Test the DUV using an initial block. Be sure to initialize all DUV input variables, and use the + // $finish system task to halt simulation at the end of the test. + + initial begin + automatic result_t expected_result; + automatic int test_count = 0; + + // Initialise all inputs + op_start = 1'b0; + operation = ADD; + operand_a = 8'h00; + operand_b = 8'h00; + + // Wait for initial setup and reset + repeat (3) @(posedge clk); + + // Exhaustively test all combinations + for (int op = 0; op < 4; op++) begin + for (int a = 0; a < (FULL_TEST ? 256 : 16); a++) begin + for (int b = 0; b < (FULL_TEST ? 256 : 16); b++) begin + // Set up inputs and calculate expected result first + operation = operation_t'(op); + operand_a = a[7:0]; + operand_b = b[7:0]; + + // Calculate expected result before starting operation + case (operation) + ADD: expected_result = (operand_a + operand_b) & 16'h01FF; // ADD + MULT: expected_result = operand_a * operand_b; // MULT + OR: expected_result = (operand_a | operand_b) & 16'h00FF; // OR + AND: expected_result = (operand_a & operand_b) & 16'h00FF; // AND + endcase + + // Start the operation + op_start = 1'b1; + + // Wait for rising edge to latch inputs + @(posedge clk); + + op_start = 1'b0; + + // Wait 2 more clock cycles for result + @(posedge clk); + @(posedge clk); + + // Compare only relevant bits based on operation + case (operation) + ADD: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h01FF, $sformatf( + "ADD a=%0d b=%0d", operand_a, operand_b)) + MULT: + `FAIL_UNLESS_EQUAL(expected_result, result, $sformatf( + "MULT a=%0d b=%0d", operand_a, operand_b)) + OR: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf( + "OR a=%0d b=%0d", operand_a, operand_b)) + AND: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf( + "AND a=%0d b=%0d", operand_a, operand_b)) + endcase + + test_count += 1; + end + end + end + + $display("All tests passed! Total tests: %0d", test_count); + $display("Finished Successfully!"); + $finish; + end // Initial end +endmodule : tb diff --git a/lab_2/SRC/typedef_pkg.sv b/lab_2/SRC/typedef_pkg.sv new file mode 100644 index 0000000..a7786e6 --- /dev/null +++ b/lab_2/SRC/typedef_pkg.sv @@ -0,0 +1,14 @@ +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
\ No newline at end of file diff --git a/lab_2/image1.png b/lab_2/image1.png Binary files differnew file mode 100644 index 0000000..d755911 --- /dev/null +++ b/lab_2/image1.png diff --git a/lab_3/CST456 Lab3.pdf b/lab_3/CST456 Lab3.pdf Binary files differnew file mode 100644 index 0000000..7e402c5 --- /dev/null +++ b/lab_3/CST456 Lab3.pdf diff --git a/lab_3/CST456 LAB3.rar b/lab_3/CST456 LAB3.rar Binary files differnew file mode 100644 index 0000000..840be78 --- /dev/null +++ b/lab_3/CST456 LAB3.rar diff --git a/lab_3/CST456 Lab3.md b/lab_3/CST456 Lab3.md new file mode 100644 index 0000000..ff8c360 --- /dev/null +++ b/lab_3/CST456 Lab3.md @@ -0,0 +1,80 @@ +# CST456 Lab3 + +**CST456 – Lab 3** + +**Layered Testbench** + +**Objective** + +The objective of this lab is to employ a SystemVerilog interface to implement a layered testbench that exhaustively tests the operations and operands of a synchronous arithmetic and logic unit (ALU). + +**Design Under Verification (DUV)** + +The ALU contains the following ports: + +| **Port Name** | **Signal Type** | **Direction** | **Number of Bits** | +| --- | --- | --- | --- | +| clk | Clock | Input | 1 | +| op_start | Control | Input | 1 | +| operation | Control | Input | 2 | +| operand_a | Data | Input | 8 | +| operand_b | Data | Input | 8 | +| result | Data | Output | 8 | + +At the rising edge of the clock, if op_start is asserted (== 1’b1) then the operation, operand_a, and operand_b signals are latched into the ALU. Exactly two clock cycles later the upper eight bits of the result are read from the result port. The lower eight bits of the result are read from the result port one clock cycle later. The op_start signal is ignored during the middle of an operation. The ALU supports the following operations: + +| **Name** | **Value** | **Description** | +| --- | --- | --- | +| ADD | 2’b00 | operand_a is added to operand_b. Only the lower nine bits of the 16-bit result are used. | +| MULT | 2’b01 | operand_a is multiplied with operand_b. This is an unsigned operation and all sixteen bits of the result are used. | +| OR | 2’b10 | operand_a is bitwise ORed with operand_b. Only the lower eight bits of the 16-bit result are used. | +| AND | 2’b11 | operand_a is bitwise ANDed with operand_b. Only the lower eight bits of the 16-bit result are used. | + +Figure 1 shows a timing diagram for the addition operation, where 255 + 255 = 510. + + + +**Figure 1 - Timing diagram for an addition operation.** + +**Package** + +Rather than using the binary value for the ALU’s operations, it is more human-readable to use an enumerated type. Edit the typedef_pkg.sv file and create an enumeration typedef for the four ALU operations: ADD, MULT, OR, and AND. Name the typedef operation_t. This typedef will be imported into the interface and testbench. + +**Interface** + +We will use an interface to connect the testbench to the DUV and to provide a task that performs ALU operations. Edit the interface.sv file and import the operation_t typedef from the package. Declare the signals, other than clk, that will connect to the DUV and create a task called execute_op with the following ports: + +| **Port Name** | **Data Type** | **Direction** | +| --- | --- | --- | +| op | operation_t | Input | +| op_a | logic [7:0] | Input | +| op_b | logic [7:0] | Input | +| res | logic [15:0] | Output | + +The task performs the ALU operation specified by op using the two operands op_a and op_b. It returns the result of the operation through the res port. + +**Testbench** + +Edit the tb.sv file and create a testbench to exhaustively test all + +the operations and operand combinations that the ALU supports. Create + +a do-while loop and two nested for-loops. The do-while loop enumerates + +through all four operations, the first for-loop enumerates through all + +256 values for operand_a, and the second for-loop enumerates through + +all 256 values for operand_b. Use the interface’s execute_op task to + +send data to and receive data from the DUV, and use the + +`FAIL_UNLESS_EQUAL macro to check the expected result with the tested + +result. The DUV does not contain any bugs, so the testing is expected + +to be successful. + +**Lab Submission** + +Zip the entire contents of the lab directory and submit it to Canvas. diff --git a/lab_3/SIM/build_simulation.bat b/lab_3/SIM/build_simulation.bat new file mode 100644 index 0000000..bcac078 --- /dev/null +++ b/lab_3/SIM/build_simulation.bat @@ -0,0 +1,4 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/typedef_pkg.sv ../SRC/interface.sv ../SRC/duv.sv ../SRC/tb.sv +call C:\Xilinx\Vivado\2022.1\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot +pause diff --git a/lab_3/SIM/run_simulation.bat b/lab_3/SIM/run_simulation.bat new file mode 100644 index 0000000..1ffb30d --- /dev/null +++ b/lab_3/SIM/run_simulation.bat @@ -0,0 +1,7 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/typedef_pkg.sv ../SRC/interface.sv ../SRC/duv.sv ../SRC/tb.sv +call C:\Xilinx\Vivado\2022.1\bin\xelab -debug typical -top tb -snapshot duv_tb_snapshot +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot -R +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl +call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb +pause diff --git a/lab_3/SIM/run_waveform.bat b/lab_3/SIM/run_waveform.bat new file mode 100644 index 0000000..b3ddc9a --- /dev/null +++ b/lab_3/SIM/run_waveform.bat @@ -0,0 +1,3 @@ +@echo off +call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl +call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb diff --git a/lab_3/SIM/xsim_cfg.tcl b/lab_3/SIM/xsim_cfg.tcl new file mode 100644 index 0000000..b7c49f5 --- /dev/null +++ b/lab_3/SIM/xsim_cfg.tcl @@ -0,0 +1,3 @@ +log_wave -recursive *
+run all
+exit
\ No newline at end of file diff --git a/lab_3/SRC/duv.sv b/lab_3/SRC/duv.sv new file mode 100644 index 0000000..564fc46 --- /dev/null +++ b/lab_3/SRC/duv.sv @@ -0,0 +1,26 @@ +
+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 [15:0] result_tmp;
+
+ always_ff @(posedge clk) begin
+ if (op_start == 1'b1) begin
+ case (operation)
+ 0: result_tmp = operand_a + operand_b;
+ 1: result_tmp = operand_a * operand_b;
+ 2: result_tmp = operand_a | operand_b;
+ 3: result_tmp = operand_a & operand_b;
+ endcase
+ end
+
+ result <= result_tmp;
+ end
+
+endmodule : duv
diff --git a/lab_3/SRC/interface.sv b/lab_3/SRC/interface.sv new file mode 100644 index 0000000..aec4d93 --- /dev/null +++ b/lab_3/SRC/interface.sv @@ -0,0 +1,33 @@ +interface intf ( + input logic clk +); + // [Step 1] Wildcard import the enumeration typedef from the typedef_pkg package. + import typedef_pkg::*; + + // [Step 2] Declare the signals, other than clk, that will connect to the DUV. + logic op_start; + logic [1:0] operation; + logic [7:0] operand_a; + logic [7:0] operand_b; + logic [15:0] result; + + // [Step 3] Implement the execute_op task. + task execute_op(input operation_t op, input logic [7:0] op_a, input logic [7:0] op_b, + output logic [15:0] res); + // Set inputs and start operation + operation = op; + operand_a = op_a; + operand_b = op_b; + op_start = 1'b1; + + @(posedge clk); + + op_start = 1'b0; + + // Wait 2 cycles for result + @(posedge clk); + @(posedge clk); + + res = result; + endtask +endinterface : intf diff --git a/lab_3/SRC/macro.svh b/lab_3/SRC/macro.svh new file mode 100644 index 0000000..284b9ae --- /dev/null +++ b/lab_3/SRC/macro.svh @@ -0,0 +1,10 @@ +`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); \ + $finish; \ + end +`endif diff --git a/lab_3/SRC/tb.sv b/lab_3/SRC/tb.sv new file mode 100644 index 0000000..5623d17 --- /dev/null +++ b/lab_3/SRC/tb.sv @@ -0,0 +1,88 @@ +// Contains the FAIL_UNLESS_EQUAL macro. +`include "macro.svh" + +module tb; + parameter FULL_TEST = 1; + + // [Step 1] Wildcard import the enumeration typedef from the typedef_pkg package. + import typedef_pkg::*; + + // [Step 2] Declare clk signal and initialize with value of 1'b0. + logic clk = 1'b0; + + // [Step 3] Instantiate the interface and connect the clk signal. + intf intf0 (.clk(clk)); + + // [Step 4] Instantiate the DUV module and connect the interface signals and the clk signal to the DUV ports. + duv ALU0 ( + .clk(clk), + .op_start(intf0.op_start), + .operation(intf0.operation), + .operand_a(intf0.operand_a), + .operand_b(intf0.operand_b), + .result(intf0.result) + ); + + // [Step 5] Always block to generate the clock. + always #1ns clk = ~clk; + + initial begin + automatic logic [15:0] expected_result; + automatic logic [15:0] result; + automatic int test_count = 0; + + // Initialise all inputs + intf0.op_start = 1'b0; + intf0.operation = ADD; + intf0.operand_a = 8'h00; + intf0.operand_b = 8'h00; + + // Wait for initial setup and reset + repeat (3) @(posedge clk); + + // Exhaustively test all combinations + for (int op = 0; op < 4; op++) begin + for (int a = 0; a < (FULL_TEST ? 256 : 16); a++) begin + for (int b = 0; b < (FULL_TEST ? 256 : 16); b++) begin + // Set up inputs and calculate expected result first + intf0.operation = operation_t'(op); + intf0.operand_a = a[7:0]; + intf0.operand_b = b[7:0]; + + // Calculate expected result before starting operation + case (intf0.operation) + ADD: expected_result = (intf0.operand_a + intf0.operand_b) & 16'h01FF; // ADD + MULT: expected_result = intf0.operand_a * intf0.operand_b; // MULT + OR: expected_result = (intf0.operand_a | intf0.operand_b) & 16'h00FF; // OR + AND: expected_result = (intf0.operand_a & intf0.operand_b) & 16'h00FF; // AND + endcase + + // Execute operation using interface task + intf0.execute_op(operation_t'(op), a[7:0], b[7:0], result); + + // Compare only relevant bits based on operation + case (intf0.operation) + ADD: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h01FF, $sformatf( + "ADD a=%0d b=%0d", intf0.operand_a, intf0.operand_b)) + MULT: + `FAIL_UNLESS_EQUAL(expected_result, result, $sformatf( + "MULT a=%0d b=%0d", intf0.operand_a, intf0.operand_b)) + OR: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf( + "OR a=%0d b=%0d", intf0.operand_a, intf0.operand_b)) + AND: + `FAIL_UNLESS_EQUAL(expected_result, result & 16'h00FF, $sformatf( + "AND a=%0d b=%0d", intf0.operand_a, intf0.operand_b)) + endcase + + test_count += 1; + end + end + end + + $display("All tests passed! Total tests: %0d", test_count); + $display("Finished Successfully!"); + $finish; + end //:initial +endmodule : tb diff --git a/lab_3/SRC/typedef_pkg.sv b/lab_3/SRC/typedef_pkg.sv new file mode 100644 index 0000000..227f823 --- /dev/null +++ b/lab_3/SRC/typedef_pkg.sv @@ -0,0 +1,10 @@ +// [Step 1] Create an enumeration typedef for the four operations: ADD, MULT, OR, and AND. +// Name the typedef operation_t. +package typedef_pkg; + typedef enum logic [1:0] { + ADD = 2'b00, + MULT = 2'b01, + OR = 2'b10, + AND = 2'b11 + } operation_t; +endpackage : typedef_pkg diff --git a/lab_3/image1.png b/lab_3/image1.png Binary files differnew file mode 100644 index 0000000..63909a8 --- /dev/null +++ b/lab_3/image1.png diff --git a/lab_4/CST456 LAB4.rar b/lab_4/CST456 LAB4.rar Binary files differnew file mode 100644 index 0000000..e29c0b9 --- /dev/null +++ b/lab_4/CST456 LAB4.rar diff --git a/lab_4/CST456 Lab4.md b/lab_4/CST456 Lab4.md new file mode 100644 index 0000000..36d9acd --- /dev/null +++ b/lab_4/CST456 Lab4.md @@ -0,0 +1,70 @@ +# CST456 Lab4 + +**CST456 – Lab 4** + +**Simple Randomized Testbench with Scoreboard and Checker** + +**Objective** + +The objective of this lab is to implement a simple randomized testbench to test the operations and operands of a synchronous arithmetic and logic unit (ALU). + +**Design Under Verification (DUV)** + +The ALU contains the following ports: + +| **Port Name** | **Signal Type** | **Direction** | **Number of Bits** | +| --- | --- | --- | --- | +| clk | Clock | Input | 1 | +| op_start | Control | Input | 1 | +| operation | Control | Input | 2 | +| operand_a | Data | Input | 8 | +| operand_b | Data | Input | 8 | +| result | Data | Output | 16 | + +At the rising edge of the clock, if op_start is asserted (== 1’b1) then the operation, operand_a, and operand_b signals are latched into the ALU. Exactly two clock cycles later the result of the operation is read from the result port. The ALU supports the following operations: + +| **Name** | **Value** | **Description** | +| --- | --- | --- | +| ADD | 2’b00 | operand_a is added to operand_b. Only the lower 49 bits of the result are used. | +| MULT | 2’b01 | operand_a is multiplied with operand_b. This is an unsigned operation and all 96 bits of the result are used. | +| OR | 2’b10 | operand_a is bitwise ORed with operand_b. Only the lower 48 bits of the result are used. | +| AND | 2’b11 | operand_a is bitwised ANDed with operand_b. Only the lower 48 bits of the result are used. | + +**Testbench** + +Edit the tb.sv file and create a testbench to test all the operations + +for a randomly generated subset of operand values. The testbench will + +include a scoreboard struct to log the operation, operand_a, + +operand_b, and result values, as well as a checker task that checks + +the scoreboard once an operation has completed. + +Create a repeat loop to continually generate random values for the + +operation, operand_a, and operand_b signals. Use the std::randomize + +function and the `RND_CHECK macro to check that randomization was + +successful. At the appropriate times log the operation, operand_a, + +operand_b, and result values to the scoreboard, and call the checker + +task once the scoreboard has been completed. Use the + +`FAIL_UNLESS_EQUAL macro to check the expected result with the tested + +result. Note that the `FAIL_UNLESS_EQUAL macro does not stop the test + +in the event of a failure. To run the simulation in Xilinx Vivado for + +Windows execute the following **bat** files under the **SIM** directory: + +- run_sim_cli.bat (command line simulation) +- run_sim_gui.bat (gui simulation with waveform viewer) + +**Lab Submission** + +Zip the entire contents of the lab directory and submit it to Canvas.
\ No newline at end of file diff --git a/lab_4/CST456 Lab4.pdf b/lab_4/CST456 Lab4.pdf Binary files differnew file mode 100644 index 0000000..1182af7 --- /dev/null +++ b/lab_4/CST456 Lab4.pdf diff --git a/lab_4/SIM/run_sim_cli.bat b/lab_4/SIM/run_sim_cli.bat new file mode 100644 index 0000000..9aade53 --- /dev/null +++ b/lab_4/SIM/run_sim_cli.bat @@ -0,0 +1,5 @@ +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/typedef_pkg.sv ../SRC/tb.sv ../SRC/duv.sv
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xelab -nolog -debug all testbench
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xsim testbench -R
+REM Uncomment the next line to keep the cmd window open if executing batch file from Windows Explorer.
+pause
diff --git a/lab_4/SIM/run_sim_gui.bat b/lab_4/SIM/run_sim_gui.bat new file mode 100644 index 0000000..c437b23 --- /dev/null +++ b/lab_4/SIM/run_sim_gui.bat @@ -0,0 +1,3 @@ +call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog -sv ../SRC/typedef_pkg.sv ../SRC/tb.sv ../SRC/duv.sv
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xelab -nolog -debug all testbench
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xsim testbench -gui
diff --git a/lab_4/SRC/duv.sv b/lab_4/SRC/duv.sv new file mode 100644 index 0000000..b748e4a --- /dev/null +++ b/lab_4/SRC/duv.sv @@ -0,0 +1,31 @@ +
+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 [15:0] result_temp;
+
+always_ff @(posedge clk)
+begin
+if( op_start == 1'b1)
+begin
+case (operation)
+ 0: result_temp = operand_a + operand_b;
+ 1: result_temp = operand_a * operand_b;
+ 2: result_temp = operand_a | operand_b;
+ 3: result_temp = operand_a & operand_b;
+ endcase
+ end
+
+ // result <= result_temp;
+end
+always_ff @(posedge clk)
+begin
+result = result_temp;
+end
+endmodule : duv
\ No newline at end of file diff --git a/lab_4/SRC/macro.svh b/lab_4/SRC/macro.svh new file mode 100644 index 0000000..72bf471 --- /dev/null +++ b/lab_4/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/lab_4/SRC/tb.sv b/lab_4/SRC/tb.sv new file mode 100644 index 0000000..2e45384 --- /dev/null +++ b/lab_4/SRC/tb.sv @@ -0,0 +1,114 @@ +// Contains the FAIL_UNLESS_EQUAL and RND_CHECK macros.
+`include "macro.svh"
+
+module testbench;
+ // [Step 1] Declare signals that connect to DUV. Intialize the clk signal with a value of 1'b0.
+ import typedef_pkg::*;
+
+ logic clk = 1'b0;
+ logic op_start;
+ logic [ 1:0] operation;
+ logic [ 7:0] operand_a;
+ logic [ 7:0] operand_b;
+ logic [15:0] result;
+
+ // [Step 2] Declare the scoreboard that holds the operation, operand_a, operand_b, and results values.
+ typedef struct {
+ operation_t operation;
+ logic [7:0] operand_a;
+ logic [7:0] operand_b;
+ logic [15:0] result;
+ } scoreboard_t;
+
+ // [Step 3] Instantiate the DUV module.
+ duv ALU0 (
+ .clk(clk),
+ .op_start(op_start),
+ .operation(operation),
+ .operand_a(operand_a),
+ .operand_b(operand_b),
+ .result(result)
+ );
+
+ // [Step 4] Always block to generate the clock.
+ always #1ns clk = ~clk;
+
+ // [Step 5] Implement the check task to check the scoreboard.
+ task check(input scoreboard_t sb);
+ automatic logic [15:0] expected_result;
+
+ case (sb.operation)
+ ADD: begin
+ expected_result = (sb.operand_a + sb.operand_b) & 16'h01FF;
+ `FAIL_UNLESS_EQUAL(expected_result, sb.result & 16'h01FF, $sformatf(
+ "ADD a=%0d b=%0d", sb.operand_a, sb.operand_b))
+ end
+ MULT: begin
+ expected_result = sb.operand_a * sb.operand_b;
+ `FAIL_UNLESS_EQUAL(expected_result, sb.result, $sformatf(
+ "MULT a=%0d b=%0d", sb.operand_a, sb.operand_b))
+ end
+ OR: begin
+ expected_result = (sb.operand_a | sb.operand_b) & 16'h00FF;
+ `FAIL_UNLESS_EQUAL(expected_result, sb.result & 16'h00FF, $sformatf(
+ "OR a=%0d b=%0d", sb.operand_a, sb.operand_b))
+ end
+ AND: begin
+ expected_result = (sb.operand_a & sb.operand_b) & 16'h00FF;
+ `FAIL_UNLESS_EQUAL(expected_result, sb.result & 16'h00FF, $sformatf(
+ "AND a=%0d b=%0d", sb.operand_a, sb.operand_b))
+ end
+ endcase
+ endtask
+
+ // [Step 6] Test the DUV using an initial block. Be sure to initialize all DUV input variables,
+ // and use the $finish system task to halt simulation at the end of the test.
+ initial begin
+ automatic scoreboard_t sb;
+ automatic int test_count = 0;
+ automatic logic [1:0] rnd_op;
+ automatic logic [7:0] rnd_a;
+ automatic logic [7:0] rnd_b;
+
+ // Initialise all inputs
+ op_start = 1'b0;
+ operation = ADD;
+ operand_a = 8'h00;
+ operand_b = 8'h00;
+
+ // Wait for initial setup
+ repeat (3) @(posedge clk);
+
+ // Randomised test loop
+ repeat (100) begin
+ `RND_CHECK(std::randomize(rnd_op, rnd_a, rnd_b))
+
+ // Log inputs to scoreboard
+ sb.operation = operation_t'(rnd_op);
+ sb.operand_a = rnd_a;
+ sb.operand_b = rnd_b;
+
+ // Drive DUV inputs and execute operation
+ operation = rnd_op;
+ operand_a = rnd_a;
+ operand_b = rnd_b;
+ op_start = 1'b1;
+
+ @(posedge clk);
+ op_start = 1'b0;
+
+ // Wait exactly two clock cycles for result
+ @(posedge clk);
+ @(posedge clk);
+
+ sb.result = result;
+ check(sb);
+
+ test_count += 1;
+ end
+
+ $display("All tests passed! Total tests: %0d", test_count);
+ $display("Finished Successfully!");
+ $finish;
+ end //:initial
+endmodule : testbench
diff --git a/lab_4/SRC/typedef_pkg.sv b/lab_4/SRC/typedef_pkg.sv new file mode 100644 index 0000000..5b3aa5a --- /dev/null +++ b/lab_4/SRC/typedef_pkg.sv @@ -0,0 +1,13 @@ +// [Step 1] Create an enumeration typedef for the four operations: ADD, MULT, OR, and AND. +// Name the typedef operation_t. +package typedef_pkg; + + typedef enum logic [1:0] + { + ADD = 2'b00, + MULT = 2'b01, + OR = 2'b10, + AND = 2'b11 + } operation_t; + +endpackage : typedef_pkg
\ No newline at end of file diff --git a/lab_4/~$lab3.docx b/lab_4/~$lab3.docx Binary files differnew file mode 100644 index 0000000..7d500b9 --- /dev/null +++ b/lab_4/~$lab3.docx |