Given the finite state machine circuit described below, assume that the D flip-flops are initially reset to zero before the machine begins.

// Build this circuit in Verilog.

// Input x goes to three different two-input gates: a XOR, an AND, and a OR gate. Each of the three gates is connected to the input of a D flip-flop and then the flip-flop outputs all go to a three-input XNOR, whose output is Z. The second input of the XOR is its corresponding flip-flop's output, the second input of the AND is its corresponding flip-flop's complemented output, and finally the second input of the OR is its corresponding flip-flop's complementary output.

module top_module (
	input clk,
	input x,
	output z
);

	reg [2:0] s = 0;

	always @(posedge clk) begin
		s <= { s[2] ^ x, ~s[1] & x, ~s[0] | x };
	end

	assign z = ~|s;

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input x,
	output z
);

	reg [2:0] s = 0;

	always @(posedge clk) begin
		s <= { s[2] ^ x, ~s[1] & x, ~s[0] | x };
	end

	assign z = ~|s;

endmodule

module stimulus_gen (
	input clk,
	output logic x,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		x <= 0;
		@(negedge clk) wavedrom_start();
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h1;
			@(posedge clk) x <= 2'h1;
			@(posedge clk) x <= 2'h1;
			@(posedge clk) x <= 2'h1;
		@(negedge clk) wavedrom_stop();
		repeat(100) @(posedge clk, negedge clk)
			x <= $random;

		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_z;
		int errortime_z;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic x;
	logic z_ref;
	logic z_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,x,z_ref,z_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.x );
	reference_module good1 (
		.clk,
		.x,
		.z(z_ref) );

	top_module top_module1 (
		.clk,
		.x,
		.z(z_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_z) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "z", stats1.errors_z, stats1.errortime_z);
		else $display("Hint: Output '%s' has no mismatches.", "z");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { z_ref } === ( { z_ref } ^ { z_dut } ^ { z_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (z_ref !== ( z_ref ^ z_dut ^ z_ref ))
		begin if (stats1.errors_z == 0) stats1.errortime_z = $time;
			stats1.errors_z = stats1.errors_z+1'b1; end

	end
endmodule


This is a combinational circuit. Read the simulation waveforms to determine what the circuit does, then implement it.

// time            a               b               c               d               q
// 0ns             0               0               0               0               0
// 5ns             0               0               0               0               0
// 10ns            0               0               0               0               0
// 15ns            0               0               0               0               0
// 20ns            0               0               0               1               0
// 25ns            0               0               1               0               1
// 30ns            0               0               1               1               1
// 35ns            0               1               0               0               1
// 40ns            0               1               0               1               1
// 45ns            0               1               1               0               1
// 50ns            0               1               1               1               1
// 55ns            1               0               0               0               0
// 60ns            1               0               0               1               0
// 65ns            1               0               1               0               1
// 70ns            1               0               1               1               1
// 75ns            1               1               0               0               1
// 80ns            1               1               0               1               1
// 85ns            1               1               1               0               1
// 90ns            1               1               1               1               1

module top_module (
	input a,
	input b,
	input c,
	input d,
	output q
);

	assign q = c | b;

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input a,
	input b,
	input c,
	input d,
	output q
);

	assign q = c | b;

endmodule

module stimulus_gen (
	input clk,
	output logic a,b,c,d,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		{a,b,c,d} <= 0;
		@(negedge clk) wavedrom_start("Unknown circuit");
			@(posedge clk) {a,b,c,d} <= 0;
			repeat(18) @(posedge clk, negedge clk) {a,b,c,d} <= {a,b,c,d} + 1;
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk)
			{a,b,c,d} <= $urandom;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic a;
	logic b;
	logic c;
	logic d;
	logic q_ref;
	logic q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,c,d,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b,
		.c,
		.d );
	reference_module good1 (
		.a,
		.b,
		.c,
		.d,
		.q(q_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.d,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule


Rule 110 is a one-dimensional cellular automaton with interesting properties (such as being Turing-complete). There is a one-dimensional array of cells (on or off). At each time step, the state of each cell changes. In Rule 110, the next state of each cell depends only on itself and its two neighbours, according to the following table:
// Left | Center | Right | Center's next state
// 1 | 1 | 1 | 0
// 1 | 1 | 0 | 1
// 1 | 0 | 1 | 1
// 1 | 0 | 0 | 0
// 0 | 1 | 1 | 1
// 0 | 1 | 0 | 1
// 0 | 0 | 1 | 1
// 0 | 0 | 0 | 0
// In this circuit, create a 512-cell system (q[511:0]), and advance by one time step each clock cycle. The synchronous active high load input indicates the state of the system should be loaded with data[511:0]. Assume the boundaries (q[-1] and q[512]) are both zero (off).

module top_module(
	input clk,
	input load,
	input [511:0] data,
	output reg [511:0] q);

	always @(posedge clk) begin
		if (load)
			q <= data;
		else begin
			q <=
			~((q[$bits(q)-1:1] & q[$bits(q)-1:0] & {q[$bits(q)-2:0], 1'b0}) |
			(~q[$bits(q)-1:1] & ~q[$bits(q)-1:0] & ~{q[$bits(q)-2:0], 1'b0}) |
			(q[$bits(q)-1:1] & ~q[$bits(q)-1:0] & ~{q[$bits(q)-2:0], 1'b0}) )
			;
		end
	end
endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input load,
	input [511:0] data,
	output reg [511:0] q);

	always @(posedge clk) begin
		if (load)
			q <= data;
		else begin
			q <=
			~((q[$bits(q)-1:1] & q[$bits(q)-1:0] & {q[$bits(q)-2:0], 1'b0}) |
			(~q[$bits(q)-1:1] & ~q[$bits(q)-1:0] & ~{q[$bits(q)-2:0], 1'b0}) |
			(q[$bits(q)-1:1] & ~q[$bits(q)-1:0] & ~{q[$bits(q)-2:0], 1'b0}) )
			;
		end
	end
endmodule

module stimulus_gen (
	input clk,
	output reg load,
	output reg[511:0] data,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		data <= 0;
		data[0] <= 1'b1;
		load <= 1;
		@(posedge clk); wavedrom_start("Load q[511:0] = 1: See Hint.");
		@(posedge clk);
		@(posedge clk);
		load <= 0;
		repeat(10) @(posedge clk);
		wavedrom_stop();

		data <= 0;
		data[256] <= 1'b1;
		load <= 1;
		@(posedge clk);
		@(posedge clk);
		@(posedge clk);
		load <= 0;
		repeat(1000) @(posedge clk) begin
		end
		data <= 512'h4df;
		load <= 1;
		@(posedge clk);
		load <= 0;
		repeat(1000) @(posedge clk) begin
		end
		data <= $random;
		load <= 1;
		@(posedge clk);
		load <= 0;
		repeat(1000) @(posedge clk) begin
		end

		data <= 0;
		load <= 1;
		repeat (20) @(posedge clk);
		@(posedge clk) data <= 2;
		@(posedge clk) data <= 4;
		@(posedge clk) begin
			data <= 9;
			load <= 0;
		end
		@(posedge clk) data <= 12;
		repeat(100) @(posedge clk);

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic load;
	logic [511:0] data;
	logic [511:0] q_ref;
	logic [511:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,load,data,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.load,
		.data );
	reference_module good1 (
		.clk,
		.load,
		.data,
		.q(q_ref) );

	top_module top_module1 (
		.clk,
		.load,
		.data,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule


The following is the state transition table for a Moore state machine with one input, one output, and four states. Implement this state machine. Include a synchronous active high reset that resets the FSM to state A.
// State | Next state in=0, Next state in=1 | Output
// A | A, B | 0
// B | C, B | 0
// C | A, D | 0
// D | C, B | 1

module top_module (
	input clk,
	input in,
	input reset,
	output out
);
	parameter A=0, B=1, C=2, D=3;
	reg [1:0] state;
	reg [1:0] next;

    always_comb begin
		case (state)
			A: next = in ? B : A;
			B: next = in ? B : C;
			C: next = in ? D : A;
			D: next = in ? B : C;
		endcase
    end

    always @(posedge clk) begin
		if (reset) state <= A;
        else state <= next;
	end

	assign out = (state==D);

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input in,
	input reset,
	output out
);
	parameter A=0, B=1, C=2, D=3;
	reg [1:0] state;
	reg [1:0] next;

    always_comb begin
		case (state)
			A: next = in ? B : A;
			B: next = in ? B : C;
			C: next = in ? D : A;
			D: next = in ? B : C;
		endcase
    end

    always @(posedge clk) begin
		if (reset) state <= A;
        else state <= next;
	end

	assign out = (state==D);

endmodule

module stimulus_gen (
	input clk,
	output logic in,
	output logic reset,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	input tb_match
);
	task reset_test(input async=0);
		bit arfail, srfail, datafail;

		@(posedge clk);
		@(posedge clk) reset <= 0;
		repeat(3) @(posedge clk);

		@(negedge clk) begin datafail = !tb_match ; reset <= 1; end
		@(posedge clk) arfail = !tb_match;
		@(posedge clk) begin
			srfail = !tb_match;
			reset <= 0;
		end
		if (srfail)
			$display("Hint: Your reset doesn't seem to be working.");
		else if (arfail && (async || !datafail))
			$display("Hint: Your reset should be %0s, but doesn't appear to be.", async ? "asynchronous" : "synchronous");
		// Don't warn about synchronous reset if the half-cycle before is already wrong. It's more likely
		// a functionality error than the reset being implemented asynchronously.

	endtask

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		reset <= 1;
		in <= 0;
		@(posedge clk) reset <= 0; in <= 1;
		@(posedge clk) in <= 0;
		@(posedge clk) in <= 1;
		wavedrom_start();
			@(posedge clk) in <= 0;
			@(posedge clk) in <= 1;
			@(posedge clk);
			@(negedge clk) reset <= 1;
			@(posedge clk) reset <= 0;
			@(posedge clk) in <= 1;
			@(posedge clk) in <= 1;
			@(posedge clk) in <= 0;
			@(posedge clk) in <= 1;
			@(posedge clk) in <= 0;
			@(posedge clk) in <= 1;
			@(posedge clk) in <= 1;
			@(posedge clk) in <= 1;
		@(negedge clk);
		wavedrom_stop();
		repeat(200) @(posedge clk, negedge clk) begin
			in <= $random;
			reset <= !($random & 31);
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic in;
	logic reset;
	logic out_ref;
	logic out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,in,reset,out_ref,out_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in,
		.reset );
	reference_module good1 (
		.clk,
		.in,
		.reset,
		.out(out_ref) );

	top_module top_module1 (
		.clk,
		.in,
		.reset,
		.out(out_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref } === ( { out_ref } ^ { out_dut } ^ { out_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end

	end
endmodule


This is a combinational circuit. Read the simulation waveforms to determine what the circuit does, then implement it.

// time            a               b               c               d               e               q
// 0ns             x               x               x               x               x               x
// 5ns             x               x               x               x               x               x
// 10ns            x               x               x               x               x               x
// 15ns            a               b               0               d               e               b
// 20ns            a               b               1               d               e               e
// 25ns            a               b               2               d               e               a
// 30ns            a               b               3               d               e               d
// 35ns            a               b               4               d               e               f
// 40ns            a               b               5               d               e               f
// 45ns            a               b               6               d               e               f
// 50ns            a               b               7               d               e               f
// 55ns            a               b               8               d               e               f
// 60ns            a               b               9               d               e               f
// 65ns            a               b               a               d               e               f
// 70ns            a               b               b               d               e               f
// 75ns            a               b               c               d               e               f
// 80ns            a               b               d               d               e               f
// 85ns            a               b               e               d               e               f
// 90ns            a               b               f               d               e               f

module top_module (
	input [3:0] a,
	input [3:0] b,
	input [3:0] c,
	input [3:0] d,
	input [3:0] e,
	output reg [3:0] q
);

	always @(*)
		case (c)
			0: q = b;
			1: q = e;
			2: q = a;
			3: q = d;
			default: q = 4'hf;
		endcase

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [3:0] a,
	input [3:0] b,
	input [3:0] c,
	input [3:0] d,
	input [3:0] e,
	output reg [3:0] q
);

	always @(*)
		case (c)
			0: q = b;
			1: q = e;
			2: q = a;
			3: q = d;
			default: q = 4'hf;
		endcase

endmodule

module stimulus_gen (
	input clk,
	output logic [3:0] a,b,c,d,e,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		@(negedge clk) wavedrom_start("Unknown circuit");
			@(posedge clk) {a,b,c,d,e} <= {20'hab0de};
			repeat(18) @(posedge clk, negedge clk) c <= c + 1;
		wavedrom_stop();

		@(negedge clk) wavedrom_start("Unknown circuit");
			@(posedge clk) {a,b,c,d,e} <= {20'h12034};
			repeat(8) @(posedge clk, negedge clk) c <= c + 1;
			@(posedge clk) {a,b,c,d,e} <= {20'h56078};
			repeat(8) @(posedge clk, negedge clk) c <= c + 1;
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk)
			{a,b,c,d,e} <= $urandom;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [3:0] a;
	logic [3:0] b;
	logic [3:0] c;
	logic [3:0] d;
	logic [3:0] e;
	logic [3:0] q_ref;
	logic [3:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,c,d,e,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b,
		.c,
		.d,
		.e );
	reference_module good1 (
		.a,
		.b,
		.c,
		.d,
		.e,
		.q(q_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.d,
		.e,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule


Find the bug and fix this 8-bit wide 2-to-1 mux.

// module top_module (
//     input sel,
//     input [7:0] a,
//     input [7:0] b,
//     output out  );

//     assign out = (~sel & a) | (sel & b);

// endmodule

module top_module (
	input sel,
	input [7:0] a,
	input [7:0] b,
	output reg [7:0] out
);

	// assign out = (~sel & a) | (sel & b);
    assign out = sel ? a : b;

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input sel,
	input [7:0] a,
	input [7:0] b,
	output reg [7:0] out
);

	// assign out = (~sel & a) | (sel & b);
    assign out = sel ? a : b;

endmodule

module stimulus_gen (
	input clk,
	output logic sel,
	output logic [7:0] a, b,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		{a, b, sel} <= '0;
		@(negedge clk) wavedrom_start("");
			@(posedge clk, negedge clk) {a,b,sel} <= {8'haa, 8'hbb, 1'b0};
			@(posedge clk, negedge clk) {a,b,sel} <= {8'haa, 8'hbb, 1'b0};
			@(posedge clk, negedge clk) {a,b,sel} <= {8'haa, 8'hbb, 1'b1};
			@(posedge clk, negedge clk) {a,b,sel} <= {8'haa, 8'hbb, 1'b0};
			@(posedge clk, negedge clk) {a,b,sel} <= {8'haa, 8'hbb, 1'b1};
			@(posedge clk, negedge clk) {a,b,sel} <= {8'haa, 8'hbb, 1'b1};

			@(posedge clk, negedge clk) {a, b} <= {8'hff, 8'h00}; sel <= 1'b0;
			@(posedge clk, negedge clk) sel <= 1'b0;
			@(posedge clk, negedge clk) sel <= 1'b1;
			@(posedge clk, negedge clk) sel <= 1'b0;
			@(posedge clk, negedge clk) sel <= 1'b1;
			@(posedge clk, negedge clk) sel <= 1'b1;
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk)
			{a,b,sel} <= $urandom;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic sel;
	logic [7:0] a;
	logic [7:0] b;
	logic [7:0] out_ref;
	logic [7:0] out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,sel,a,b,out_ref,out_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.sel,
		.a,
		.b );
	reference_module good1 (
		.sel,
		.a,
		.b,
		.out(out_ref) );

	top_module top_module1 (
		.sel,
		.a,
		.b,
		.out(out_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref } === ( { out_ref } ^ { out_dut } ^ { out_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end

	end
endmodule


Consider this Verilog module "full_module":

// module full_module (
//     input [2:0] r,
//     input L,
//     input clk,
//     output reg [2:0] q
);

// always @(posedge clk) begin
//     if (L) begin
//         q <= r;
//     end else begin
//         q <= {q[1] ^ q[2], q[0], q[2]};
//     end
// end

// endmodule

// You want to create a hierarchical Verilog design where a flipflop and 2-1 multiplexer are in a submodule, and that submodule is instantiated three times in this code. Create the submodule called "top_module".

module top_module(
	input clk,
	input L,
	input q_in,
	input r_in,
	output reg Q);

	initial Q=0;
	always @(posedge clk)
		Q <= L ? r_in : q_in;

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
/*
	Midterm 2015 Question 5a. Build a flip-flop with a 2-to-1 mux before it.
*/
module reference_module(
	input clk,
	input L,
	input q_in,
	input r_in,
	output reg Q);

	initial Q=0;
	always @(posedge clk)
		Q <= L ? r_in : q_in;

endmodule

module stimulus_gen (
	input clk,
	output logic L,
	output logic r_in,
	output logic q_in
);

	always @(posedge clk, negedge clk)
		{L, r_in, q_in} <= $random % 8;

	initial begin
		repeat(100) @(posedge clk);
		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_Q;
		int errortime_Q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic L;
	logic q_in;
	logic r_in;
	logic Q_ref;
	logic Q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,L,q_in,r_in,Q_ref,Q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.L,
		.q_in,
		.r_in );
	reference_module good1 (
		.clk,
		.L,
		.q_in,
		.r_in,
		.Q(Q_ref) );

	top_module top_module1 (
		.clk,
		.L,
		.q_in,
		.r_in,
		.Q(Q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_Q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "Q", stats1.errors_Q, stats1.errortime_Q);
		else $display("Hint: Output '%s' has no mismatches.", "Q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { Q_ref } === ( { Q_ref } ^ { Q_dut } ^ { Q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (Q_ref !== ( Q_ref ^ Q_dut ^ Q_ref ))
		begin if (stats1.errors_Q == 0) stats1.errortime_Q = $time;
			stats1.errors_Q = stats1.errors_Q+1'b1; end

	end
endmodule


For each bit in a 32-bit vector, capture when the input signal changes from 1 in one clock cycle to 0 the next. "Capture" means that the output will remain 1 until the register is reset (active high synchronous reset).

module top_module(
	input clk,
	input reset,
	input [31:0] in,
	output reg [31:0] out);

	reg [31:0] d_last;

	always @(posedge clk) begin
		d_last <= in;
		if (reset)
			out <= '0;
		else
			out <= out | (~in & d_last);
	end

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input reset,
	input [31:0] in,
	output reg [31:0] out);

	reg [31:0] d_last;

	always @(posedge clk) begin
		d_last <= in;
		if (reset)
			out <= '0;
		else
			out <= out | (~in & d_last);
	end

endmodule

module stimulus_gen (
	input clk,
	input tb_match,
	output reg [31:0] in,
	output reg reset,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		in <= 0;
		reset <= 1;
		@(posedge clk);
		reset <= 1;
		in = 0;
		@(negedge clk) wavedrom_start("Example");
		repeat(1) @(posedge clk);
		reset = 0;
		@(posedge clk) in = 32'h2;
		repeat(4) @(posedge clk);
		in = 32'he;
		repeat(2) @(posedge clk);
		in = 0;
		@(posedge clk) in = 32'h2;
		repeat(2) @(posedge clk);
		reset = 1;
		@(posedge clk);
		reset = 0; in = 0;
		repeat(3) @(posedge clk);

		@(negedge clk) wavedrom_stop();

		@(negedge clk) wavedrom_start("");
		repeat(2) @(posedge clk);
		in <= 1;
		repeat(2) @(posedge clk);
		in <= 0;
		repeat(2) @(negedge clk);
		in <= 6;
		repeat(1) @(negedge clk);
		in <= 0;
		repeat(2) @(posedge clk);
		in <= 32'h10;
		repeat(2) @(posedge clk);
		reset <= 1;
		repeat(1) @(posedge clk);
		in <= 32'h0;
		repeat(1) @(posedge clk);
		reset <= 0;
		repeat(1) @(posedge clk);
		reset <= 1;
		in <= 32'h20;
		repeat(1) @(posedge clk);
		reset <= 0;
		in <= 32'h00;

		repeat(2) @(posedge clk);

		@(negedge clk) wavedrom_stop();

		repeat(200)
			@(posedge clk, negedge clk) begin
				in <= $random;
				reset <= !($random & 15);
			end
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic reset;
	logic [31:0] in;
	logic [31:0] out_ref;
	logic [31:0] out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,reset,in,out_ref,out_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.reset,
		.in );
	reference_module good1 (
		.clk,
		.reset,
		.in,
		.out(out_ref) );

	top_module top_module1 (
		.clk,
		.reset,
		.in,
		.out(out_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref } === ( { out_ref } ^ { out_dut } ^ { out_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end

	end
endmodule


Create 8 D flip-flops. All DFFs should be triggered by the positive edge of clk.

module top_module(
	input clk,
	input [7:0] d,
	output reg [7:0] q);

	initial
		q = 8'h0;

	always @(posedge clk)
		q <= d;

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input [7:0] d,
	output reg [7:0] q);

	initial
		q = 8'h0;

	always @(posedge clk)
		q <= d;

endmodule

module stimulus_gen (
	input clk,
	output reg [7:0] d,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	always @(posedge clk, negedge clk)
		d <= $random % 256;

	initial begin
		@(posedge clk);
		wavedrom_start("Positive-edge triggered DFF");
		repeat(10) @(posedge clk);
		wavedrom_stop();
		#100;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [7:0] d;
	logic [7:0] q_ref;
	logic [7:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,d,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.d );
	reference_module good1 (
		.clk,
		.d,
		.q(q_ref) );

	top_module top_module1 (
		.clk,
		.d,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule


Assume that you have two 8-bit 2's complement numbers, a[7:0] and b[7:0]. These numbers are added to produce s[7:0]. Also compute whether a (signed) overflow has occurred.

module top_module (
	input [7:0] a,
	input [7:0] b,
	output [7:0] s,
	output overflow
);

	wire [8:0] sum = a+b;
	assign s = sum[7:0];
	assign overflow = !(a[7]^b[7]) && (a[7] != s[7]);

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [7:0] a,
	input [7:0] b,
	output [7:0] s,
	output overflow
);

	wire [8:0] sum = a+b;
	assign s = sum[7:0];
	assign overflow = !(a[7]^b[7]) && (a[7] != s[7]);

endmodule

module stimulus_gen (
	input clk,
	output logic [7:0] a, b,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		{a, b} <= 0;
		@(negedge clk) wavedrom_start();
			@(posedge clk) {a, b} <= 16'h0;
			@(posedge clk) {a, b} <= 16'h0070;
			@(posedge clk) {a, b} <= 16'h7070;
			@(posedge clk) {a, b} <= 16'h7090;
			@(posedge clk) {a, b} <= 16'h9070;
			@(posedge clk) {a, b} <= 16'h9090;
			@(posedge clk) {a, b} <= 16'h90ff;
		@(negedge clk) wavedrom_stop();
		repeat(100) @(posedge clk, negedge clk)
			{a,b} <= $random;

		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_s;
		int errortime_s;
		int errors_overflow;
		int errortime_overflow;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [7:0] a;
	logic [7:0] b;
	logic [7:0] s_ref;
	logic [7:0] s_dut;
	logic overflow_ref;
	logic overflow_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,s_ref,s_dut,overflow_ref,overflow_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b );
	reference_module good1 (
		.a,
		.b,
		.s(s_ref),
		.overflow(overflow_ref) );

	top_module top_module1 (
		.a,
		.b,
		.s(s_dut),
		.overflow(overflow_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_s) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "s", stats1.errors_s, stats1.errortime_s);
		else $display("Hint: Output '%s' has no mismatches.", "s");
		if (stats1.errors_overflow) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "overflow", stats1.errors_overflow, stats1.errortime_overflow);
		else $display("Hint: Output '%s' has no mismatches.", "overflow");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { s_ref, overflow_ref } === ( { s_ref, overflow_ref } ^ { s_dut, overflow_dut } ^ { s_ref, overflow_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (s_ref !== ( s_ref ^ s_dut ^ s_ref ))
		begin if (stats1.errors_s == 0) stats1.errortime_s = $time;
			stats1.errors_s = stats1.errors_s+1'b1; end
		if (overflow_ref !== ( overflow_ref ^ overflow_dut ^ overflow_ref ))
		begin if (stats1.errors_overflow == 0) stats1.errortime_overflow = $time;
			stats1.errors_overflow = stats1.errors_overflow+1'b1; end

	end
endmodule


Given the following Moore state machine with 3 input (d, done_counting, ack) and 3 outputs (shift_ena, counting, done). Unless otherwise stated in the diagram below, assume outputs are 0 and inputs are don't cares.

// S () --d=0--> S
// S () --d=1--> S1
// S1 () --d=0--> S
// S1 () --d=1--> S11
// S11 () --d=0--> S110
// S11 () --d=1--> S11
// S110 () --d=0--> S
// S110 () --d=1--> B0
// B0 (shift_ena=1) -- (always go to next cycle) --> B1
// B1 (shift_ena=1) -- (always go to next cycle) --> B2
// B2 (shift_ena=1) -- (always go to next cycle) --> B3
// B3 (shift_ena=1) -- (always go to next cycle) --> Count
// Count (counting=1) --!(done_counting)--> Count
// Count (counting=1) --(done_counting)--> Wait
// Wait (done=1) --ack=0--> Wait
// Wait (done=1) --ack=1--> S

// At reset, the state machine starts in state "S". Derive next-state logic equations and output logic equations by inspection assuming the following one-hot encoding is used: (S, S1, S11, S110, B0, B1, B2, B3, Count, Wait) = (10'b0000000001, 10'b0000000010, 10'b0000000100, ... , 10'b1000000000)

// Derive state transition and output logic equations by inspection assuming a one-hot encoding. Implement only the state transition logic and output logic (the combinational logic portion) for this state machine.

// Write code that generates the following equations:

// - B3_next -- next-state logic for state B3
// - S_next
// - S1_next
// - Count_next
// - Wait_next
// - done -- output logic
// - counting
// - shift_ena

module top_module(
    input d,
    input done_counting,
    input ack,
    input [9:0] state,    // 10-bit one-hot current state
    output B3_next,
    output S_next,
    output S1_next,
    output Count_next,
    output Wait_next,
    output done,
    output counting,
    output shift_ena
 );

	parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;

	assign B3_next = state[B2];
	assign S_next = state[S]&~d | state[S1]&~d | state[S110]&~d | state[Wait]&ack;
	assign S1_next = state[S]&d;
	assign Count_next = state[B3] | state[Count]&~done_counting;
	assign Wait_next = state[Count]&done_counting | state[Wait]&~ack;

	assign done = state[Wait];
	assign counting = state[Count];
	assign shift_ena = |state[B3:B0];

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
    input d,
    input done_counting,
    input ack,
    input [9:0] state,    // 10-bit one-hot current state
    output B3_next,
    output S_next,
    output S1_next,
    output Count_next,
    output Wait_next,
    output done,
    output counting,
    output shift_ena
 );

	 parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;

	assign B3_next = state[B2];
	assign S_next = state[S]&~d | state[S1]&~d | state[S110]&~d | state[Wait]&ack;
	assign S1_next = state[S]&d;
	assign Count_next = state[B3] | state[Count]&~done_counting;
	assign Wait_next = state[Count]&done_counting | state[Wait]&~ack;

	assign done = state[Wait];
	assign counting = state[Count];
	assign shift_ena = |state[B3:B0];

endmodule

module stimulus_gen (
	input clk,
	output reg d, done_counting, ack,
	output reg [9:0] state,
	input tb_match
);
	bit failed = 0;
	bit fail_onehot = 0;

	always @(posedge clk, negedge clk)
		if (!tb_match)
			failed <= 1;

	initial begin
		{d, done_counting, ack} <= 3'h0;
		state <= 10'h0;

		repeat(300) @(posedge clk, negedge clk) begin
			{d, done_counting, ack} = $random;
			state <= 1<< ($unsigned($random) % 10);
		end

		@(posedge clk) fail_onehot <= failed;

		repeat(3000) @(posedge clk, negedge clk) begin
			{d, done_counting, ack} = $random;
			state <= $random;
		end

		@(posedge clk);
		if (!fail_onehot && failed) begin
			$display ("Hint: Your circuit passed when given only one-hot inputs, but not with random inputs.");
			$display ("Hint: Are you doing something more complicated than deriving state transition equations by inspection?\n");
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_B3_next;
		int errortime_B3_next;
		int errors_S_next;
		int errortime_S_next;
		int errors_S1_next;
		int errortime_S1_next;
		int errors_Count_next;
		int errortime_Count_next;
		int errors_Wait_next;
		int errortime_Wait_next;
		int errors_done;
		int errortime_done;
		int errors_counting;
		int errortime_counting;
		int errors_shift_ena;
		int errortime_shift_ena;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic d;
	logic done_counting;
	logic ack;
	logic [9:0] state;
	logic B3_next_ref;
	logic B3_next_dut;
	logic S_next_ref;
	logic S_next_dut;
	logic S1_next_ref;
	logic S1_next_dut;
	logic Count_next_ref;
	logic Count_next_dut;
	logic Wait_next_ref;
	logic Wait_next_dut;
	logic done_ref;
	logic done_dut;
	logic counting_ref;
	logic counting_dut;
	logic shift_ena_ref;
	logic shift_ena_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,d,done_counting,ack,state,B3_next_ref,B3_next_dut,S_next_ref,S_next_dut,S1_next_ref,S1_next_dut,Count_next_ref,Count_next_dut,Wait_next_ref,Wait_next_dut,done_ref,done_dut,counting_ref,counting_dut,shift_ena_ref,shift_ena_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.d,
		.done_counting,
		.ack,
		.state );
	reference_module good1 (
		.d,
		.done_counting,
		.ack,
		.state,
		.B3_next(B3_next_ref),
		.S_next(S_next_ref),
		.S1_next(S1_next_ref),
		.Count_next(Count_next_ref),
		.Wait_next(Wait_next_ref),
		.done(done_ref),
		.counting(counting_ref),
		.shift_ena(shift_ena_ref) );

	top_module top_module1 (
		.d,
		.done_counting,
		.ack,
		.state,
		.B3_next(B3_next_dut),
		.S_next(S_next_dut),
		.S1_next(S1_next_dut),
		.Count_next(Count_next_dut),
		.Wait_next(Wait_next_dut),
		.done(done_dut),
		.counting(counting_dut),
		.shift_ena(shift_ena_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_B3_next) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "B3_next", stats1.errors_B3_next, stats1.errortime_B3_next);
		else $display("Hint: Output '%s' has no mismatches.", "B3_next");
		if (stats1.errors_S_next) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "S_next", stats1.errors_S_next, stats1.errortime_S_next);
		else $display("Hint: Output '%s' has no mismatches.", "S_next");
		if (stats1.errors_S1_next) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "S1_next", stats1.errors_S1_next, stats1.errortime_S1_next);
		else $display("Hint: Output '%s' has no mismatches.", "S1_next");
		if (stats1.errors_Count_next) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "Count_next", stats1.errors_Count_next, stats1.errortime_Count_next);
		else $display("Hint: Output '%s' has no mismatches.", "Count_next");
		if (stats1.errors_Wait_next) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "Wait_next", stats1.errors_Wait_next, stats1.errortime_Wait_next);
		else $display("Hint: Output '%s' has no mismatches.", "Wait_next");
		if (stats1.errors_done) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "done", stats1.errors_done, stats1.errortime_done);
		else $display("Hint: Output '%s' has no mismatches.", "done");
		if (stats1.errors_counting) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "counting", stats1.errors_counting, stats1.errortime_counting);
		else $display("Hint: Output '%s' has no mismatches.", "counting");
		if (stats1.errors_shift_ena) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "shift_ena", stats1.errors_shift_ena, stats1.errortime_shift_ena);
		else $display("Hint: Output '%s' has no mismatches.", "shift_ena");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { B3_next_ref, S_next_ref, S1_next_ref, Count_next_ref, Wait_next_ref, done_ref, counting_ref, shift_ena_ref } === ( { B3_next_ref, S_next_ref, S1_next_ref, Count_next_ref, Wait_next_ref, done_ref, counting_ref, shift_ena_ref } ^ { B3_next_dut, S_next_dut, S1_next_dut, Count_next_dut, Wait_next_dut, done_dut, counting_dut, shift_ena_dut } ^ { B3_next_ref, S_next_ref, S1_next_ref, Count_next_ref, Wait_next_ref, done_ref, counting_ref, shift_ena_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (B3_next_ref !== ( B3_next_ref ^ B3_next_dut ^ B3_next_ref ))
		begin if (stats1.errors_B3_next == 0) stats1.errortime_B3_next = $time;
			stats1.errors_B3_next = stats1.errors_B3_next+1'b1; end
		if (S_next_ref !== ( S_next_ref ^ S_next_dut ^ S_next_ref ))
		begin if (stats1.errors_S_next == 0) stats1.errortime_S_next = $time;
			stats1.errors_S_next = stats1.errors_S_next+1'b1; end
		if (S1_next_ref !== ( S1_next_ref ^ S1_next_dut ^ S1_next_ref ))
		begin if (stats1.errors_S1_next == 0) stats1.errortime_S1_next = $time;
			stats1.errors_S1_next = stats1.errors_S1_next+1'b1; end
		if (Count_next_ref !== ( Count_next_ref ^ Count_next_dut ^ Count_next_ref ))
		begin if (stats1.errors_Count_next == 0) stats1.errortime_Count_next = $time;
			stats1.errors_Count_next = stats1.errors_Count_next+1'b1; end
		if (Wait_next_ref !== ( Wait_next_ref ^ Wait_next_dut ^ Wait_next_ref ))
		begin if (stats1.errors_Wait_next == 0) stats1.errortime_Wait_next = $time;
			stats1.errors_Wait_next = stats1.errors_Wait_next+1'b1; end
		if (done_ref !== ( done_ref ^ done_dut ^ done_ref ))
		begin if (stats1.errors_done == 0) stats1.errortime_done = $time;
			stats1.errors_done = stats1.errors_done+1'b1; end
		if (counting_ref !== ( counting_ref ^ counting_dut ^ counting_ref ))
		begin if (stats1.errors_counting == 0) stats1.errortime_counting = $time;
			stats1.errors_counting = stats1.errors_counting+1'b1; end
		if (shift_ena_ref !== ( shift_ena_ref ^ shift_ena_dut ^ shift_ena_ref ))
		begin if (stats1.errors_shift_ena == 0) stats1.errortime_shift_ena = $time;
			stats1.errors_shift_ena = stats1.errors_shift_ena+1'b1; end

	end
endmodule


Build a two-bit saturating counter. The counter increments (up to a maximum of 3) when train_valid = 1 and train_taken = 1. It decrements (down to a minimum of 0) when train_valid = 1 and train_taken = 0. When not training (train_valid = 0), the counter keeps its value unchanged. areset is a positive edge triggered asynchronous reset that resets the counter to weakly not-taken (2'b01). Output state[1:0] is the two-bit counter value.

module top_module(
    input clk,
    input areset,
    input train_valid,
    input train_taken,
    output logic [1:0] state
);
    always @(posedge clk, posedge areset) begin
        if (areset)
            state <= 1;
        else if (train_valid) begin
            if(state < 3 && train_taken)
                state <= state + 1;
            else if(state > 0 && !train_taken)
                state <= state - 1;
        end
    end
endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
    input clk,
    input areset,
    input train_valid,
    input train_taken,
    output logic [1:0] state
);
    always @(posedge clk, posedge areset) begin
        if (areset)
            state <= 1;
        else if (train_valid) begin
            if(state < 3 && train_taken)
                state <= state + 1;
            else if(state > 0 && !train_taken)
                state <= state - 1;
        end
    end
endmodule

module stimulus_gen(
	input clk,
	output logic areset,
	output logic train_valid,
	output train_taken,

	input tb_match,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	output int wavedrom_hide_after_time
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	reg reset;
	task reset_test(input async=0);
		bit arfail, srfail, datafail;

		@(posedge clk);
		@(posedge clk) reset <= 0;
		repeat(3) @(posedge clk);

		@(negedge clk) begin datafail = !tb_match ; reset <= 1; end
		@(posedge clk) arfail = !tb_match;
		@(posedge clk) begin
			srfail = !tb_match;
			reset <= 0;
		end
		if (srfail)
			$display("Hint: Your reset doesn't seem to be working.");
		else if (arfail && (async || !datafail))
			$display("Hint: Your reset should be %0s, but doesn't appear to be.", async ? "asynchronous" : "synchronous");
		// Don't warn about synchronous reset if the half-cycle before is already wrong. It's more likely
		// a functionality error than the reset being implemented asynchronously.

	endtask

	assign areset = reset;
	logic train_taken_r;
	assign train_taken = train_valid ? train_taken_r : 1'bx;

	initial begin
		@(posedge clk);
		@(posedge clk) reset <= 1;
		@(posedge clk) reset <= 0;
		train_taken_r <= 1;
		train_valid <= 1;

		wavedrom_start("Asynchronous reset");
			reset_test(1); // Test for asynchronous reset
		wavedrom_stop();
		@(posedge clk) reset <= 1;
		train_taken_r <= 1;
		train_valid <= 0;
		@(posedge clk) reset <= 0;

		wavedrom_start("Count up, then down");
		train_taken_r <= 1;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 0;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 0;
			@(posedge clk) train_valid <= 1;
		train_taken_r <= 0;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 0;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 1;
			@(posedge clk) train_valid <= 0;
			@(posedge clk) train_valid <= 1;
		wavedrom_stop();

		repeat(1000) @(posedge clk,negedge clk)
			{train_valid, train_taken_r} <= {$urandom} ;

		#1 $finish;
	end

endmodule
module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_state;
		int errortime_state;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic areset;
	logic train_valid;
	logic train_taken;
	logic [1:0] state_ref;
	logic [1:0] state_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,areset,train_valid,train_taken,state_ref,state_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.areset,
		.train_valid,
		.train_taken );
	reference_module good1 (
		.clk,
		.areset,
		.train_valid,
		.train_taken,
		.state(state_ref) );

	top_module top_module1 (
		.clk,
		.areset,
		.train_valid,
		.train_taken,
		.state(state_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_state) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "state", stats1.errors_state, stats1.errortime_state);
		else $display("Hint: Output '%s' has no mismatches.", "state");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { state_ref } === ( { state_ref } ^ { state_dut } ^ { state_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (state_ref !== ( state_ref ^ state_dut ^ state_ref ))
		begin if (stats1.errors_state == 0) stats1.errortime_state = $time;
			stats1.errors_state = stats1.errors_state+1'b1; end

	end
endmodule


Build a priority encoder for 8-bit inputs. Given an 8-bit vector, the output should report the first (least significant) bit in the vector that is 1. Report zero if the input vector has no bits that are high. For example, the input 8'b10010000 should output 3'd4, because bit[4] is first bit that is high.

module top_module (
	input [7:0] in,
	output reg [2:0] pos
);

	always @(*) begin
		casez (in)
			default : pos = 2'h0;
			8'bzzzzzzz1: pos = 3'h0;
			8'bzzzzzz1z: pos = 3'h1;
			8'bzzzzz1zz: pos = 3'h2;
			8'bzzzz1zzz: pos = 3'h3;
			8'bzzz1zzzz: pos = 3'h4;
			8'bzz1zzzzz: pos = 3'h5;
			8'bz1zzzzzz: pos = 3'h6;
			8'b1zzzzzzz: pos = 3'h7;
		endcase
	end

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [7:0] in,
	output reg [2:0] pos
);

	always @(*) begin
		casez (in)
			default : pos = 2'h0;
			8'bzzzzzzz1: pos = 3'h0;
			8'bzzzzzz1z: pos = 3'h1;
			8'bzzzzz1zz: pos = 3'h2;
			8'bzzzz1zzz: pos = 3'h3;
			8'bzzz1zzzz: pos = 3'h4;
			8'bzz1zzzzz: pos = 3'h5;
			8'bz1zzzzzz: pos = 3'h6;
			8'b1zzzzzzz: pos = 3'h7;
		endcase
	end

endmodule

module stimulus_gen (
	input clk,
	output logic [7:0] in,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		@(negedge clk) wavedrom_start("Priority encoder");
			@(posedge clk) in <= 8'h1;
			repeat(8) @(posedge clk) in <= in << 1;
			in <= 8'h10;
			repeat(8) @(posedge clk) in <= in + 1;
		@(negedge clk) wavedrom_stop();

		repeat(50) @(posedge clk, negedge clk) begin
			in <= $urandom;
		end
		repeat(260) @(posedge clk, negedge clk) begin
			in <= in + 1;
		end
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_pos;
		int errortime_pos;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [7:0] in;
	logic [2:0] pos_ref;
	logic [2:0] pos_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,in,pos_ref,pos_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in );
	reference_module good1 (
		.in,
		.pos(pos_ref) );

	top_module top_module1 (
		.in,
		.pos(pos_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_pos) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "pos", stats1.errors_pos, stats1.errortime_pos);
		else $display("Hint: Output '%s' has no mismatches.", "pos");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { pos_ref } === ( { pos_ref } ^ { pos_dut } ^ { pos_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (pos_ref !== ( pos_ref ^ pos_dut ^ pos_ref ))
		begin if (stats1.errors_pos == 0) stats1.errortime_pos = $time;
			stats1.errors_pos = stats1.errors_pos+1'b1; end

	end
endmodule


Suppose you're building a circuit to process scancodes from a PS/2 keyboard for a game. Given the last two bytes of scancodes received, you need to indicate whether one of the arrow keys on the keyboard have been pressed. This involves a fairly simple mapping, which can be implemented as a case statement (or if-elseif) with four cases.
// Scancode[15:0] | Arrow key
// 16'he06b | left arrow
// 16'he072 | down arrow
// 16'he074 | right arrow
// 16'he075 | up arrow
// Anything else | none
// Your circuit has one 16-bit input, and four outputs. Build this circuit that recognizes these four scancodes and asserts the correct output.

module top_module (
	input [15:0] scancode,
	output reg left,
	output reg down,
	output reg right,
	output reg up
);

	always @(*) begin
		{up, left, down, right} = 0;
		case (scancode)
			16'he06b: left = 1;
			16'he072: down = 1;
			16'he074: right = 1;
			16'he075: up = 1;
		endcase
	end

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [15:0] scancode,
	output reg left,
	output reg down,
	output reg right,
	output reg up
);

	always @(*) begin
		{up, left, down, right} = 0;
		case (scancode)
			16'he06b: left = 1;
			16'he072: down = 1;
			16'he074: right = 1;
			16'he075: up = 1;
		endcase
	end

endmodule

module stimulus_gen (
	input clk,
	output logic [15:0] scancode,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		@(negedge clk) wavedrom_start("Recognize arrow keys");
			@(posedge clk) scancode <= 16'h0;
			@(posedge clk) scancode <= 16'h1;
			@(posedge clk) scancode <= 16'he075;
			@(posedge clk) scancode <= 16'he06b;
			@(posedge clk) scancode <= 16'he06c;
			@(posedge clk) scancode <= 16'he072;
			@(posedge clk) scancode <= 16'he074;
			@(posedge clk) scancode <= 16'he076;
			@(posedge clk) scancode <= 16'hffff;
		@(negedge clk) wavedrom_stop();

		repeat(30000) @(posedge clk, negedge clk) begin
			scancode <= $urandom;
		end
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_left;
		int errortime_left;
		int errors_down;
		int errortime_down;
		int errors_right;
		int errortime_right;
		int errors_up;
		int errortime_up;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [15:0] scancode;
	logic left_ref;
	logic left_dut;
	logic down_ref;
	logic down_dut;
	logic right_ref;
	logic right_dut;
	logic up_ref;
	logic up_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,scancode,left_ref,left_dut,down_ref,down_dut,right_ref,right_dut,up_ref,up_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.scancode );
	reference_module good1 (
		.scancode,
		.left(left_ref),
		.down(down_ref),
		.right(right_ref),
		.up(up_ref) );

	top_module top_module1 (
		.scancode,
		.left(left_dut),
		.down(down_dut),
		.right(right_dut),
		.up(up_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_left) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "left", stats1.errors_left, stats1.errortime_left);
		else $display("Hint: Output '%s' has no mismatches.", "left");
		if (stats1.errors_down) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "down", stats1.errors_down, stats1.errortime_down);
		else $display("Hint: Output '%s' has no mismatches.", "down");
		if (stats1.errors_right) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "right", stats1.errors_right, stats1.errortime_right);
		else $display("Hint: Output '%s' has no mismatches.", "right");
		if (stats1.errors_up) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "up", stats1.errors_up, stats1.errortime_up);
		else $display("Hint: Output '%s' has no mismatches.", "up");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { left_ref, down_ref, right_ref, up_ref } === ( { left_ref, down_ref, right_ref, up_ref } ^ { left_dut, down_dut, right_dut, up_dut } ^ { left_ref, down_ref, right_ref, up_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (left_ref !== ( left_ref ^ left_dut ^ left_ref ))
		begin if (stats1.errors_left == 0) stats1.errortime_left = $time;
			stats1.errors_left = stats1.errors_left+1'b1; end
		if (down_ref !== ( down_ref ^ down_dut ^ down_ref ))
		begin if (stats1.errors_down == 0) stats1.errortime_down = $time;
			stats1.errors_down = stats1.errors_down+1'b1; end
		if (right_ref !== ( right_ref ^ right_dut ^ right_ref ))
		begin if (stats1.errors_right == 0) stats1.errortime_right = $time;
			stats1.errors_right = stats1.errors_right+1'b1; end
		if (up_ref !== ( up_ref ^ up_dut ^ up_ref ))
		begin if (stats1.errors_up == 0) stats1.errortime_up = $time;
			stats1.errors_up = stats1.errors_up+1'b1; end

	end
endmodule


Implement a 4-bit adder with full adders. The output sum should include the overflow bit.

module top_module (
	input [3:0] x,
	input [3:0] y,
	output [4:0] sum
);

	assign sum = x+y;
endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [3:0] x,
	input [3:0] y,
	output [4:0] sum
);

	assign sum = x+y;
endmodule

module stimulus_gen (
	input clk,
	output logic [3:0] x,y
);

	initial begin
		repeat(100) @(posedge clk, negedge clk) begin
			{x,y} <= $random;
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_sum;
		int errortime_sum;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [3:0] x;
	logic [3:0] y;
	logic [4:0] sum_ref;
	logic [4:0] sum_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,x,y,sum_ref,sum_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.x,
		.y );
	reference_module good1 (
		.x,
		.y,
		.sum(sum_ref) );

	top_module top_module1 (
		.x,
		.y,
		.sum(sum_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_sum) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "sum", stats1.errors_sum, stats1.errortime_sum);
		else $display("Hint: Output '%s' has no mismatches.", "sum");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { sum_ref } === ( { sum_ref } ^ { sum_dut } ^ { sum_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (sum_ref !== ( sum_ref ^ sum_dut ^ sum_ref ))
		begin if (stats1.errors_sum == 0) stats1.errortime_sum = $time;
			stats1.errors_sum = stats1.errors_sum+1'b1; end

	end
endmodule


Build a 32-bit global history shift register, including support for rolling back state in response to a pipeline flush caused by a branch misprediction. When a branch prediction is made (predict_valid = 1), shift in predict_taken from the LSB side to update the branch history for the predicted branch. (predict_history[0] is the direction of the youngest branch.) When a branch misprediction occurs (train_mispredicted = 1), load the branch history register with the history after the completion of the mispredicted branch. This is the history before the mispredicted branch (train_history) concatenated with the actual result of the branch (train_taken). If both a prediction and misprediction occur at the same time, the misprediction takes precedence, because the pipeline flush will also flush out the branch that is currently making a prediction. predict_history is the value of the branch history register. areset is a positive edge triggered asynchronous reset that resets the history counter to zero.

module top_module
(
    input clk,
    input areset,
    input predict_valid,
    input predict_taken,
    output logic [31:0] predict_history,

    input train_mispredicted,
    input train_taken,
    input [31:0] train_history
);
    always@(posedge clk, posedge areset)
		if (areset) begin
			predict_history = 0;
        end	else begin
			if (train_mispredicted)
				predict_history <= {train_history, train_taken};
			else if (predict_valid)
				predict_history <= {predict_history, predict_taken};
		end
endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module
(
    input clk,
    input areset,
    input predict_valid,
    input predict_taken,
    output logic [31:0] predict_history,

    input train_mispredicted,
    input train_taken,
    input [31:0] train_history
);
    always@(posedge clk, posedge areset)
		if (areset) begin
			predict_history = 0;
        end	else begin
			if (train_mispredicted)
				predict_history <= {train_history, train_taken};
			else if (predict_valid)
				predict_history <= {predict_history, predict_taken};
		end
endmodule

module stimulus_gen
(
	input clk,
	output logic areset,

	output logic predict_valid,
	output predict_taken,

	output logic train_mispredicted,
	output train_taken,
	output [31:0] train_history,

	input tb_match,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	output int wavedrom_hide_after_time
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	reg reset;
	task reset_test(input async=0);
		bit arfail, srfail, datafail;

		@(posedge clk);
		@(posedge clk) reset <= 0;
		repeat(3) @(posedge clk);

		@(negedge clk) begin datafail = !tb_match ; reset <= 1; end
		@(posedge clk) arfail = !tb_match;
		@(posedge clk) begin
			srfail = !tb_match;
			reset <= 0;
		end
		if (srfail)
			$display("Hint: Your reset doesn't seem to be working.");
		else if (arfail && (async || !datafail))
			$display("Hint: Your reset should be %0s, but doesn't appear to be.", async ? "asynchronous" : "synchronous");
		// Don't warn about synchronous reset if the half-cycle before is already wrong. It's more likely
		// a functionality error than the reset being implemented asynchronously.

	endtask

	assign areset = reset;
	logic predict_taken_r;
	assign predict_taken = predict_valid ? predict_taken_r : 1'bx;

	logic train_taken_r;
	logic [31:0] train_history_r;
	assign train_taken = train_mispredicted ? train_taken_r : 1'bx;
	assign train_history = train_mispredicted ? train_history_r : 32'hx;

	initial begin
		@(posedge clk) reset <= 1;
		@(posedge clk) reset <= 0;
		predict_taken_r <= 1;
		predict_valid <= 1;
		train_mispredicted <= 0;
		train_history_r <= 32'h5;
		train_taken_r <= 1;

		wavedrom_start("Asynchronous reset");
			reset_test(1); // Test for asynchronous reset
		wavedrom_stop();
		@(posedge clk) reset <= 1;
		predict_valid <= 0;

		wavedrom_start("Predictions: Shift in");
		repeat(2) @(posedge clk) {predict_valid, predict_taken_r} <= {$urandom};
		reset <= 0;
		predict_valid <= 1;
		repeat(6) @(posedge clk) {predict_taken_r} <= {$urandom};
		predict_valid <= 0;
		repeat(3) @(posedge clk) {predict_taken_r} <= {$urandom};
		predict_valid <= 1;
		train_mispredicted <= 1;
		@(posedge clk) train_mispredicted <= 0;
		repeat(6) @(posedge clk) {predict_taken_r} <= {$urandom};
		wavedrom_stop();

		repeat(2000) @(posedge clk,negedge clk) begin
			{predict_valid, predict_taken_r, train_taken_r} <= {$urandom};
			train_history_r <= $urandom;
			train_mispredicted <= !($urandom_range(0,31));
		end

		#1 $finish;
	end

endmodule
module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_predict_history;
		int errortime_predict_history;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic areset;
	logic predict_valid;
	logic predict_taken;
	logic train_mispredicted;
	logic train_taken;
	logic [31:0] train_history;
	logic [31:0] predict_history_ref;
	logic [31:0] predict_history_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,areset,predict_valid,predict_taken,train_mispredicted,train_taken,train_history,predict_history_ref,predict_history_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.areset,
		.predict_valid,
		.predict_taken,
		.train_mispredicted,
		.train_taken,
		.train_history );
	reference_module good1 (
		.clk,
		.areset,
		.predict_valid,
		.predict_taken,
		.train_mispredicted,
		.train_taken,
		.train_history,
		.predict_history(predict_history_ref) );

	top_module top_module1 (
		.clk,
		.areset,
		.predict_valid,
		.predict_taken,
		.train_mispredicted,
		.train_taken,
		.train_history,
		.predict_history(predict_history_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_predict_history) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "predict_history", stats1.errors_predict_history, stats1.errortime_predict_history);
		else $display("Hint: Output '%s' has no mismatches.", "predict_history");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { predict_history_ref } === ( { predict_history_ref } ^ { predict_history_dut } ^ { predict_history_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (predict_history_ref !== ( predict_history_ref ^ predict_history_dut ^ predict_history_ref ))
		begin if (stats1.errors_predict_history == 0) stats1.errortime_predict_history = $time;
			stats1.errors_predict_history = stats1.errors_predict_history+1'b1; end

	end
endmodule


Implement the following circuit. Create two intermediate wires (named anything you want) to connect the AND and OR gates together. Note that the wire that feeds the NOT gate is really wire `out`, so you do not necessarily need to declare a third wire here. Notice how wires are driven by exactly one source (output of a gate), but can feed multiple inputs.

// The circuit is composed of two layers. The first layer, counting from the input, is two AND gates: one whose input is connected to a and b, and the second is connected to c and d. The second layer there is an OR gate to OR the two AND outputs, connected the output 'out'. Additionally, there is an inverted output 'out_n'.

module top_module (
	input a,
	input b,
	input c,
	input d,
	output out,
	output out_n );

	wire w1, w2;
	assign w1 = a&b;
	assign w2 = c&d;
	assign out = w1|w2;
	assign out_n = ~out;

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
// hdlbits_prop {len: 5}
module reference_module (
	input a,
	input b,
	input c,
	input d,
	output out,
	output out_n );

	wire w1, w2;
	assign w1 = a&b;
	assign w2 = c&d;
	assign out = w1|w2;
	assign out_n = ~out;

endmodule

module stimulus_gen (
	input clk,
	output reg a,b,c,d,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		{a,b,c,d} = 4'h0;
		@(negedge clk);
		wavedrom_start("Exhaustive test");
		repeat(20) @(posedge clk, negedge clk)
			{d,c,b,a} <= {d,c,b,a} + 1'b1;
		wavedrom_stop();
		repeat(100) @(posedge clk, negedge clk) begin
			{a,b,c,d} <= $random;
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;
		int errors_out_n;
		int errortime_out_n;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic a;
	logic b;
	logic c;
	logic d;
	logic out_ref;
	logic out_dut;
	logic out_n_ref;
	logic out_n_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,c,d,out_ref,out_dut,out_n_ref,out_n_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b,
		.c,
		.d );
	reference_module good1 (
		.a,
		.b,
		.c,
		.d,
		.out(out_ref),
		.out_n(out_n_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.d,
		.out(out_dut),
		.out_n(out_n_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");
		if (stats1.errors_out_n) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_n", stats1.errors_out_n, stats1.errortime_out_n);
		else $display("Hint: Output '%s' has no mismatches.", "out_n");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref, out_n_ref } === ( { out_ref, out_n_ref } ^ { out_dut, out_n_dut } ^ { out_ref, out_n_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end
		if (out_n_ref !== ( out_n_ref ^ out_n_dut ^ out_n_ref ))
		begin if (stats1.errors_out_n == 0) stats1.errortime_out_n = $time;
			stats1.errors_out_n = stats1.errors_out_n+1'b1; end

	end
endmodule


Create a single D flip-flop.

module top_module(
	input clk,
	input d,
	output reg q);

	initial
		q = 1'hx;

	always @(posedge clk)
		q <= d;

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input d,
	output reg q);

	initial
		q = 1'hx;

	always @(posedge clk)
		q <= d;

endmodule

module stimulus_gen (
	input clk,
	output reg d,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	always @(posedge clk, negedge clk)
		d <= $urandom;

	initial begin
		@(posedge clk);
		wavedrom_start("Positive-edge triggered DFF");
		repeat(10) @(posedge clk);
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk);
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic d;
	logic q_ref;
	logic q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,d,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.d );
	reference_module good1 (
		.clk,
		.d,
		.q(q_ref) );

	top_module top_module1 (
		.clk,
		.d,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule


In this question, you will design a circuit for an 8x1 memory, where writing to the memory is accomplished by shifting-in bits, and reading is "random access", as in a typical RAM. You will then use the circuit to realize a 3-input logic function. First, create an 8-bit shift register with 8 D-type flip-flops. Label the flip-flop outputs from Q[0]...Q[7]. The shift register input should be called S, which feeds the input of Q[0] (MSB is shifted in first). The enable input is synchronous active high and controls whether to shift. Extend the circuit to have 3 additional inputs A,B,C and an output Z. The circuit's behaviour should be as follows: when ABC is 000, Z=Q[0], when ABC is 001, Z=Q[1], and so on. Your circuit should contain ONLY the 8-bit shift register, and multiplexers.

module top_module (
	input clk,
	input enable,
	input S,
	input A,
	input B,
	input C,
	output reg Z
);

	reg [7:0] q;
	always @(posedge clk) begin
		if (enable)
			q <= {q[6:0], S};
	end

	assign Z = q[ {A, B, C} ];

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input enable,
	input S,
	input A,
	input B,
	input C,
	output reg Z
);

	reg [7:0] q;
	always @(posedge clk) begin
		if (enable)
			q <= {q[6:0], S};
	end

	assign Z = q[ {A, B, C} ];

endmodule

module stimulus_gen (
	input clk,
	output logic S, enable,
	output logic A, B, C,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		enable <= 0;
		{A,B,C} <= 0;
		S <= 1'bx;
		@(negedge clk) wavedrom_start("A 3-input AND gate");
			@(posedge clk);
			@(posedge clk) enable <= 1; S <= 1;
			@(posedge clk) S <= 0;
			@(posedge clk) S <= 0;
			@(posedge clk) S <= 0;
			@(posedge clk) S <= 0;
			@(posedge clk) S <= 0;
			@(posedge clk) S <= 0;
			@(posedge clk) S <= 0;
			@(posedge clk) enable <= 0; S <= 1'bx;
			{A,B,C} <= 5;
			@(posedge clk) {A,B,C} <= 6;
			@(posedge clk) {A,B,C} <= 7;
			@(posedge clk) {A,B,C} <= 0;
			@(posedge clk) {A,B,C} <= 1;
		@(negedge clk) wavedrom_stop();

		repeat(500) @(posedge clk, negedge clk) begin
			{A,B,C,S} <= $random;
			enable <= ($random&3) == 0;
		end

		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_Z;
		int errortime_Z;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic enable;
	logic S;
	logic A;
	logic B;
	logic C;
	logic Z_ref;
	logic Z_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,enable,S,A,B,C,Z_ref,Z_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.enable,
		.S,
		.A,
		.B,
		.C );
	reference_module good1 (
		.clk,
		.enable,
		.S,
		.A,
		.B,
		.C,
		.Z(Z_ref) );

	top_module top_module1 (
		.clk,
		.enable,
		.S,
		.A,
		.B,
		.C,
		.Z(Z_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_Z) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "Z", stats1.errors_Z, stats1.errortime_Z);
		else $display("Hint: Output '%s' has no mismatches.", "Z");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { Z_ref } === ( { Z_ref } ^ { Z_dut } ^ { Z_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (Z_ref !== ( Z_ref ^ Z_dut ^ Z_ref ))
		begin if (stats1.errors_Z == 0) stats1.errortime_Z = $time;
			stats1.errors_Z = stats1.errors_Z+1'b1; end

	end
endmodule


A heating/cooling thermostat controls both a heater (during winter) and an air conditioner (during summer). Implement a circuit that will turn on and off the heater, air conditioning, and blower fan as appropriate. The thermostat can be in one of two modes: heating (mode = 1) and cooling (mode = 0). In heating mode, turn the heater on when it is too cold (too_cold = 1) but do not use the air conditioner. In cooling mode, turn the air conditioner on when it is too hot (too_hot = 1), but do not turn on the heater. When the heater or air conditioner are on, also turn on the fan to circulate the air. In addition, the user can also request the fan to turn on (fan_on = 1), even if the heater and air conditioner are off.

module top_module(
	input mode,
	input too_cold,
	input too_hot,
	input fan_on,
	output heater,
	output aircon,
	output fan
);

	assign fan = (mode ? too_cold : too_hot) | fan_on;
	assign heater = (mode & too_cold);
	assign aircon = (~mode & too_hot);

endmodule

`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input mode,
	input too_cold,
	input too_hot,
	input fan_on,
	output heater,
	output aircon,
	output fan
);

	assign fan = (mode ? too_cold : too_hot) | fan_on;
	assign heater = (mode & too_cold);
	assign aircon = (~mode & too_hot);

endmodule

module stimulus_gen (
	input clk,
	output reg too_cold, too_hot, mode, fan_on,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		{too_cold, too_hot, mode, fan_on} <= 4'b0010;
		@(negedge clk);
		wavedrom_start("Winter");
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0010;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0010;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1010;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1011;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0010;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0011;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0010;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0110;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1110;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0111;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1111;
		@(negedge clk) wavedrom_stop();

		{too_cold, too_hot, mode, fan_on} <= 4'b0000;
		@(negedge clk);
		wavedrom_start("Summer");
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0000;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0000;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0100;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0101;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0000;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0001;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b0000;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1000;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1100;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1001;
			@(posedge clk) {too_cold, too_hot, mode, fan_on} <= 4'b1101;
		@(negedge clk) wavedrom_stop();

		repeat(200)
			@(posedge clk, negedge clk) {too_cold, too_hot, mode, fan_on} <= $random;

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_heater;
		int errortime_heater;
		int errors_aircon;
		int errortime_aircon;
		int errors_fan;
		int errortime_fan;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic mode;
	logic too_cold;
	logic too_hot;
	logic fan_on;
	logic heater_ref;
	logic heater_dut;
	logic aircon_ref;
	logic aircon_dut;
	logic fan_ref;
	logic fan_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,mode,too_cold,too_hot,fan_on,heater_ref,heater_dut,aircon_ref,aircon_dut,fan_ref,fan_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.mode,
		.too_cold,
		.too_hot,
		.fan_on );
	reference_module good1 (
		.mode,
		.too_cold,
		.too_hot,
		.fan_on,
		.heater(heater_ref),
		.aircon(aircon_ref),
		.fan(fan_ref) );

	top_module top_module1 (
		.mode,
		.too_cold,
		.too_hot,
		.fan_on,
		.heater(heater_dut),
		.aircon(aircon_dut),
		.fan(fan_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_heater) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "heater", stats1.errors_heater, stats1.errortime_heater);
		else $display("Hint: Output '%s' has no mismatches.", "heater");
		if (stats1.errors_aircon) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "aircon", stats1.errors_aircon, stats1.errortime_aircon);
		else $display("Hint: Output '%s' has no mismatches.", "aircon");
		if (stats1.errors_fan) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "fan", stats1.errors_fan, stats1.errortime_fan);
		else $display("Hint: Output '%s' has no mismatches.", "fan");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { heater_ref, aircon_ref, fan_ref } === ( { heater_ref, aircon_ref, fan_ref } ^ { heater_dut, aircon_dut, fan_dut } ^ { heater_ref, aircon_ref, fan_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (heater_ref !== ( heater_ref ^ heater_dut ^ heater_ref ))
		begin if (stats1.errors_heater == 0) stats1.errortime_heater = $time;
			stats1.errors_heater = stats1.errors_heater+1'b1; end
		if (aircon_ref !== ( aircon_ref ^ aircon_dut ^ aircon_ref ))
		begin if (stats1.errors_aircon == 0) stats1.errortime_aircon = $time;
			stats1.errors_aircon = stats1.errors_aircon+1'b1; end
		if (fan_ref !== ( fan_ref ^ fan_dut ^ fan_ref ))
		begin if (stats1.errors_fan == 0) stats1.errortime_fan = $time;
			stats1.errors_fan = stats1.errors_fan+1'b1; end

	end
endmodule