summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-24 20:46:14 -0800
committerFuwn <[email protected]>2026-02-24 20:46:14 -0800
commit57bb24b96645ad0f60c6e6968a6b2ac48754e2dc (patch)
tree9f7da4da999b87ea9541e5ad83b9cbe87f674ce7
parentfeat(homework_2): Add initial files (diff)
downloadcst456-57bb24b96645ad0f60c6e6968a6b2ac48754e2dc.tar.xz
cst456-57bb24b96645ad0f60c6e6968a6b2ac48754e2dc.zip
feat(homework_2): Add implementation
-rw-r--r--.gitignore1
-rw-r--r--homework_2/SIM/run_coverage.bat7
-rw-r--r--homework_2/SIM/run_sim_cli.bat5
-rw-r--r--homework_2/SIM/run_sim_gui.bat6
-rw-r--r--homework_2/SRC/base_test.sv130
-rw-r--r--homework_2/SRC/driver.sv70
-rw-r--r--homework_2/SRC/duv.sv151
-rw-r--r--homework_2/SRC/gen_item_seq.sv58
-rw-r--r--homework_2/SRC/interface.sv31
-rw-r--r--homework_2/SRC/item.sv35
-rw-r--r--homework_2/SRC/monitor.sv81
-rw-r--r--homework_2/SRC/scoreboard.sv114
-rw-r--r--homework_2/SRC/tb.sv71
13 files changed, 400 insertions, 360 deletions
diff --git a/.gitignore b/.gitignore
index 81b54fc..1eb1b20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ xsim.dir
.Xil
*.zip
xsim.covdb
+cRun*
diff --git a/homework_2/SIM/run_coverage.bat b/homework_2/SIM/run_coverage.bat
new file mode 100644
index 0000000..6448877
--- /dev/null
+++ b/homework_2/SIM/run_coverage.bat
@@ -0,0 +1,7 @@
+@echo off
+call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog --sv ../SRC/duv.sv ../SRC/tb.sv -L UVM
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xelab -nolog -debug typical -top tb -snapshot duv_tb_snapshot -L UVM -cc_type sbct -cc_db DB1 -cc_dir ./cRun1
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot -R
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xcrg -cc_db DB1 -cc_dir ./cRun1 -cc_report ./cReport1
+if %ERRORLEVEL% EQU 0 start ./cReport1/dashboard.html
+pause
diff --git a/homework_2/SIM/run_sim_cli.bat b/homework_2/SIM/run_sim_cli.bat
new file mode 100644
index 0000000..aad09bd
--- /dev/null
+++ b/homework_2/SIM/run_sim_cli.bat
@@ -0,0 +1,5 @@
+@echo off
+call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog --sv ../SRC/duv.sv ../SRC/tb.sv -L UVM
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xelab -nolog -debug typical -top tb -snapshot duv_tb_snapshot -L UVM
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot -R
+pause
diff --git a/homework_2/SIM/run_sim_gui.bat b/homework_2/SIM/run_sim_gui.bat
new file mode 100644
index 0000000..100bf58
--- /dev/null
+++ b/homework_2/SIM/run_sim_gui.bat
@@ -0,0 +1,6 @@
+@echo off
+call C:\Xilinx\Vivado\2022.1\bin\xvlog -nolog --sv ../SRC/duv.sv ../SRC/tb.sv -L UVM
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xelab -nolog -debug typical -top tb -snapshot duv_tb_snapshot -L UVM
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xsim duv_tb_snapshot --tclbatch xsim_cfg.tcl
+if %ERRORLEVEL% EQU 0 call C:\Xilinx\Vivado\2022.1\bin\xsim --gui duv_tb_snapshot.wdb
+pause
diff --git a/homework_2/SRC/base_test.sv b/homework_2/SRC/base_test.sv
index ea675bc..b6b81ef 100644
--- a/homework_2/SRC/base_test.sv
+++ b/homework_2/SRC/base_test.sv
@@ -1,63 +1,67 @@
-// Test class instantiates the environment and starts it.
-class base_test extends uvm_test;
- `uvm_component_utils(base_test)
- function new(string name = "base_test", uvm_component parent=null);
- super.new(name, parent);
- endfunction
-
- env e0;
- bit[`LENGTH-1:0] pattern = 4'b1011;
- gen_item_seq seq;
- virtual des_if vif;
-
- virtual function void build_phase(uvm_phase phase);
- super.build_phase(phase);
-
- // Create the environment
- e0 = env::type_id::create("e0", this);
-
- // Get virtual IF handle from top level and pass it to everything
- // in env level
- if (!uvm_config_db#(virtual des_if)::get(this, "", "des_vif", vif))
- `uvm_fatal("TEST", "Did not get vif")
- uvm_config_db#(virtual des_if)::set(this, "e0.a0.*", "des_vif", vif);
-
- // Setup pattern queue and place into config db
- uvm_config_db#(bit[`LENGTH-1:0])::set(this, "*", "ref_pattern", pattern);
-
- // Create sequence and randomize it
- seq = gen_item_seq::type_id::create("seq");
- seq.randomize();
- endfunction
-
- virtual task run_phase(uvm_phase phase);
- phase.raise_objection(this);
- apply_reset();
- seq.start(e0.a0.s0);
- #200;
- phase.drop_objection(this);
- endtask
-
- virtual task apply_reset();
- vif.rstn <= 0;
- vif.in <= 0;
- repeat(5) @ (posedge vif.clk);
- vif.rstn <= 1;
- repeat(10) @ (posedge vif.clk);
- endtask
-endclass
-
-class test_1011 extends base_test;
- `uvm_component_utils(test_1011)
- function new(string name="test_1011", uvm_component parent=null);
- super.new(name, parent);
- endfunction
-
- virtual function void build_phase(uvm_phase phase);
- pattern = 4'b1011;
- super.build_phase(phase);
- seq.randomize() with { num inside {[300:500]}; };
- endfunction
-endclass
-
-// The int \ No newline at end of file
+// Test class instantiates the environment and starts it.
+class base_test extends uvm_test;
+ `uvm_component_utils(base_test)
+ function new(string name = "base_test", uvm_component parent = null);
+ super.new(name, parent);
+ endfunction
+
+ env e0;
+ gen_item_seq seq;
+ virtual des_if vif;
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+
+ // Create the environment
+ e0 = env::type_id::create("e0", this);
+
+ // Get virtual IF handle from top level and pass it to everything
+ // in env level
+ if (!uvm_config_db#(virtual des_if)::get(this, "", "des_vif", vif))
+ `uvm_fatal("TEST", "Did not get vif")
+
+ uvm_config_db#(virtual des_if)::set(this, "e0.a0.*", "des_vif", vif);
+
+ // Create sequence and randomize it
+ seq = gen_item_seq::type_id::create("seq");
+
+ if (!seq.randomize()) `uvm_fatal("TEST", "Failed to randomize sequence")
+ endfunction
+
+ virtual task run_phase(uvm_phase phase);
+ phase.raise_objection(this);
+ apply_reset();
+ seq.start(e0.a0.s0);
+
+ #200;
+
+ `uvm_info("TEST_DONE", "Sequence detector test completed", UVM_LOW)
+
+ phase.drop_objection(this);
+ endtask
+
+ virtual task apply_reset();
+ vif.reset <= 1'b1;
+ vif.inp <= 0;
+
+ repeat (5) @(posedge vif.clk);
+
+ vif.reset <= 0;
+
+ repeat (10) @(posedge vif.clk);
+ endtask
+endclass
+
+class test_both_patterns extends base_test;
+ `uvm_component_utils(test_both_patterns)
+ function new(string name = "test_both_patterns", uvm_component parent = null);
+ super.new(name, parent);
+ endfunction
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+
+ if (!seq.randomize() with {num inside {[520 : 620]};})
+ `uvm_fatal("TEST", "Failed to randomize sequence length")
+ endfunction
+endclass
diff --git a/homework_2/SRC/driver.sv b/homework_2/SRC/driver.sv
index 37d0583..03d17b8 100644
--- a/homework_2/SRC/driver.sv
+++ b/homework_2/SRC/driver.sv
@@ -1,33 +1,37 @@
-// The driver is responsible for driving transactions to the DUT
-// All it does is to get a transaction from the mailbox if it is
-// available and drive it out into the DUT interface.
-class driver extends uvm_driver #(Item);
- `uvm_component_utils(driver)
- function new(string name = "driver", uvm_component parent=null);
- super.new(name, parent);
- endfunction
-
- virtual des_if vif;
-
- virtual function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- if (!uvm_config_db#(virtual des_if)::get(this, "", "des_vif", vif))
- `uvm_fatal("DRV", "Could not get vif")
- endfunction
-
- virtual task run_phase(uvm_phase phase);
- super.run_phase(phase);
- forever begin
- Item m_item;
- `uvm_info("DRV", $sformatf("Wait for item from sequencer"), UVM_HIGH)
- seq_item_port.get_next_item(m_item);
- drive_item(m_item);
- seq_item_port.item_done();
- end
- endtask
-
- virtual task drive_item(Item m_item);
- @(vif.cb);
- vif.cb.in <= m_item.in;
- endtask
-endclass \ No newline at end of file
+// The driver is responsible for driving transactions to the DUT
+// All it does is to get a transaction from the mailbox if it is
+// available and drive it out into the DUT interface.
+class driver extends uvm_driver #(Item);
+ `uvm_component_utils(driver)
+ function new(string name = "driver", uvm_component parent = null);
+ super.new(name, parent);
+ endfunction
+
+ virtual des_if vif;
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+
+ if (!uvm_config_db#(virtual des_if)::get(this, "", "des_vif", vif))
+ `uvm_fatal("DRV", "Could not get vif")
+ endfunction
+
+ virtual task run_phase(uvm_phase phase);
+ super.run_phase(phase);
+ forever begin
+ Item m_item;
+
+ `uvm_info("DRV", $sformatf("Wait for item from sequencer"), UVM_HIGH)
+
+ seq_item_port.get_next_item(m_item);
+ drive_item(m_item);
+ seq_item_port.item_done();
+ end
+ endtask
+
+ virtual task drive_item(Item m_item);
+ @(vif.cb);
+
+ vif.cb.inp <= m_item.inp;
+ endtask
+endclass
diff --git a/homework_2/SRC/duv.sv b/homework_2/SRC/duv.sv
index e7e0c0f..62e5b99 100644
--- a/homework_2/SRC/duv.sv
+++ b/homework_2/SRC/duv.sv
@@ -1,86 +1,65 @@
-module duv ( input clk,
- input rstn,
- input in,
- output out );
-
- parameter IDLE = 0,
- S1 = 1,
- S10 = 2,
- S101 = 3,
- S1011 = 4;
-
- reg [2:0] cur_state, next_state;
-
- assign out = cur_state == S1011 ? 1 : 0;
-
- always @ (posedge clk) begin
- if (!rstn)
- cur_state <= IDLE;
- else
- cur_state <= next_state;
- end
-
- always @ (cur_state or in) begin
- case (cur_state)
- IDLE : begin
- if (in) next_state = S1;
- else next_state = IDLE;
- end
-
- S1: begin
-`ifdef BUG_FIX_1
- // Designer assumed that if next input is 1,
- // state should start from IDLE. But he forgot
- // that it should stay in same state since it
- // already matched part of the pattern which
- // is the starting "1"
- if (in) next_state = S1;
-`else
- if (in) next_state = IDLE;
-`endif
- else next_state = S10;
- end
-
- S10 : begin
- if (in) next_state = S101;
- else next_state = IDLE;
- end
-
- S101 : begin
- if (in) next_state = S1011;
-`ifdef BUG_FIX_2
- // Designer assumed that if next input is 0,
- // then pattern fails to match and should
- // restart. But he forgot that S101 followed
- // by 0 actually matches part of the pattern
- // which is "10" and only "11" is remaining
- // So it should actually go back to S10
- else next_state = S10;
-`else
- else next_state = IDLE;
-`endif
- end
-
- S1011: begin
-`ifdef BUG_FIX_3
- // Designer assumed next state should always
- // be IDLE since the pattern has matched. But
- // he forgot that if next input is 1, it is
- // already the start of another sequence and
- // instead should go to S1.
- if (in) next_state = S1;
- `ifdef BUG_FIX_4
- // Designer forgot again that if next input is 0
- // then pattern still matches "10" and should
- // go to S10 instead of IDLE.
- else next_state = S10;
- `else
- else next_state = IDLE;
- `endif
-`else
- next_state = IDLE;
-`endif
- end
- endcase
- end
-endmodule \ No newline at end of file
+module duv (
+ input logic clk,
+ input logic reset,
+ input logic inp,
+ output logic outp
+);
+ localparam S0 = 3'b000, S1 = 3'b001, S11 = 3'b010, S10 = 3'b011, S110 = 3'b100, S101 = 3'b101;
+
+ logic [2:0] state;
+ logic [2:0] next_state;
+
+ // State register with asynchronous active-high reset
+ always_ff @(posedge clk or posedge reset) begin
+ if (reset) state <= S0;
+ else state <= next_state;
+ end
+
+ // Mealy next-state and output logic for 1011 and 1100
+ always_comb begin
+ next_state = state;
+ outp = 1'b0;
+
+ case (state)
+ S0: begin
+ if (inp) next_state = S1;
+ else next_state = S0;
+ end
+
+ S1: begin
+ if (inp) next_state = S11;
+ else next_state = S10;
+ end
+
+ S11: begin
+ if (inp) next_state = S11;
+ else next_state = S110;
+ end
+
+ S10: begin
+ if (inp) next_state = S101;
+ else next_state = S0;
+ end
+
+ S110: begin
+ if (inp) begin
+ next_state = S101;
+ end else begin
+ next_state = S0;
+ outp = 1'b1; // Detected 1100
+ end
+ end
+
+ S101: begin
+ if (inp) begin
+ next_state = S11;
+ outp = 1'b1; // Detected 1011
+ end else begin
+ next_state = S10;
+ end
+ end
+
+ default: next_state = S0;
+ endcase
+ end
+endmodule
diff --git a/homework_2/SRC/gen_item_seq.sv b/homework_2/SRC/gen_item_seq.sv
index c42cf3a..ce3c3f5 100644
--- a/homework_2/SRC/gen_item_seq.sv
+++ b/homework_2/SRC/gen_item_seq.sv
@@ -1,22 +1,36 @@
-// The generator class is replaced by a sequence
-class gen_item_seq extends uvm_sequence;
- `uvm_object_utils(gen_item_seq)
- function new(string name="gen_item_seq");
- super.new(name);
- endfunction
-
- rand int num; // Config total number of items to be sent
-
- constraint c1 { soft num inside {[10:50]}; }
-
- virtual task body();
- for (int i = 0; i < num; i ++) begin
- Item m_item = Item::type_id::create("m_item");
- start_item(m_item);
- m_item.randomize();
- `uvm_info("SEQ", $sformatf("Generate new item: %s", m_item.convert2str()), UVM_HIGH)
- finish_item(m_item);
- end
- `uvm_info("SEQ", $sformatf("Done generation of %0d items", num), UVM_LOW)
- endtask
-endclass \ No newline at end of file
+// The generator class is replaced by a sequence
+class gen_item_seq extends uvm_sequence;
+ `uvm_object_utils(gen_item_seq)
+ function new(string name = "gen_item_seq");
+ super.new(name);
+ endfunction
+
+ rand int num; // Config total number of items to be sent
+
+ constraint c1 {soft num inside {[300 : 500]};}
+
+ virtual task body();
+ bit seed_bits [$] = '{1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0};
+ int total_num;
+
+ total_num = (num < seed_bits.size()) ? seed_bits.size() : num;
+
+ for (int i = 0; i < total_num; i++) begin
+ Item m_item = Item::type_id::create($sformatf("m_item_%0d", i));
+
+ start_item(m_item);
+
+ if (i < seed_bits.size()) begin
+ m_item.inp = seed_bits[i];
+ end else begin
+ if (!m_item.randomize()) `uvm_fatal("SEQ", "Randomization failure for sequence item")
+ end
+
+ `uvm_info("SEQ", $sformatf("Generate new item: %s", m_item.convert2str()), UVM_HIGH)
+
+ finish_item(m_item);
+ end
+
+ `uvm_info("SEQ", $sformatf("Done generation of %0d items", total_num), UVM_LOW)
+ endtask
+endclass
diff --git a/homework_2/SRC/interface.sv b/homework_2/SRC/interface.sv
index a9906c8..47ed74a 100644
--- a/homework_2/SRC/interface.sv
+++ b/homework_2/SRC/interface.sv
@@ -1,15 +1,16 @@
-// using a virtual interface handle
-interface des_if (input bit clk);
- logic rstn;
- logic in;
- logic out;
-
- clocking cb @(posedge clk);
- default input #1step output #3ns;
- input out;
- output in;
- endclocking
-
-endinterface
-
-// Top level test \ No newline at end of file
+// using a virtual interface handle
+interface des_if (
+ input bit clk
+);
+ logic reset;
+ logic inp;
+ logic outp;
+
+ clocking cb @(posedge clk);
+ default input #1step output #3ns;
+ input outp;
+ output inp;
+ endclocking
+endinterface
+
+// Top level test
diff --git a/homework_2/SRC/item.sv b/homework_2/SRC/item.sv
index 5decdca..655d0b5 100644
--- a/homework_2/SRC/item.sv
+++ b/homework_2/SRC/item.sv
@@ -1,15 +1,20 @@
-class Item extends uvm_sequence_item;
- `uvm_object_utils(Item)
- rand bit in;
- bit out;
-
- virtual function string convert2str();
- return $sformatf("in=%0d, out=%0d", in, out);
- endfunction
-
- function new(string name = "Item");
- super.new(name);
- endfunction
-
- constraint c1 { in dist {0:/20, 1:/80}; }
-endclass \ No newline at end of file
+class Item extends uvm_sequence_item;
+ `uvm_object_utils(Item)
+ rand bit inp;
+ bit outp;
+
+ virtual function string convert2str();
+ return $sformatf("inp=%0d, outp=%0d", inp, outp);
+ endfunction
+
+ function new(string name = "Item");
+ super.new(name);
+ endfunction
+
+ constraint c1 {
+ inp dist {
+ 0 :/ 50,
+ 1 :/ 50
+ };
+ }
+endclass
diff --git a/homework_2/SRC/monitor.sv b/homework_2/SRC/monitor.sv
index cb848ec..d4b3e01 100644
--- a/homework_2/SRC/monitor.sv
+++ b/homework_2/SRC/monitor.sv
@@ -1,37 +1,44 @@
-// The monitor has a virtual interface handle with which
-// it can monitor the events happening on the interface.
-// It sees new transactions and then captures information
-// into a packet and sends it to the scoreboard
-// using another mailbox.
-class monitor extends uvm_monitor;
- `uvm_component_utils(monitor)
- function new(string name="monitor", uvm_component parent=null);
- super.new(name, parent);
- endfunction
-
- uvm_analysis_port #(Item) mon_analysis_port;
- virtual des_if vif;
-
- virtual function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- if (!uvm_config_db#(virtual des_if)::get(this, "", "des_vif", vif))
- `uvm_fatal("MON", "Could not get vif")
- mon_analysis_port = new ("mon_analysis_port", this);
- endfunction
-
- virtual task run_phase(uvm_phase phase);
- super.run_phase(phase);
- // This task monitors the interface for a complete
- // transaction and writes into analysis port when complete
- forever begin
- @ (vif.cb);
- if (vif.rstn) begin
- Item item = Item::type_id::create("item");
- item.in = vif.in;
- item.out = vif.cb.out;
- mon_analysis_port.write(item);
- `uvm_info("MON", $sformatf("Saw item %s", item.convert2str()), UVM_HIGH)
- end
- end
- endtask
-endclass
+// The monitor has a virtual interface handle with which
+// it can monitor the events happening on the interface.
+// It sees new transactions and then captures information
+// into a packet and sends it to the scoreboard
+// using another mailbox.
+class monitor extends uvm_monitor;
+ `uvm_component_utils(monitor)
+ function new(string name = "monitor", uvm_component parent = null);
+ super.new(name, parent);
+ endfunction
+
+ uvm_analysis_port #(Item) mon_analysis_port;
+
+ virtual des_if vif;
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+
+ if (!uvm_config_db#(virtual des_if)::get(this, "", "des_vif", vif))
+ `uvm_fatal("MON", "Could not get vif")
+
+ mon_analysis_port = new("mon_analysis_port", this);
+ endfunction
+
+ virtual task run_phase(uvm_phase phase);
+ super.run_phase(phase);
+
+ // This task monitors the interface for a complete
+ // transaction and writes into analysis port when complete
+ forever begin
+ @(vif.cb);
+ if (!vif.reset) begin
+ Item item = Item::type_id::create("item");
+
+ item.inp = vif.inp;
+ item.outp = vif.cb.outp;
+
+ mon_analysis_port.write(item);
+
+ `uvm_info("MON", $sformatf("Saw item %s", item.convert2str()), UVM_HIGH)
+ end
+ end
+ endtask
+endclass
diff --git a/homework_2/SRC/scoreboard.sv b/homework_2/SRC/scoreboard.sv
index c442f57..a55c812 100644
--- a/homework_2/SRC/scoreboard.sv
+++ b/homework_2/SRC/scoreboard.sv
@@ -1,53 +1,61 @@
-// the design routes packets based on an address range, the
-// scoreboard checks that the packet's address is within valid
-// range.
-class scoreboard extends uvm_scoreboard;
- `uvm_component_utils(scoreboard)
- function new(string name="scoreboard", uvm_component parent=null);
- super.new(name, parent);
- endfunction
-`define LENGTH 4
- bit[`LENGTH-1:0] ref_pattern;
- bit[`LENGTH-1:0] act_pattern;
- bit exp_out;
-
- uvm_analysis_imp #(Item, scoreboard) m_analysis_imp;
-
- virtual function void build_phase(uvm_phase phase);
- super.build_phase(phase);
-
- m_analysis_imp = new("m_analysis_imp", this);
- if (!uvm_config_db#(bit[`LENGTH-1:0])::get(this, "*", "ref_pattern", ref_pattern))
- `uvm_fatal("SCBD", "Did not get ref_pattern !")
- endfunction
-
- virtual function write(Item item);
- act_pattern = act_pattern << 1 | item.in;
-
- `uvm_info("SCBD", $sformatf("in=%0d out=%0d ref=0b%0b act=0b%0b",
- item.in, item.out, ref_pattern, act_pattern), UVM_LOW)
-
- // Always check that expected out value is the actual observed value
- // Since it takes 1 clock for out to be updated after pattern match,
- // do the check first and then update exp_out value
- if (item.out != exp_out) begin
- `uvm_error("SCBD", $sformatf("ERROR ! out=%0d exp=%0d",
- item.out, exp_out))
- end else begin
- `uvm_info("SCBD", $sformatf("PASS ! out=%0d exp=%0d",
- item.out, exp_out), UVM_HIGH)
- end
-
- // If current index has reached the full pattern, then set exp_out to be 1
- // which will be checked in the next clock. If pattern is not complete, keep
- // exp_out to zero
- if (!(ref_pattern ^ act_pattern)) begin
- `uvm_info("SCBD", $sformatf("Pattern found to match, next out should be 1"), UVM_LOW)
- exp_out = 1;
- end else begin
- exp_out = 0;
- end
-
- endfunction
-endclass
- \ No newline at end of file
+// the design checks two valid sequence patterns and compares
+// expected output to monitored output in each cycle.
+class scoreboard extends uvm_scoreboard;
+ `uvm_component_utils(scoreboard)
+ function new(string name = "scoreboard", uvm_component parent = null);
+ super.new(name, parent);
+ endfunction
+
+ `define LENGTH 4
+ bit [`LENGTH-1:0] act_pattern;
+ bit exp_out;
+ bit seen_1011;
+ bit seen_1100;
+
+ uvm_analysis_imp #(Item, scoreboard) m_analysis_imp;
+
+ virtual function void build_phase(uvm_phase phase);
+ super.build_phase(phase);
+
+ m_analysis_imp = new("m_analysis_imp", this);
+ act_pattern = '0;
+ exp_out = 0;
+ seen_1011 = 0;
+ seen_1100 = 0;
+ endfunction
+
+ virtual function write(Item item);
+ act_pattern = act_pattern << 1 | item.inp;
+ exp_out = ((act_pattern == 4'b1011) || (act_pattern == 4'b1100));
+
+ `uvm_info("SCBD", $sformatf("inp=%0d outp=%0d act=0b%0b", item.inp, item.outp, act_pattern),
+ UVM_LOW)
+
+ if (act_pattern == 4'b1011) begin
+ seen_1011 = 1;
+
+ `uvm_info("SCBD", $sformatf("Pattern found to match"), UVM_LOW)
+ end
+
+ if (act_pattern == 4'b1100) begin
+ seen_1100 = 1;
+
+ `uvm_info("SCBD", $sformatf("Pattern found to match"), UVM_LOW)
+ end
+
+ if (item.outp != exp_out) begin
+ `uvm_error("SCBD", $sformatf("ERROR ! out=%0d exp=%0d", item.outp, exp_out))
+ end else if (exp_out) begin
+ `uvm_info("SCBD", $sformatf("PASS ! out=%0d exp=%0d", item.outp, exp_out), UVM_LOW)
+ end
+ endfunction
+
+ virtual function void report_phase(uvm_phase phase);
+ super.report_phase(phase);
+
+ if (!seen_1011 || !seen_1100)
+ `uvm_error(
+ "SCBD", $sformatf(
+ "Both patterns were not observed (seen_1011=%0d seen_1100=%0d)", seen_1011, seen_1100))
+ endfunction
+endclass
diff --git a/homework_2/SRC/tb.sv b/homework_2/SRC/tb.sv
index fd98597..40ecafc 100644
--- a/homework_2/SRC/tb.sv
+++ b/homework_2/SRC/tb.sv
@@ -1,36 +1,35 @@
-`include "uvm_macros.svh"
-import uvm_pkg::*;
-
-`include "interface.sv"
-`include "item.sv"
-`include "gen_item_seq.sv"
-`include "monitor.sv"
-`include "scoreboard.sv"
-`include "driver.sv"
-`include "agent.sv"
-`include "env.sv"
-`include "base_test.sv"
-
-
-
-`define LENGTH 4
-
-module tb;
- reg clk;
-
- always #10 clk =~ clk;
- des_if _if (clk);
-
- duv u0 ( .clk(clk),
- .rstn(_if.rstn),
- .in(_if.in),
- .out(_if.out));
-
-
- initial begin
- clk <= 0;
- uvm_config_db#(virtual des_if)::set(null, "uvm_test_top", "des_vif", _if);
- run_test("test_1011");
- end
- endmodule
-
+`include "uvm_macros.svh"
+import uvm_pkg::*;
+
+`include "interface.sv"
+`include "item.sv"
+`include "gen_item_seq.sv"
+`include "monitor.sv"
+`include "scoreboard.sv"
+`include "driver.sv"
+`include "agent.sv"
+`include "env.sv"
+`include "base_test.sv"
+
+module tb;
+ reg clk;
+
+ always #10 clk = ~clk;
+
+ des_if _if (clk);
+
+ duv u0 (
+ .clk (clk),
+ .reset(_if.reset),
+ .inp (_if.inp),
+ .outp (_if.outp)
+ );
+
+ initial begin
+ clk <= 0;
+
+ uvm_config_db#(virtual des_if)::set(null, "uvm_test_top", "des_vif", _if);
+
+ run_test("test_both_patterns");
+ end
+endmodule