dakies/OSS_Verilog huggingface dataset:
module glitch_filter #(
	parameter integer L = 2
)(
	input wire  pin_iob_reg,
	input wire  cond,

	output wire val,
	output reg  rise,
	output reg  fall,

	input  wire clk,
	input  wire rst
);
	// Signals
	wire [L-1:0] all_zero;
	wire [L-1:0] all_one;
	wire [L-1:0] all_cur;

	reg [1:0] sync;
	reg state;
	reg [L-1:0] cnt;

	// Constants
	assign all_zero = { L{1'b0} };
	assign all_one  = { L{1'b1} };
	assign all_cur  = { L{sync[1]} };

	// Synchronizer
	always @(posedge clk)
		sync <= { sync[0], pin_iob_reg };

	// Filter
	always @(posedge clk)
		if (rst)
			cnt <= all_cur;
		else begin
			if (sync[1] & (cnt != all_one))
				cnt <= cnt + 1;
			else if (~sync[1] & (cnt != all_zero))
				cnt <= cnt - 1;
			else
				cnt <= cnt;
		end

	// State
	always @(posedge clk)
		if (rst)
			state <= sync[1];
		else begin
			if (state & cnt == all_zero)
				state <= 1'b0;
			else if (~state & cnt == all_one)
				state <= 1'b1;
			else
				state <= state;
		end

	assign val = state;

	// Rise / Fall detection
	always @(posedge clk)
	begin
		if (~cond) begin
			rise <= 1'b0;
			fall <= 1'b0;
		end else begin
			rise <= ~state & (cnt == all_one);
			fall <=  state & (cnt == all_zero);
		end
	end

endmodule // glitch_filter
module fifo_sync_shift #(
	parameter integer DEPTH =  4,
	parameter integer WIDTH = 16
)(
	input  wire [WIDTH-1:0] wr_data,
	input  wire wr_ena,
	output wire wr_full,

	output wire [WIDTH-1:0] rd_data,
	input  wire rd_ena,
	output wire rd_empty,

	input  wire clk,
	input  wire rst
);

	// Signals
	// -------

	wire  [DEPTH+1:0] ce;
	wire  [DEPTH+1:0] valid;
	wire  [WIDTH-1:0] data [DEPTH+1:0];


	// Stages
	// ------

	// Generate loop
	genvar i;

	generate
		for (i=1; i<=DEPTH; i=i+1)
		begin : stage
			// Local signals
			reg [WIDTH-1:0] l_data;
			reg l_valid;

			// Data register
			always @(posedge clk)
				if (ce[i])
					l_data <= valid[i+1] ? data[i+1] : wr_data;

			// Valid flag
			always @(posedge clk or posedge rst)
				if (rst)
					l_valid <= 1'b0;
				else if (ce[i])
					l_valid <= ~rd_ena | valid[i+1] | (wr_ena & valid[i]);

			// CE for this stage
			assign ce[i] = rd_ena | (wr_ena & ~valid[i] & valid[i-1]);

			// Map
			assign data[i]  = l_data;
			assign valid[i] = l_valid;
		end
	endgenerate

	// Boundary conditions
	assign data[DEPTH+1] = wr_data;
	assign data[0] = { WIDTH{1'bx} };

	assign valid[DEPTH+1] = 1'b0;
	assign valid[0] = 1'b1;

	assign ce[DEPTH+1] = 1'bx;
	assign ce[0] = 1'bx;


	// User IF
	// -------

	assign wr_full = valid[DEPTH];

	assign rd_empty = ~valid[1];
	assign rd_data  = data[1];

endmodule // fifo_sync_shift
module fifo_sync_ram #(
	parameter integer DEPTH = 256,
	parameter integer WIDTH = 16
)(
	input  wire [WIDTH-1:0] wr_data,
	input  wire wr_ena,
	output wire wr_full,
	output reg  wr_afull,

	output wire [WIDTH-1:0] rd_data,
	input  wire rd_ena,
	output wire rd_empty,
	output reg  rd_aempty,

	input  wire clk,
	input  wire rst
);

	localparam AWIDTH = $clog2(DEPTH);


	// Signals
	// -------

	// RAM
	reg  [AWIDTH-1:0] ram_wr_addr;
	wire [ WIDTH-1:0] ram_wr_data;
	wire ram_wr_ena;

	reg  [AWIDTH-1:0] ram_rd_addr;
	wire [ WIDTH-1:0] ram_rd_data;
	wire ram_rd_ena;

	// Fill-level
	reg  [AWIDTH:0] level;
	(* keep="true" *) wire lvl_dec;
	(* keep="true" *) wire lvl_mov;
	wire lvl_empty;

	// Full
	wire full_nxt;
	reg  full;

	// Read logic
	reg  rd_valid;


	// Fill level counter
	// ------------------
	// (counts the number of used words - 1)

	always @(posedge clk or posedge rst)
		if (rst)
			level <= {(AWIDTH+1){1'b1}};
		else
			level <= level + { {AWIDTH{lvl_dec}}, lvl_mov };

	assign lvl_dec = ram_rd_ena & ~ram_wr_ena;
	assign lvl_mov = ram_rd_ena ^  ram_wr_ena;
	assign lvl_empty = level[AWIDTH];

	always @(posedge clk or posedge rst)
		if (rst) begin
			wr_afull  <= 1'b0;
			rd_aempty <= 1'b1;
		end else begin
			wr_afull  <=  level[AWIDTH:AWIDTH-2] == 3'b011;
			rd_aempty <= (level[AWIDTH:AWIDTH-2] == 3'b000) | level[AWIDTH];
		end


	// Full flag generation
	// --------------------

	assign full_nxt = level == { 1'b0, {(AWIDTH-2){1'b1}}, 2'b01 };

	always @(posedge clk or posedge rst)
		if (rst)
			full <= 1'b0;
		else
			full <= (full | (wr_ena & ~rd_ena & full_nxt)) & ~(rd_ena & ~wr_ena);

	assign wr_full = full;


	// Write
	// -----

	always @(posedge clk or posedge rst)
		if (rst)
			ram_wr_addr <= 0;
		else if (ram_wr_ena)
			ram_wr_addr <= ram_wr_addr + 1;

	assign ram_wr_data = wr_data;
	assign ram_wr_ena  = wr_ena;


	// Read
	// ----

	always @(posedge clk or posedge rst)
		if (rst)
			ram_rd_addr <= 0;
		else if (ram_rd_ena)
			ram_rd_addr <= ram_rd_addr + 1;

	assign ram_rd_ena = (rd_ena | ~rd_valid) & ~lvl_empty;

	always @(posedge clk or posedge rst)
		if (rst)
			rd_valid <= 1'b0;
		else if (rd_ena | ~rd_valid)
			rd_valid <= ~lvl_empty;

	assign rd_data = ram_rd_data;
	assign rd_empty = ~rd_valid;


	// RAM
	// ---

	ram_sdp #(
		.AWIDTH(AWIDTH),
		.DWIDTH(WIDTH)
	) ram_I (
		.wr_addr(ram_wr_addr),
		.wr_data(ram_wr_data),
		.wr_ena(ram_wr_ena),
		.rd_addr(ram_rd_addr),
		.rd_data(ram_rd_data),
		.rd_ena(ram_rd_ena),
		.clk(clk)
	);

endmodule // fifo_sync_ram
module dual_clock_fifo #(
	parameter ADDR_WIDTH = 3,
	parameter DATA_WIDTH = 32
)
(
	input wire 			wr_rst_i,
	input wire 			wr_clk_i,
	input wire 			wr_en_i,
	input wire [DATA_WIDTH-1:0]	wr_data_i,

	input wire 			rd_rst_i,
	input wire 			rd_clk_i,
	input wire 			rd_en_i,
	output reg [DATA_WIDTH-1:0]	rd_data_o,

	output reg 			full_o,
	output reg 			empty_o
);

reg [ADDR_WIDTH-1:0]	wr_addr;
reg [ADDR_WIDTH-1:0]	wr_addr_gray;
reg [ADDR_WIDTH-1:0]	wr_addr_gray_rd;
reg [ADDR_WIDTH-1:0]	wr_addr_gray_rd_r;
reg [ADDR_WIDTH-1:0]	rd_addr;
reg [ADDR_WIDTH-1:0]	rd_addr_gray;
reg [ADDR_WIDTH-1:0]	rd_addr_gray_wr;
reg [ADDR_WIDTH-1:0]	rd_addr_gray_wr_r;

function [ADDR_WIDTH-1:0] gray_conv;
input [ADDR_WIDTH-1:0] in;
begin
	gray_conv = {in[ADDR_WIDTH-1],
		     in[ADDR_WIDTH-2:0] ^ in[ADDR_WIDTH-1:1]};
end
endfunction

always @(posedge wr_clk_i) begin
	if (wr_rst_i) begin
		wr_addr <= 0;
		wr_addr_gray <= 0;
	end else if (wr_en_i) begin
		wr_addr <= wr_addr + 1'b1;
		wr_addr_gray <= gray_conv(wr_addr + 1'b1);
	end
end

// synchronize read address to write clock domain
always @(posedge wr_clk_i) begin
	rd_addr_gray_wr <= rd_addr_gray;
	rd_addr_gray_wr_r <= rd_addr_gray_wr;
end

always @(posedge wr_clk_i)
	if (wr_rst_i)
		full_o <= 0;
	else if (wr_en_i)
		full_o <= gray_conv(wr_addr + 2) == rd_addr_gray_wr_r;
	else
		full_o <= full_o & (gray_conv(wr_addr + 1'b1) == rd_addr_gray_wr_r);

always @(posedge rd_clk_i) begin
	if (rd_rst_i) begin
		rd_addr <= 0;
		rd_addr_gray <= 0;
	end else if (rd_en_i) begin
		rd_addr <= rd_addr + 1'b1;
		rd_addr_gray <= gray_conv(rd_addr + 1'b1);
	end
end

// synchronize write address to read clock domain
always @(posedge rd_clk_i) begin
	wr_addr_gray_rd <= wr_addr_gray;
	wr_addr_gray_rd_r <= wr_addr_gray_rd;
end

always @(posedge rd_clk_i)
	if (rd_rst_i)
		empty_o <= 1'b1;
	else if (rd_en_i)
		empty_o <= gray_conv(rd_addr + 1) == wr_addr_gray_rd_r;
	else
		empty_o <= empty_o & (gray_conv(rd_addr) == wr_addr_gray_rd_r);

// generate dual clocked memory
reg [DATA_WIDTH-1:0] mem[(1<<ADDR_WIDTH)-1:0];

always @(posedge rd_clk_i)
	if (rd_en_i)
		rd_data_o <= mem[rd_addr];

always @(posedge wr_clk_i)
	if (wr_en_i)
		mem[wr_addr] <= wr_data_i;
endmodule
module fifo
  #(
    parameter DEPTH_WIDTH = 0,
    parameter DATA_WIDTH = 0
    )
   (
    input 		    clk,
    input 		    rst,

    input [DATA_WIDTH-1:0]  wr_data_i,
    input 		    wr_en_i,

    output [DATA_WIDTH-1:0] rd_data_o,
    input 		    rd_en_i,

    output 		    full_o,
    output 		    empty_o
    );

   localparam DW = (DATA_WIDTH  < 1) ? 1 : DATA_WIDTH;
   localparam AW = (DEPTH_WIDTH < 1) ? 1 : DEPTH_WIDTH;

   //synthesis translate_off
   initial begin
      if(DEPTH_WIDTH < 1) $display("%m : Warning: DEPTH_WIDTH must be > 0. Setting minimum value (1)");
      if(DATA_WIDTH < 1) $display("%m : Warning: DATA_WIDTH must be > 0. Setting minimum value (1)");
   end
   //synthesis translate_on

   reg [AW:0] write_pointer;
   reg [AW:0] read_pointer;

   wire 	       empty_int = (write_pointer[AW] ==
				    read_pointer[AW]);
   wire 	       full_or_empty = (write_pointer[AW-1:0] ==
					read_pointer[AW-1:0]);
   
   assign full_o  = full_or_empty & !empty_int;
   assign empty_o = full_or_empty & empty_int;
   
   always @(posedge clk) begin
      if (wr_en_i)
	write_pointer <= write_pointer + 1'd1;

      if (rd_en_i)
	read_pointer <= read_pointer + 1'd1;

      if (rst) begin
	 read_pointer  <= 0;
	 write_pointer <= 0;
      end
   end
   simple_dpram_sclk
     #(
       .ADDR_WIDTH(AW),
       .DATA_WIDTH(DW),
       .ENABLE_BYPASS(1)
       )
   fifo_ram
     (
      .clk			(clk),
      .dout			(rd_data_o),
      .raddr			(read_pointer[AW-1:0]),
      .re			(rd_en_i),
      .waddr			(write_pointer[AW-1:0]),
      .we			(wr_en_i),
      .din			(wr_data_i)
      );

endmodule
module stream_dual_clock_fifo
  #(parameter DW = 0,
    parameter AW = 0)
   (input 	    wr_clk,
    input 	    wr_rst,
    input [DW-1:0]  stream_s_data_i, 
    input 	    stream_s_valid_i,
    output 	    stream_s_ready_o,

    input 	    rd_clk,
    input 	    rd_rst,
    output [DW-1:0] stream_m_data_o,
    output 	    stream_m_valid_o,
    input 	    stream_m_ready_i);
   
   

   wire 	    fifo_rd_en;
   wire [DW-1:0]    fifo_dout;
   wire 	    fifo_empty;
   wire 	    full;
   
   assign stream_s_ready_o = !(full | wr_rst);
   
	
   // orig_fifo is just a normal (non-FWFT) synchronous or asynchronous FIFO
   dual_clock_fifo
     #(.ADDR_WIDTH (AW),
       .DATA_WIDTH (DW))
   dual_clock_fifo
     (.wr_rst_i  (wr_rst),       
      .wr_clk_i  (wr_clk),
      .wr_en_i   (stream_s_valid_i & stream_s_ready_o),
      .wr_data_i (stream_s_data_i),
      .full_o    (full),

      .rd_rst_i  (rd_rst),       
      .rd_clk_i  (rd_clk),
      .rd_en_i   (fifo_rd_en),
      .rd_data_o (fifo_dout),
      .empty_o   (fifo_empty));

   stream_fifo_if
     #(.DW (DW))
   stream_if
   (.clk              (rd_clk),
    .rst              (rd_rst),
    .fifo_data_i      (fifo_dout),
    .fifo_rd_en_o     (fifo_rd_en),
    .fifo_empty_i     (fifo_empty),
    .stream_m_data_o  (stream_m_data_o),
    .stream_m_valid_o (stream_m_valid_o),
    .stream_m_ready_i (stream_m_ready_i));
   
endmodule
module stream_fifo_if
  #(parameter DW = 0)
   (input 		clk,
    input 		rst,
    //FIFO Interface    
    input [DW-1:0] 	fifo_data_i,
    output 		fifo_rd_en_o,
    input 		fifo_empty_i,
    //Stream Interface
    output reg [DW-1:0] stream_m_data_o,
    output reg 		stream_m_valid_o,
    input 		stream_m_ready_i);
    
   reg 		    fifo_valid, middle_valid;
   reg [DW-1:0]     middle_dout;
   
   wire will_update_dout = (middle_valid || fifo_valid) && (stream_m_ready_i || !stream_m_valid_o);
   wire will_update_middle = fifo_valid && (middle_valid == will_update_dout);

   assign fifo_rd_en_o = (!fifo_empty_i) && !(middle_valid && stream_m_valid_o && fifo_valid);
   always @(posedge clk)
      if (rst)
         begin
            fifo_valid <= 0;
            middle_valid <= 0;
            stream_m_valid_o <= 0;
            stream_m_data_o <= 0;
            middle_dout <= 0;
         end
      else
         begin
            if (will_update_middle)
               middle_dout <= fifo_data_i;
            
            if (will_update_dout)
               stream_m_data_o <= middle_valid ? middle_dout : fifo_data_i;
            
            if (fifo_rd_en_o)
               fifo_valid <= 1;
            else if (will_update_middle || will_update_dout)
               fifo_valid <= 0;
            
            if (will_update_middle)
               middle_valid <= 1;
            else if (will_update_dout)
               middle_valid <= 0;
            
            if (will_update_dout)
               stream_m_valid_o <= 1;
            else if (stream_m_ready_i)
               stream_m_valid_o <= 0;
         end 
endmodule
module b1_demux_1_4_case
(
    input      din, 
    input      [1:0] sel,
    output reg dout0, 
    output reg dout1,
    output reg dout2,
    output reg dout3
);
    always @(*)
        case (sel)
            2'b00: 
            begin
                dout0 = din;
                dout1 = 0;
                dout2 = 0;
                dout3 = 0;
            end
            2'b01: 
            begin
                dout0 = 0;
                dout1 = din;
                dout2 = 0;
                dout3 = 0;
            end
            2'b10: 
            begin
                dout0 = 0;
                dout1 = 0;
                dout2 = din;
                dout3 = 0;
            end
            2'b11: 
            begin
                dout0 = 0;
                dout1 = 0;
                dout2 = 0;
                dout3 = din;
            end
        endcase
    
endmodule
module b1_demux_1_4_shift
(
    input      din, 
    input      [1:0] sel,
    output reg dout0, 
    output reg dout1,
    output reg dout2,
    output reg dout3
);

    always @(*)
        {dout3, dout2, dout1, dout0}= din<<sel;
        
endmodule
module bn_demux_1_4_case
#(parameter DATA_WIDTH=2)
(
    input      [DATA_WIDTH-1:0] din, 
    input      [1:0] sel,
    output reg [DATA_WIDTH-1:0] dout0, 
    output reg [DATA_WIDTH-1:0] dout1,
    output reg [DATA_WIDTH-1:0] dout2,
    output reg [DATA_WIDTH-1:0] dout3
);

    always @(*)
        case (sel)
            2'b00: 
            begin
                dout0 = din;
                dout1 = 0;
                dout2 = 0;
                dout3 = 0;
            end
            2'b01: 
            begin
                dout0 = 0;
                dout1 = din;
                dout2 = 0;
                dout3 = 0;
            end
            2'b10: 
            begin
                dout0 = 0;
                dout1 = 0;
                dout2 = din;
                dout3 = 0;
            end
            2'b11: 
            begin
                dout0 = 0;
                dout1 = 0;
                dout2 = 0;
                dout3 = din;
            end
        endcase
        
endmodule
module b2_demux_1_4_block
(
    input   [1:0] din, 
    input   [1:0] sel,
    output  [1:0] dout0, 
    output  [1:0] dout1,
    output  [1:0] dout2,
    output  [1:0] dout3
);
    
    b1_demux_1_4_case dmux0  (.din(din[0]),      .sel(sel),          .dout0(dout0[0]), 
                              .dout1(dout1[0]),  .dout2(dout2[0]),   .dout3(dout3[0]));
    b1_demux_1_4_shift dmux1 (.din(din[1]),      .sel(sel),          .dout0(dout0[1]), 
                              .dout1(dout1[1]),  .dout2(dout2[1]),   .dout3(dout3[1]));
        
endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

`ifdef CASE 
    bn_demux_1_4_case #(2) bn_demux_1_4_case (.din(SW[1:0]),     .sel(KEY[1:0]),    .dout0(LEDR[1:0]), 
                                              .dout1(LEDR[3:2]), .dout2(LEDR[5:4]), .dout3(LEDR[7:6]));
`else
    b2_demux_1_4_block b2_demux_1_4_block    (.din(SW[1:0]),     .sel(KEY[1:0]),    .dout0(LEDR[1:0]), 
                                              .dout1(LEDR[3:2]), .dout2(LEDR[5:4]), .dout3(LEDR[7:6]));
`endif
    
endmodule
module bn_mux_n_1_generate 
#( parameter  DATA_WIDTH = 8,
   parameter  SEL_WIDTH   = 2) 
(
    input   [((2**SEL_WIDTH)*DATA_WIDTH)-1:0] data,
    input   [SEL_WIDTH-1:0]                   sel,   
    output  [DATA_WIDTH-1:0]                  y
);

wire    [DATA_WIDTH-1:0] tmp_array [0:(2**SEL_WIDTH)-1];

genvar i;
generate
    for(i=0; i<2**SEL_WIDTH; i=i+1) 
    begin: gen_array
        assign  tmp_array[i] = data[((i+1)*DATA_WIDTH)-1:(i*DATA_WIDTH)];
    end
endgenerate

    assign  y =  tmp_array[sel];

endmodule
module bn_selector_n_1_generate 
#( parameter  DATA_WIDTH = 8,
   parameter  INPUT_CHANNELS   = 2) 
(
    input   [(INPUT_CHANNELS*DATA_WIDTH)-1:0] data,
    input   [INPUT_CHANNELS-1:0]              sel,   
    output  [DATA_WIDTH-1:0]                  y
);

genvar i;
generate
    for(i=0;i<INPUT_CHANNELS;i=i+1) 
    begin: gen_array
        assign y = sel[i] ? data[((i+1)*DATA_WIDTH)-1:(i*DATA_WIDTH)] : {DATA_WIDTH{1'bx}};
    end
endgenerate

endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

    bn_mux_n_1_generate #(2,2) bn_mux_n_1_generate (.data({SW[7:6],SW[5:4],SW[3:2],SW[1:0]}), .sel(KEY[1:0]), .y(LEDR[1:0]));
    bn_selector_n_1_generate #(4,2) bn_selector_n_1_generate (.data({SW[7:4],SW[3:0]}), .sel(SW[9:8]), .y(LEDR[9:6]));

endmodule
module b2_mux_2_1_sel
(
    input  [1:0] d0,
    input  [1:0] d1,
    input        sel,
    output [1:0] y
);

    assign y = sel ? d1 : d0;

endmodule
module b2_mux_4_1_sel
(
    input  [1:0] d0, d1, d2, d3,
    input  [1:0] sel,
    output [1:0] y
);

    assign y = sel [1] ? (sel [0] ? d3 : d2)
            : (sel [0] ? d1 : d0);

endmodule
module b2_mux_4_1_case
(
    input      [1:0] d0, d1, d2, d3,
    input      [1:0] sel,
    output reg [1:0] y
);

    always @(*)
        case (sel)
        2'b00: y = d0;
        2'b01: y = d1;
        2'b10: y = d2;
        2'b11: y = d3;
        endcase

endmodule
module b2_mux_4_1_block
(
    input  [1:0] d0, d1, d2, d3,
    input  [1:0] sel,
    output [1:0] y
);

    wire [1:0] w01, w23;

    b2_mux_2_1_sel mux0(.d0(d0), .d1(d1), .sel(sel[0]), .y(w01));
    b2_mux_2_1_sel mux1(.d0(d2),.d1(d3), .sel(sel[0]), .y(w23));
    b2_mux_2_1_sel mux2(.d0(w01), .d1(w23), .sel(sel[1]), .y(y));

endmodule
module b1_mux_4_1_case
(
    input      d0, d1, d2, d3,
    input      [1:0] sel,
    output reg y
);

    always @(*)
        case (sel)
        2'b00: y = d0;
        2'b01: y = d1;
        2'b10: y = d2;
        2'b11: y = d3;
        endcase

endmodule
module b2_mux_4_1_block_alt
(
    input  [1:0] d0, d1, d2, d3,
    input  [1:0] sel,
    output [1:0] y
);

    b1_mux_4_1_case hi(.d0(d0[1]), .d1(d1[1]), .d2(d2[1]), .d3(d3[1]), .sel(sel), .y(y[1]));
    b1_mux_4_1_case lo(.d0(d0[0]), .d1(d1[0]), .d2(d2[0]), .d3(d3[0]), .sel(sel), .y(y[0]));

endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

    b2_mux_4_1_case b2_mux_4_1_case(.d0(SW[1:0]),.d1(SW[3:2]),.d2(SW[5:4]),.d3(SW[7:6]),.sel(KEY[1:0]),.y(LEDR[1:0]));
    b2_mux_4_1_sel b2_mux_4_1_sel(.d0(SW[1:0]),.d1(SW[3:2]),.d2(SW[5:4]),.d3(SW[7:6]),.sel(KEY[1:0]),.y(LEDR[3:2]));
    b2_mux_4_1_block b2_mux_4_1_block(.d0(SW[1:0]),.d1(SW[3:2]),.d2(SW[5:4]),.d3(SW[7:6]),.sel(KEY[1:0]),.y(LEDR[5:4]));
    b2_mux_4_1_block_alt b2_mux_4_1_block_alt(.d0(SW[1:0]),.d1(SW[3:2]),.d2(SW[5:4]),.d3(SW[7:6]),.sel(KEY[1:0]),.y(LEDR[7:6]));
    
endmodule
module bn_select_8_1_case
#(parameter DATA_WIDTH=8)
(
    input       [DATA_WIDTH-1:0] d0, 
    input       [DATA_WIDTH-1:0] d1,
    input       [DATA_WIDTH-1:0] d2,
    input       [DATA_WIDTH-1:0] d3,
    input       [DATA_WIDTH-1:0] d4, 
    input       [DATA_WIDTH-1:0] d5,
    input       [DATA_WIDTH-1:0] d6,
    input       [DATA_WIDTH-1:0] d7,
    input       [7:0] sel,
    output  reg [DATA_WIDTH-1:0] y
);
    
    always @(*)
        case (sel)
            8'b00000001: y=d0;
            8'b00000010: y=d1;
            8'b00000100: y=d2;
            8'b00001000: y=d3;
            8'b00010000: y=d4;
            8'b00100000: y=d5;
            8'b01000000: y=d6;
            8'b10000000: y=d7;
            default:     y={DATA_WIDTH{1'bx}};
        endcase
    
endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

    bn_select_8_1_case #(3) bn_select_8_1_case (.d0(SW[2:0]), .d1(SW[3:1]), .d2(SW[4:2]), 
                                                .d3(SW[5:3]), .d4(SW[6:4]), .d5(SW[7:5]), 
                                                .d6(SW[8:6]), .d7(SW[9:7]), .sel(SW[7:0]), .y(LEDR[2:0]));
    // if SW[7:0] == 8'b0_0000001..8'b0_1000000 LEDR[2:0] always will be 3'b001, SW[9:8] does not affect
    // if SW[7:0] == 8'b1_0000000 LEDR[0] = 1'b1, LEDR[2:1] = SW[9:8]. 
endmodule
module b2_mux_2_1_comb_incorrect
(
    input  [1:0] d0,
    input  [1:0] d1,
    input        sel,
    output [1:0] y
);

    assign y = (sel & d1) | ((~sel) & d0);

endmodule
module b2_mux_2_1_comb_correct1
(
    input  [1:0] d0,
    input  [1:0] d1,
    input        sel,
    output [1:0] y
);

    assign y[0] = (sel & d1[0]) | ((~sel) & d0[0]);
    assign y[1] = (sel & d1[1]) | ((~sel) & d0[1]);
    
endmodule
module b2_mux_2_1_comb_correct2
(
    input  [1:0] d0,
    input  [1:0] d1,
    input        sel,
    output [1:0] y
);

    wire [1:0] select;
    assign select = {2{sel}};
    assign y = (select & d1) | (~select & d0);
    
endmodule
module b2_mux_2_1_if
(
    input  [1:0] d0,
    input  [1:0] d1,
    input        sel,
    output reg [1:0] y
);
    always@(*)
    begin
        if(sel)
            y = d1;
        else 
            y = d0;
    end

endmodule
module b2_mux_2_1_case
(
    input  [1:0] d0,
    input  [1:0] d1,
    input        sel,
    output reg [1:0] y
);
    always@(*)
    begin
        case (sel)
            0: y = d0;
            1: y = d1;
        endcase
    end

endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

    b2_mux_2_1_sel b2_mux_2_1_sel(.d0(SW[1:0]),.d1(SW[3:2]),.sel(KEY[0]),.y(LEDR[1:0]));
    b2_mux_2_1_if b2_mux_2_1_if(.d0(SW[1:0]),.d1(SW[3:2]),.sel(KEY[0]),.y(LEDR[3:2]));
    b2_mux_2_1_comb_correct1 b2_mux_2_1_comb_correct1(.d0(SW[1:0]),.d1(SW[3:2]),.sel(KEY[0]),.y(LEDR[5:4]));
    b2_mux_2_1_comb_correct2 b2_mux_2_1_comb_correct2(.d0(SW[1:0]),.d1(SW[3:2]),.sel(KEY[0]),.y(LEDR[7:6]));
    b2_mux_2_1_comb_incorrect b2_mux_2_1_comb_incorrect(.d0(SW[1:0]),.d1(SW[3:2]),.sel(KEY[0]),.y(LEDR[9:8]));
    
endmodule
module bn_selector_4_1_and_or 
#( parameter  DATA_WIDTH = 32) 
(
    input   [(DATA_WIDTH*4)-1:0] data,
    input   [3:0]                sel,   
    output  [DATA_WIDTH-1:0]     y
);

    wire [(DATA_WIDTH*4)-1:0] mask;
    wire [(DATA_WIDTH*4)-1:0] masked_data;
    
    assign mask        = {{DATA_WIDTH{sel[3]}}, 
                          {DATA_WIDTH{sel[2]}}, 
                          {DATA_WIDTH{sel[1]}}, 
                          {DATA_WIDTH{sel[0]}}};
    assign masked_data = data & mask;
    assign y           = masked_data[DATA_WIDTH*4-1:DATA_WIDTH*3]|
                                masked_data[DATA_WIDTH*3-1:DATA_WIDTH*2]|
                                masked_data[DATA_WIDTH*2-1:DATA_WIDTH]|
                                masked_data[DATA_WIDTH-1:0];

endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

    bn_selector_4_1_and_or #(2) bn_selector_4_1_and_or 
                                (.data(SW[7:0]), .sel({SW[9:8], KEY[1:0]}), .y(LEDR[9:8]));
    assign LEDR[3:0] = {SW[9:8], KEY[1:0]};

endmodule
module b1_mux_2_1_comb
(
    input  d0,
    input  d1,
    input  sel,
    output y
);

    assign y = (sel & d1) | ((~sel) & d0);

endmodule
module b1_mux_2_1_sel
(
    input  d0,
    input  d1,
    input  sel,
    output y
);

    assign y = sel ? d1 : d0;

endmodule
module b1_mux_2_1_if
(
    input  d0,
    input  d1,
    input  sel,
    output reg y
);
    always@(*)
    begin
        if(sel)
            y = d1;
        else 
            y = d0;
    end

endmodule
module b1_mux_2_1_case
(
    input  d0,
    input  d1,
    input  sel,
    output reg y
);
    always@(*)
    begin
        case (sel)
            0: y = d0;
            1: y = d1;
        endcase
    end

endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

    b1_mux_2_1_comb b1_mux_2_1_comb  (SW[0], SW[1], KEY[0], LEDR[0]);
    b1_mux_2_1_sel b1_mux_2_1_sel    (SW[0], SW[1], KEY[0], LEDR[1]);
    b1_mux_2_1_if b1_mux_2_1_if      (SW[0], SW[1], KEY[0], LEDR[2]);
    b1_mux_2_1_case b1_mux_2_1_case  (SW[0], SW[1], KEY[0], LEDR[3]);

endmodule
module b2_mux_3_1_case_latch
(
    input      [1:0] d0, d1, d2, 
    input      [1:0] sel,
    output reg [1:0] y
);

    always @(*)
        case (sel)
        2'b00: y = d0;
        2'b01: y = d1;
        2'b10: y = d2;
        endcase

endmodule
module b2_mux_3_1_case_correct
(
    input      [1:0] d0, d1, d2, 
    input      [1:0] sel,
    output reg [1:0] y
);

    always @(*)
        case (sel)
        2'b00: y = d0;
        2'b01: y = d1;
        default: y = d2;
        endcase

endmodule
module b2_mux_3_1_casex_correct
(
    input      [1:0] d0, d1, d2, 
    input      [1:0] sel,
    output reg [1:0] y
);

    always @(*)
        case (sel)
        2'b00: y = d0;
        2'b01: y = d1;
        2'b10: y = d2;
        default: y=2'bxx;
        endcase

endmodule
module lab4
(
    input   [ 1:0]  KEY,
    input   [ 9:0]  SW,
    output  [ 9:0]  LEDR
);

    b2_mux_3_1_case_latch b2_mux_3_1_case_latch(.d0(SW[1:0]),.d1(SW[3:2]),.d2(SW[5:4]),.sel(KEY[1:0]),.y(LEDR[1:0]));
    b2_mux_3_1_case_correct b2_mux_3_1_case_correct(.d0(SW[1:0]),.d1(SW[3:2]),.d2(SW[5:4]),.sel(KEY[1:0]),.y(LEDR[3:2]));
    b2_mux_3_1_casex_correct b2_mux_3_1_casex_correct(.d0(SW[1:0]),.d1(SW[3:2]),.d2(SW[5:4]),.sel(KEY[1:0]),.y(LEDR[5:4]));
    
endmodule
module tb();

    reg CLOCK_50 = 0;               // DE-series 50 MHz clock
    reg [9:0] SW = 0;               // DE-series SW switches
    reg [3:0] KEY = 0;              // DE-series pushbutton keys
    wire [(8*6) -1:0] HEX;          // HEX displays (six ports)
    wire [9:0] LEDR;                // DE-series LEDs

    reg key_action = 0;
    reg [7:0] scan_code = 0;
    wire [2:0] ps2_lock_control;

    wire [7:0] VGA_X;               // "VGA" column
    wire [6:0] VGA_Y;               // "VGA" row
    wire [2:0] VGA_COLOR;           // "VGA pixel" colour (0-7)
    wire plot;                      // "Pixel" is drawn when this is pulsed
    wire [31:0] GPIO;               // DE-series GPIO port

    initial $sim_fpga(CLOCK_50, SW, KEY, LEDR, HEX, key_action, scan_code, 
                      ps2_lock_control, VGA_X, VGA_Y, VGA_COLOR, plot, GPIO);

   
    // create the 50 MHz clock signal
    always #10
        CLOCK_50 <= ~CLOCK_50;

    
    top DUT (.SW(SW), .KEY(KEY), .LEDR(LEDR));

endmodule
module top (SW, KEY, LEDR);

    input wire [9:0] SW;        // DE-series switches
    input wire [3:0] KEY;       // DE-series pushbuttons

    output wire [9:0] LEDR;     // DE-series LEDs   

    lab4 lab4 (KEY[1:0], SW, LEDR);
 
endmodule
module testbench;
parameter DATA_CASE_WIDTH = 8;
parameter DATA_BLOCK_WIDTH  = 2;
    // input and output test signals
    wire  [DATA_CASE_WIDTH-1:0] dout0_case;
	wire  [DATA_CASE_WIDTH-1:0] dout1_case;
    wire  [DATA_CASE_WIDTH-1:0] dout2_case;
	wire  [DATA_CASE_WIDTH-1:0] dout3_case;
	wire  [DATA_BLOCK_WIDTH-1:0] dout0_block;
	wire  [DATA_BLOCK_WIDTH-1:0] dout1_block;
    wire  [DATA_BLOCK_WIDTH-1:0] dout2_block;
	wire  [DATA_BLOCK_WIDTH-1:0] dout3_block;
	reg   [1:0] sel;
	reg   [DATA_CASE_WIDTH-1:0] din_case;
	reg   [DATA_BLOCK_WIDTH-1:0] din_block;
	
 
   // creating the instance of the module we want to test
	bn_demux_1_4_case #(DATA_CASE_WIDTH) bn_demux_1_4_case (.din(din_case), .sel(sel), .dout0(dout0_case), .dout1(dout1_case), .dout2(dout2_case), .dout3(dout3_case));
	b2_demux_1_4_block b2_demux_1_4_block (.din(din_block), .sel(sel), .dout0(dout0_block), .dout1(dout1_block), .dout2(dout2_block), .dout3(dout3_block));
	
	initial 
        begin
			din_case=8'b11111111;
			din_block=din_case;
			#5;
            sel = 2'b00;     // sel change to 00; a -> y
			#10;
			sel = 2'b01;     // sel change to 01; b -> y
			#10
			sel = 2'b10;     // sel change to 10; c -> y
			#10;
			sel = 2'b11;     // sel change to 11; ? -> y
			#10;
			din_case=8'b10101010;
			din_block=din_case;
			#10;
			din_case=8'b01010101;
			din_block=din_case;
			#10;
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        $monitor("sel=%b din_case=%b din_block=%b dout0_case=%b dout1_case=%b dout2_case=%b dout3_case=%b dout0_block=%b dout1_block=%b dout2_block=%b dout3_block=%b", 
		         sel, din_case, din_block, dout0_case, dout1_case, dout2_case, dout3_case, dout0_block, dout1_block, dout2_block, dout3_block);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module testbench;
	parameter DATA_WIDTH = 8;
	parameter SEL_WIDTH = 3;	//2;
	parameter INPUT_CHANNELS = 8;
    // input and output test signals
    wire  [DATA_WIDTH-1:0] y;
	wire  [DATA_WIDTH-1:0] y2;
	reg   [SEL_WIDTH-1:0] sel;
	reg   [INPUT_CHANNELS-1:0] sel2;
	reg   [DATA_WIDTH-1:0] d0; 
	reg	  [DATA_WIDTH-1:0] d1;
	reg   [DATA_WIDTH-1:0] d2;
	reg   [DATA_WIDTH-1:0] d3;
	reg   [DATA_WIDTH-1:0] d4; 
	reg   [DATA_WIDTH-1:0] d5;
	reg   [DATA_WIDTH-1:0] d6;
	reg   [DATA_WIDTH-1:0] d7;
 
   // creating the instance of the module we want to test
	bn_mux_n_1_generate #(DATA_WIDTH,SEL_WIDTH) bn_mux_n_1_generate (.data({d7,d6,d5,d4,d3,d2,d1,d0}), .sel(sel), .y(y));
	//bn_mux_n_1_generate #(DATA_WIDTH,SEL_WIDTH) bn_mux_n_1_generate (.data({d3,d2,d1,d0}), .sel(sel), .y(y));
	
	bn_selector_n_1_generate #(DATA_WIDTH,INPUT_CHANNELS) bn_selector_n_1_generate (.data({d7,d6,d5,d4,d3,d2,d1,d0}), .sel(sel2), .y(y2));
	
	initial 
        begin
			d0=0; d1=1; d2=2; d3=3; d4=4; d5=5; d6=6; d7=7;
			#5;
            sel = 0;     
			sel2 = 8'b00000001;
			#10;
			repeat (2**SEL_WIDTH-1)	
			begin
				sel=sel+1;
				sel2=sel2<<1;
				#10;
			end
			d7=123;
			#10;
			d7=77;
			#10;
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        $monitor("sel=%b sel2=%b d0=%d d1=%d d2=%d d3=%d d4=%d d5=%d d6=%d d7=%d y=%d y2=%d", 
		         sel, sel2, d0, d1, d2, d3, d4, d5, d6, d7, y, y2);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module testbench;
    // input and output test signals
    reg  [1:0] a;
	reg  [1:0] b;
    reg  [1:0] c;
	reg  [1:0] d;
	reg  [1:0] sel;
	wire [1:0] y_sel;
	wire [1:0] y_block;
	wire [1:0] y_block_alt;
	wire [1:0] y_case;
 
   // creating the instance of the module we want to test
	b2_mux_4_1_case b2_mux_4_1_case(a,b,c,d,sel,y_case);
	b2_mux_4_1_sel b2_mux_4_1_sel(a,b,c,d,sel,y_sel);
	b2_mux_4_1_block b2_mux_4_1_block(a,b,c,d,sel,y_block);
	b2_mux_4_1_block_alt b2_mux_4_1_block_alt(a,b,c,d,sel,y_block_alt);
	
	initial 
        begin
			a = 2'b00;
			b = 2'b01;
			c = 2'b10;
			d = 2'b11;
			#5;
            sel = 2'b00;     // sel change to 00; a -> y
			#10;
			sel = 2'b01;     // sel change to 01; b -> y
			#10
			sel = 2'b10;     // sel change to 10; c -> y
			#10;
			sel = 2'b11;     // sel change to 11; d -> y
			#10
			d = 2'b10;		// d change; y changes too. sel == 2'b11
			#5
			d = 2'b01;
            #5;            // pause
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        $monitor("a=%b b=%b c=%b d=%b sel=%b y_sel=%d y_block=%b y_block_alt=%b y_case=%b", 
		         a, b, c, d, sel, y_sel, y_block, y_block_alt, y_case);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module testbench;
	parameter DATA_WIDTH = 8;
    // input and output test signals
    wire  [DATA_WIDTH-1:0] y;
	reg   [7:0] sel;
	reg   [DATA_WIDTH-1:0] d0; 
	reg	  [DATA_WIDTH-1:0] d1;
	reg   [DATA_WIDTH-1:0] d2;
	reg   [DATA_WIDTH-1:0] d3;
	reg   [DATA_WIDTH-1:0] d4; 
	reg   [DATA_WIDTH-1:0] d5;
	reg   [DATA_WIDTH-1:0] d6;
	reg   [DATA_WIDTH-1:0] d7;
 
   // creating the instance of the module we want to test
	bn_select_8_1_case #(8) select_8_1 (.d0(d0), .d1(d1), .d2(d2), 
	                                           .d3(d3), .d4(d4), .d5(d5), 
											   .d6(d6), .d7(d7), .sel(sel), .y(y));
	
	initial 
        begin
			d0=0; d1=1; d2=2; d3=3; d4=4; d5=5; d6=6; d7=7;
			#5;
            sel = 8'b00000001;     
			#10;
			repeat (7)
			begin
				sel=sel<<1;
				#10;
			end
			d7=123;
			#10;
			d7=77;
			#10;
			sel=$urandom;
			#10;
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        $monitor("sel=%b d0=%d d1=%d d2=%d d3=%d d4=%d d5=%d d6=%d d7=%d y=%d", 
		         sel, d0, d1, d2, d3, d4, d5, d6, d7, y);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module testbench;
    // input and output test signals
    reg  [1:0] a;
	reg  [1:0] b;
	reg  sel;
    wire [1:0] y_comb_correct1;
	wire [1:0] y_comb_correct2;
	wire [1:0] y_comb_incorrect;
	wire [1:0] y_sel;
	wire [1:0] y_if;
	wire [1:0] y_case;
 
   // creating the instance of the module we want to test
	b2_mux_2_1_sel b2_mux_2_1_sel  (a, b, sel, y_sel);
	b2_mux_2_1_if b2_mux_2_1_if  (a, b, sel, y_if);
	b2_mux_2_1_case b2_mux_2_1_case  (a, b, sel, y_case);
	b2_mux_2_1_comb_correct1 b2_mux_2_1_comb_correct1  (a, b, sel, y_comb_correct1);
	b2_mux_2_1_comb_correct2 b2_mux_2_1_comb_correct2  (a, b, sel, y_comb_correct2);
	b2_mux_2_1_comb_incorrect b2_mux_2_1_comb_incorrect  (a, b, sel, y_comb_incorrect);
	
	
	initial 
        begin
			a = 2'b00;
			b = 2'b11;
			#5;
            sel = 1'b0;     // sel change to 0; a -> y
			#10;
			sel = 1'b1;     // sel change to 1; b -> y
			#10
			b = 2'b10;		// b change; y changes too. sel == 1'b1
			#5
			b = 2'b01;
            #5;            // pause
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        $monitor("a=%b b=%b sel=%b y_sel=%b y_if=%b y_case=%b y_comb_corr1=%b y_comb_corr2=%b y_comb_incorr=%b", 
		         a, b, sel, y_sel, y_if, y_case, y_comb_correct1, y_comb_correct2, y_comb_incorrect);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module testbench;
	parameter DATA_WIDTH = 32;
	//parameter SEL_WIDTH = 3;	//2;
	//parameter INPUT_CHANNELS = 8;
    // input and output test signals
    wire  [DATA_WIDTH-1:0] y;
	//wire  [DATA_WIDTH-1:0] y2;
	reg   [/*SEL_WIDTH-1*/3:0] sel;
	//reg   [INPUT_CHANNELS-1:0] sel2;
	reg   [DATA_WIDTH-1:0] d0; 
	reg	  [DATA_WIDTH-1:0] d1;
	reg   [DATA_WIDTH-1:0] d2;
	reg   [DATA_WIDTH-1:0] d3;
	//reg   [DATA_WIDTH-1:0] d4; 
	//reg   [DATA_WIDTH-1:0] d5;
	//reg   [DATA_WIDTH-1:0] d6;
	//reg   [DATA_WIDTH-1:0] d7;
 
   // creating the instance of the module we want to test
	bn_selector_4_1_and_or #(DATA_WIDTH) bn_selector_4_1_and_or (.data({d3,d2,d1,d0}), .sel(sel), .y(y));
	//bn_mux_n_1_generate #(DATA_WIDTH,SEL_WIDTH) bn_mux_n_1_generate (.data({d3,d2,d1,d0}), .sel(sel), .y(y));
	
	//bn_selector_n_1_generate #(DATA_WIDTH,INPUT_CHANNELS) bn_selector_n_1_generate (.data({d7,d6,d5,d4,d3,d2,d1,d0}), .sel(sel2), .y(y2));
	
	initial 
        begin
			d0=0; d1=1; d2=2; d3=3; //d4=4; d5=5; d6=6; d7=7;
			#5;
            sel = 4'b0001;     
			//sel2 = 8'b00000001;
			#10;
			repeat (3)	
			begin
				sel=sel<<1;
				//sel2=sel2<<1;
				#10;
			end
			d3=123;
			#10;
			d3=77;
			#10;
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        //$monitor("sel=%b sel2=%b d0=%d d1=%d d2=%d d3=%d d4=%d d5=%d d6=%d d7=%d y=%d y2=%d", 
		$monitor("sel=%b d0=%d d1=%d d2=%d d3=%d y=%d", 
		         sel, /*sel2,*/ d0, d1, d2, d3,/* d4, d5, d6, d7,*/ y/*, y2*/);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module testbench;
    // input and output test signals
    reg  a;
    reg  b;
    reg  sel;
    wire y_comb;
    wire y_sel;
    wire y_if;
    wire y_case;
 
   // creating the instance of the module we want to test
    b1_mux_2_1_comb b1_mux_2_1_comb  (a, b, sel, y_comb);
    b1_mux_2_1_sel b1_mux_2_1_sel  (a, b, sel, y_sel);
    b1_mux_2_1_if b1_mux_2_1_if  (a, b, sel, y_if);
    b1_mux_2_1_case b1_mux_2_1_case  (a, b, sel, y_case);
    
    initial 
        begin
            a = 1'b0;
            b = 1'b1;
            #5;
            sel = 1'b0;     // sel change to 0; a -> y
            #10;
            sel = 1'b1;     // sel change to 1; b -> y
            #10
            b = 1'b0;       // b change; y changes too. sel == 1'b1
            #5
            b = 1'b1;
            #5;            // pause
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        $monitor("a=%b b=%b sel=%b y_comb=%b y_sel=%b y_if=%b y_case=%b", 
                a, b, sel, y_comb, y_sel, y_if, y_case);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module testbench;
    // input and output test signals
    reg  [1:0] a;
	reg  [1:0] b;
    reg  [1:0] c;
	reg  [1:0] sel;
	wire [1:0] y_case_correct;
	wire [1:0] y_casex_correct;
	wire [1:0] y_case_latch;
 
   // creating the instance of the module we want to test
	b2_mux_3_1_case_latch b2_mux_3_1_case_latch(a,b,c,sel,y_case_latch);
	b2_mux_3_1_case_correct b2_mux_3_1_case_correct(a,b,c,sel,y_case_correct);
	b2_mux_3_1_casex_correct b2_mux_3_1_casex_correct(a,b,c,sel,y_casex_correct);
	
	initial 
        begin
			a = 2'b00;
			b = 2'b01;
			c = 2'b10;
			#5;
            sel = 2'b00;     // sel change to 00; a -> y
			#10;
			sel = 2'b01;     // sel change to 01; b -> y
			#10
			sel = 2'b10;     // sel change to 10; c -> y
			#10;
			sel = 2'b11;     // sel change to 11; ? -> y
			#10;
			sel = 2'b00;     // sel change to 00; a -> y
			#10;
			sel = 2'b11;     // sel change to 11; ? -> y
			#10;
        end
    // do at the beginning of the simulation
    //  print signal values on every change
    initial 
        $monitor("a=%b b=%b c=%b sel=%b y_case_latch=%b y_case_correct=%b y_casex_correct=%b", 
		         a, b, c, sel, y_case_latch, y_case_correct, y_casex_correct);
    // do at the beginning of the simulation
    initial 
        $dumpvars;  //iverilog dump init
endmodule
module top
(
    input  clk,
    output led,

    inout            io_1  , io_2  , io_3  , io_4  , io_5  , io_6  , io_7  , io_8  ,
                                                     io_15 , io_16 , io_17 , io_18 , io_19 ,
           io_20  ,  io_21 ,                                 io_26 , io_27 , io_28 , io_29 ,
           io_30  ,                  io_33 , io_34 , io_35 , io_36 , io_37 , io_38 , io_39 ,
           io_40  ,  io_41 , io_42 , io_43 , io_44 ,                 io_47 , io_48 , io_49 ,
           io_50  ,  io_51 , io_52 , io_53 , io_54 , io_55 , io_56 , io_57 , io_58 ,
                     io_61 ,                                 io_66 , io_67 , io_68 , io_69 ,
           io_70  ,  io_71 , io_72 , io_73 , io_74 , io_75 , io_76 ,         io_78 ,
                     io_81 , io_82 , io_83 , io_84 , io_85 , io_86 , io_87 , io_88 , io_89 ,
           io_90  ,  io_91 , io_92 ,                 io_95 , io_96 , io_97 , io_98 , io_99 ,
           io_100
);

    reg [31:0] cnt;
    
    always @ (posedge clk)
        cnt <= cnt + 1;

    assign led = cnt [24];

    wire [ 3:0] key = { io_15 , io_16 , io_17 , io_18 };
    wire [ 7:0] sw  = { io_1  , io_2  , io_3  , io_4  , io_5  , io_6  , io_7  , io_8 };

    wire [11:0] led2;
    wire [ 7:0] abcdefgh;
    wire [ 7:0] digit;
    wire        buzzer;

    assign { io_81 , io_82 , io_83 , io_84 , io_85 , io_86 ,
             io_87 , io_88 , io_89 , io_90 , io_91 , io_92 } = led2;

    assign { io_33 , io_34 , io_35 , io_36 ,
             io_37 , io_38 , io_39 , io_40 } = abcdefgh;

    assign { io_50 , io_51 , io_52 , io_53 ,
             io_54 , io_55 , io_56 , io_57 } = digit;

    assign io_58 = buzzer;

    top2 i_top2
    (
        clk,
        key,
        sw,
        led2,
        abcdefgh,
        digit,
        buzzer
    );

endmodule
module moore_fsm
(
    input  clk,
    input  rst_n,
    input  en,
    input  a,
    output y
);

    parameter [1:0] S0 = 0, S1 = 1, S2 = 2;

    reg [1:0] state, next_state;

    // State register

    always @ (posedge clk or negedge rst_n)
        if (! rst_n)
            state <= S0;
        else if (en)
            state <= next_state;

    // Next state logic

    always @*
        case (state)
        
        S0:
            if (a)
                next_state = S0;
            else
                next_state = S1;

        S1:
            if (a)
                next_state = S2;
            else
                next_state = S1;

        S2:
            if (a)
                next_state = S0;
            else
                next_state = S1;

        default:

            next_state = S0;

        endcase

    // Output logic based on current state

    assign y = (state == S2);

endmodule
module mealy_fsm
(
    input  clk,
    input  rst_n,
    input  en,
    input  a,
    output y
);

    parameter [0:0] S0 = 1'b0, S1 = 1'b1;

    reg state, next_state;

    // State register

    always @ (posedge clk or negedge rst_n)
        if (! rst_n)
            state <= S0;
        else if (en)
            state <= next_state;

    // Next state logic

    always @*
        case (state)
        
        S0:
            if (a)
                next_state = S0;
            else
                next_state = S1;

        S1:
            if (a)
                next_state = S0;
            else
                next_state = S1;

        default:

            next_state = S0;

        endcase

    // Output logic based on current state and inputs

    assign y = (a & state == S1);

endmodule
module sync_and_debounce_one
# (
    parameter depth = 8
)
(   
    input      clk,
    input      sw_in,
    output reg sw_out
);

    reg  [depth - 1:0] cnt;
    reg  [        2:0] sync;
    wire               sw_in_s;

    assign sw_in_s = sync [2];

    always @ (posedge clk)
        sync <= { sync [1:0], sw_in };

    always @ (posedge clk)
        if (sw_out ^ sw_in_s)
            cnt <= cnt + 1'b1;
        else
            cnt <= { depth { 1'b0 } };

    always @ (posedge clk)
        if (cnt == { depth { 1'b1 } })
            sw_out <= sw_in_s;

endmodule
module sync_and_debounce
# (
    parameter w = 1, depth = 8
)
(   
    input            clk,
    input  [w - 1:0] sw_in,
    output [w - 1:0] sw_out
);

    genvar sw_cnt;

    generate
        for (sw_cnt = 0; sw_cnt < w; sw_cnt = sw_cnt + 1)
        begin : gen_sync_and_debounce
           
           sync_and_debounce_one
           # (.depth (depth))
           i_sync_and_debounce_one
           (    
              .clk    ( clk             ),
              .sw_in  ( sw_in  [sw_cnt] ),
              .sw_out ( sw_out [sw_cnt] )
           );

        end
    endgenerate 

endmodule
module counter
# (
    parameter w = 1
) 
(
    input            clk,
    input            rst_n,
    input            en,
    output [w - 1:0] cnt
);

    wire [w - 1:0] q;
    wire [w - 1:0] d = q + 1'b1;

    register # (w) i_reg (clk, rst_n, en, d, q);
    
    assign cnt = q;

endmodule
module counter
# (
    parameter w = 1
) 
(
    input                clk,
    input                rst_n,
    input                en,
    output reg [w - 1:0] cnt
);

    always @ (posedge clk or negedge rst_n)
        if (! rst_n)
            cnt <= { w { 1'b0 } };
        else if (en)
            cnt <= cnt + 1'b1;

endmodule
module register
# (
    parameter w = 1
) 
(
    input                clk,
    input                rst_n,
    input                en,
    input      [w - 1:0] d,
    output reg [w - 1:0] q
);

    always @ (posedge clk or negedge rst_n)
        if (! rst_n)
            q <= { w { 1'b0 } };
        else if (en)
            q <= d;

endmodule
module selector
#(
    parameter w = 8,
              n = 2
) 
(
    input      [n * w - 1:0] d,
    input      [n     - 1:0] sel,
    output reg [w     - 1:0] y
);

    integer i;

    always @*
    begin
        y = { w { 1'b0 } };
        
        for (i = 0; i < n; i = i + 1) 
            y = y | (d [i * w +: w] & { w { sel [i] } });
    end

endmodule
module testbench;

    reg         clk;
    reg  [ 3:0] key;
    reg  [ 7:0] sw;
    wire [11:0] led;
    wire [ 7:0] abcdefgh;
    wire [ 7:0] digit;
    wire        buzzer;

    top i_top
    (
        .clk      ( clk      ),
        .key      ( key      ),
        .sw       ( sw       ),
        .led      ( led      ),
        .abcdefgh ( abcdefgh ),
        .digit    ( digit    ),
        .buzzer   ( buzzer   )
    );


    initial
    begin
        clk = 0;

        forever
            # 10 clk = ! clk;
    end

    reg rst_n;
    
    always @*
        key [3] = rst_n;

    initial
    begin
        repeat (2) @ (posedge clk);
        rst_n <= 0;
        repeat (2) @ (posedge clk);
        rst_n <= 1;
    end

    initial
    begin
        #0
        $dumpvars;

        @ (posedge rst_n);

        repeat (10000)
        begin
            @ (posedge clk);

            key <= $random;
            sw  <= $random;
        end

        $stop;
    end

endmodule
module strobe_gen
# (
    parameter w = 24
)
(
    input  clk,
    input  rst_n,
    output strobe
);

    wire [w - 1:0] count; 

    counter # (w) i_counter (clk, rst_n, 1'b1, count);
    assign strobe = (count == { w { 1'b0 } } );

endmodule
module seven_segment
# (
    parameter w              = 32,
              bits_per_digit = 4,
              n_digits       = w / bits_per_digit
)
(
    input                   clk,
    input                   rst_n,
    input                   en,
    input  [w        - 1:0] num,
    input  [n_digits - 1:0] dots,
    output [6:0]            abcdefg,
    output                  dot,
    output [n_digits - 1:0] anodes
);

    function [6:0] dig_to_seg (input [3:0] dig);

        case (dig)
        'h0: dig_to_seg = 'b0000001;  // a b c d e f g
        'h1: dig_to_seg = 'b1001111;
        'h2: dig_to_seg = 'b0010010;  //   --a--
        'h3: dig_to_seg = 'b0000110;  //  |     |
        'h4: dig_to_seg = 'b1001100;  //  f     b
        'h5: dig_to_seg = 'b0100100;  //  |     |
        'h6: dig_to_seg = 'b0100000;  //   --g--
        'h7: dig_to_seg = 'b0001111;  //  |     |
        'h8: dig_to_seg = 'b0000000;  //  e     c
        'h9: dig_to_seg = 'b0001100;  //  |     |
        'ha: dig_to_seg = 'b0001000;  //   --d-- 
        'hb: dig_to_seg = 'b1100000;
        'hc: dig_to_seg = 'b0110001;
        'hd: dig_to_seg = 'b1000010;
        'he: dig_to_seg = 'b0110000;
        'hf: dig_to_seg = 'b0111000;
        endcase

    endfunction

    //------------------------------------------------------------------------

    reg [n_digits - 1:0] anodes_d, anodes_q;

    always @*
        anodes_d <= { anodes_q [0], anodes_q [n_digits - 1 : 1] };

    always @ (posedge clk or negedge rst_n)
        if (! rst_n)
            anodes_q <= { { n_digits - 1 { 1'b1 } }, 1'b0 };
        else if (en)
            anodes_q <= anodes_d;
    
    assign anodes = anodes_q;
    
    //------------------------------------------------------------------------

    wire [bits_per_digit - 1:0] dig;

    selector # (.w (bits_per_digit), .n (n_digits)) i_sel_dig
        (.d (num), .sel (~ anodes_d), .y (dig));

    register_no_rst # (7) i_abcdefg
    (
        .clk ( clk              ),
        .en  ( en               ),
        .d   ( dig_to_seg (dig) ),
        .q   ( abcdefg          )
    ); 

    //------------------------------------------------------------------------

    wire dot_d;

    selector # (.w (1), .n (n_digits)) i_sel_dot
        (.d (dots), .sel (~ anodes_d), .y (dot_d));

    register_no_rst i_dot
    (
        .clk (   clk   ),
        .en  (   en    ),
        .d   ( ~ dot_d ),
        .q   (   dot   )
    ); 

endmodule
module register_no_rst
# (
    parameter w = 1
) 
(
    input                clk,
    input                en,
    input      [w - 1:0] d,
    output reg [w - 1:0] q
);

    always @ (posedge clk)
        if (en)
            q <= d;

endmodule