dakies/OSS_Verilog huggingface dataset:
module maxpooling(
    input               clk             ,
    input               rst_n           ,

    input               valid_input     ,
    input   [32:0]      input_data      ,

    output              out_valid       ,
    output  [32:0]      out_data
    );

    reg     [ 9:0]      count            ;
    reg     [ 4:0]      max_cnt          ;
    reg                 out_flag         ;

    wire    [32:0]      ram_reg          ;
    wire    [32:0]      max_col_1_reg    ;
    wire    [32:0]      max_col_2_reg    ;

    reg     [32:0]      win_pool  [3:0]  ;

   always @ (posedge clk or negedge rst_n)begin
        if (!rst_n)
            count <= 10'd0;
        else if (valid_input)
            count <= count + 1'b1;
        else
            count <= count;
    end

    always @ (posedge clk or negedge rst_n)begin
        if (!rst_n)
            max_cnt <= 5'd0;
        else if (count >= 10'd25 && count <= 10'd576 && max_cnt == 5'd24)
            max_cnt <= 5'd1;
        else if (count >= 10'd25 && count <= 10'd576)
            max_cnt <= max_cnt + 1'b1;
        else
            max_cnt <= max_cnt;
    end

    always @ (posedge clk or negedge rst_n)begin
        if (!rst_n)
            out_flag <= 1'd0;
            else if (max_cnt >= 5'd1 && max_cnt <= 5'd23)
            out_flag <= ~ out_flag;
        else
            out_flag <= 1'b0;
    end

    always @ (posedge clk or negedge rst_n)begin
        if (!rst_n)begin
            win_pool[0] <= 32'd0;
            win_pool[1] <= 32'd0;
            win_pool[2] <= 32'd0;
            win_pool[3] <= 32'd0;
        end
        else if (count >= 10'd24 && count <= 10'd576)begin
            win_pool[0] <= ram_reg;
            win_pool[1] <= input_data;
            win_pool[2] <= win_pool[0];
            win_pool[3] <= win_pool[1];
        end
        else begin
            win_pool[0] <= win_pool[0];
            win_pool[1] <= win_pool[1];
            win_pool[2] <= win_pool[2];
            win_pool[3] <= win_pool[3];
        end
    end

    assign max_col_1_reg = win_pool[0] > win_pool[1] ? win_pool[0] : win_pool[1];
    assign max_col_2_reg = win_pool[2] > win_pool[3] ? win_pool[2] : win_pool[3];
    assign out_data      = out_valid == 1'b0 ? 32'd0 : max_col_2_reg > max_col_1_reg ? max_col_2_reg : max_col_1_reg;
    assign out_valid     = count >= 10'd24 && max_cnt >= 5'd2 && max_cnt <=5'd24 && out_flag ? 1'b1 : 1'b0;
    
    data_fifo fifo_inst(
        .CLK    (clk        ),
        .D      (input_data ),
        .CE     (valid_input),
        .Q      (ram_reg    )
    );
endmodule
module rainbow_generate(
    input           	  clk     ,
    input           	  rst_n   ,

    input   	[ 9:0]  x_pix   ,
    input   	[ 9:0]  y_pix   ,

    output reg [23:0]  data
);

parameter red       = 24'hFF0000;
parameter green     = 24'h00FF00;
parameter blue      = 24'h0000FF;
parameter purple    = 24'h9B30FF;
parameter yellow    = 24'hFFFF00;
parameter cyan      = 24'h00FFFF;
parameter orange    = 24'hFFA500;
parameter white     = 24'hFFFFFF;

parameter bar_wide = 10'd640 / 10'd8;

always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		data <= 24'b0;
	end
	else begin
		if(x_pix < bar_wide * 11'd1)
			data <= red;
		else if(x_pix < bar_wide * 11'd2)
			data <= green;
		else if(x_pix < bar_wide * 11'd3)
			data <= blue;
		else if(x_pix < bar_wide * 11'd4)
			data <= purple;
		else if(x_pix < bar_wide * 11'd5)
			data <= yellow;
		else if(x_pix < bar_wide * 11'd6)
			data <= cyan;
		else if(x_pix < bar_wide * 11'd7)
			data <= orange;
		else
			data <= white;
	end
end

endmodule
module relu(
    input       [32:0]      A   ,
    output      [32:0]      B
    );

    assign B = A[32] == 1'b0 ? A : 33'b0;
endmodule
module vga_top(
    input           sys_clk     ,
    input           sys_rst_n   ,

    output          hs          ,
    output          vs          ,
	 output			  clk_25MHz	  ,
    output  [23:0]  color_rgb
);

wire    [ 9:0]  x_pix       ;
wire    [ 9:0]  y_pix       ;

wire    [23:0]  data        ;


vga vga_inst(
    .clk        (clk_25MHz      ),
    .rst_n      (sys_rst_n      ),

    .data       (data           ),

    .hs         (hs             ),
    .vs         (vs             ),

    .x_pix      (x_pix          ),
    .y_pix      (y_pix          ),

    .color_rgb  (color_rgb      )
);

rainbow_generate inst(
    .clk        (clk_25MHz      ),
    .rst_n      (sys_rst_n      ),

    .x_pix      (x_pix          ),
    .y_pix      (y_pix          ),

    .data       (data           )
);

PLL_25MHz clk_25MHz_generate(
    .refclk     (sys_clk        ),
    .rst        (~sys_rst_n     ),
    .outclk_0   (clk_25MHz      ),
    .locked     (locked         )
);
endmodule
module max_data_generate(
    input           clk              ,
    input           rst_n            ,
    input           data_start       ,

    output          data_out_valid   ,
    output  [32:0]  data_out
    );

    wire    [32:0]      data_out_out         ;

    reg     [32:0]      data_out_reg         ;
    reg     [ 9:0]      addr                 ;
    reg                 work_en              ;
    reg                 data_out_valid_reg   ;

always @ (posedge clk or negedge rst_n)begin
    if (!rst_n)
        data_out_reg <= 16'b0;
    else if (data_out_out)
        data_out_reg <= data_out_out;
    else
        data_out_reg <= data_out_reg;
end

always @ (posedge clk or negedge rst_n)begin
    if (!rst_n)
        data_out_valid_reg <= 1'b0;
    else if (work_en && addr == 9'd1)
        data_out_valid_reg <= 1'b1;
    else if (addr == 10'd576)
        data_out_valid_reg <= 1'b0;
    else
        data_out_valid_reg <= data_out_valid_reg;
end

always @ (posedge clk or negedge rst_n)begin
    if (!rst_n)
        addr <= 10'b0;
    else if (work_en && addr == 10'd576)
        addr <= 10'd576;
    else if (work_en)
        addr <= addr + 1'b1;
    else
        addr <= addr;
end

always @ (posedge clk or negedge rst_n)begin
    if (!rst_n)
        work_en <= 1'b0;
    else if (data_start)
        work_en <= 1'b1;
    else if (addr == 10'd576)
        work_en <= 1'b0;
end

assign  data_out = data_out_reg;
assign  data_out_valid = data_out_valid_reg;

rom_max_data rom_max_data(
    .clka   (clk            ),
    .addra  (addr           ),
    .douta  (data_out_out   )
);
endmodule
module top;
  reg clk = 1;
  reg tick_60hz = 0;
  reg [15:0] keys = 0;
  wire out;

  cpu cpu0(.clk(clk),
           .tick_60hz(tick_60hz),
           .tick_next(1'b1),
           .keys(keys),
           .out(out),
           .scr_busy(1'b0),
           .scr_read(1'b0));

  initial
    forever #1 clk = ~clk;

  initial
    forever begin
      #98 tick_60hz = 1;
      #2 tick_60hz = 0;
    end

  initial utils.timeout(10000);

  task reset;
    integer i;
    begin
      for (i = 0; i < 'h1000; i++)
        cpu0.mem0.data[i] = 0;
      $readmemh("font.hex", cpu0.mem0.data, 'h030, 'h07f);

      cpu0.addr = 0;
      cpu0.pc = 'h200;
      cpu0.dt = 0;
      cpu0.st = 0;

      cpu0.state = cpu0.STATE_NEXT;
    end
  endtask

  integer i;

`define run(name) \
  $display("Running %s", name); \
  reset; \
  $readmemh(name, cpu0.mem0.data, 'h200, 'hFFF); \
  wait (cpu0.state == cpu0.STATE_STOP);

  initial begin
    $dumpfile(`VCD_FILE);
    $dumpvars;

    `run("build/test_jump.hex");
    utils.assert_equal(cpu0.mem0.data['h020], 'h42);

    `run("build/test_call.hex");
    utils.assert_equal(cpu0.mem0.data['h020], 'h42);

    `run("build/test_add.hex");
    utils.assert_equal(cpu0.mem0.data['h020], 'h42);

    `run("build/test_mem.hex");
    utils.assert_equal(cpu0.mem0.data['h020], 'h42);

    `run("build/test_jump_v0.hex");
    utils.assert_equal(cpu0.mem0.data['h020], 'h42);

    keys <= 'b10101010;
    `run("build/test_keys.hex");
    keys <= 'b00000000;
    utils.assert_equal(cpu0.mem0.data['h020], 'b10101010);

    `run("build/test_screen.hex");
    for (i = 'h100; i < 'h200; i++)
      utils.assert_equal(cpu0.mem0.data[i], 0);

    `run("build/test_drw.hex");

    utils.assert_equal(cpu0.mem0.data['h138], 'b00100000);
    utils.assert_equal(cpu0.mem0.data['h140], 'b01100000);
    utils.assert_equal(cpu0.mem0.data['h148], 'b00100000);
    utils.assert_equal(cpu0.mem0.data['h150], 'b00100000);
    utils.assert_equal(cpu0.mem0.data['h158], 'b01110000);

    utils.assert_equal({cpu0.mem0.data['h110], cpu0.mem0.data['h111]}, 'b00110000_00110000);
    utils.assert_equal({cpu0.mem0.data['h118], cpu0.mem0.data['h119]}, 'b00111100_11110000);
    utils.assert_equal({cpu0.mem0.data['h120], cpu0.mem0.data['h121]}, 'b00111100_11110000);
    utils.assert_equal({cpu0.mem0.data['h128], cpu0.mem0.data['h129]}, 'b00111100_11110000);
    utils.assert_equal({cpu0.mem0.data['h130], cpu0.mem0.data['h131]}, 'b00110000_00110000);

    // collision
    utils.assert_equal(cpu0.mem0.data['h02f], 1);

    `run("build/test_bcd.hex");
    utils.assert_equal(cpu0.mem0.data['h020], 'h42);

    // This program should wait 5 ticks
    i = $time;
    `run("build/test_timers.hex");
    utils.assert_equal(($time - i) / 100, 5);
    utils.assert_equal(out, 1);

    $finish;
  end
endmodule // Top
module screen_bridge(input wire clk,
                     input wire tick_60hz,
                     input wire read,
                     input wire [5:0] row_idx,
                     input wire [6:0] column_idx,
                     output reg [7:0] data,
                     output reg ack,

                     output wire scr_busy,
                     output wire scr_read,
                     output wire [7:0] scr_read_idx,
                     input wire [7:0] scr_read_byte,
                     input wire scr_read_ack);

  reg [7:0] buffer [0:1023];
  wire [9:0] buffer_read_idx = {row_idx[2:0], column_idx};

  // 8 x 4 rectangle (scanned in horizontal stripes, output in vertical ones)
  reg [7:0] rect [0:3];
  // Num of rectangle on screen
  reg [5:0] rect_num = 0;
  // Index of byte (horizontal stripe) in rectangle
  reg [1:0] rect_scan_idx = 0;

  // Index of vertical stripe in rectangle (16 double-pixel stripes)
  reg [3:0] rect_write_idx = 0;

  assign scr_read = state == STATE_READ_RECT && !scr_read_ack;
  assign scr_read_idx = {rect_num[5:3], rect_scan_idx, rect_num[2:0]};
  wire [9:0] buffer_write_idx = {rect_num, rect_write_idx};

  wire [7:0] buffer_write_byte = {rect[3][7], rect[3][7],
                                  rect[2][7], rect[2][7],
                                  rect[1][7], rect[1][7],
                                  rect[0][7], rect[0][7]};

  localparam
    STATE_READ_RECT = 0,
    STATE_WRITE_RECT = 1,
    STATE_WAIT = 2;

  assign scr_busy = state != STATE_WAIT;

  reg [1:0] state = STATE_READ_RECT;

  reg draw_next = 0;

  always @(posedge clk) begin
    if (tick_60hz)
      draw_next <= 1;

    ack <= 0;
    if (read) begin
      ack <= 1;
      data <= buffer[buffer_read_idx];
    end

    case (state)
      STATE_READ_RECT: begin
        if (scr_read_ack) begin
          rect[rect_scan_idx] <= scr_read_byte;
          rect_scan_idx <= rect_scan_idx + 1;
          if (rect_scan_idx == 'b11) begin
            state <= STATE_WRITE_RECT;
          end
        end
      end
      STATE_WRITE_RECT: begin
        buffer[buffer_write_idx] <= buffer_write_byte;
        rect_write_idx <= rect_write_idx + 1;
        if (rect_write_idx[0]) begin
          rect[0] <= rect[0] << 1;
          rect[1] <= rect[1] << 1;
          rect[2] <= rect[2] << 1;
          rect[3] <= rect[3] << 1;
        end
        if (rect_write_idx == 'b1111) begin
          rect_num <= rect_num + 1;
          if (rect_num == 'b111111)
            state <= STATE_WAIT;
          else
            state <= STATE_READ_RECT;
        end
      end
      STATE_WAIT:
        if (draw_next) begin
          draw_next <= 0;
          state <= STATE_READ_RECT;
        end
    endcase
  end
endmodule
module bcd(input wire [7:0] abc,
           output wire [1:0] a,
           output reg [3:0] b,
           output reg [3:0] c);
  assign a = abc >= 200 ? 2 : abc >= 100 ? 1 : 0;
  wire [6:0] bc = abc - 100 * a;

  // See Hacker's Delight, Integer division by constants:
  // https://www.hackersdelight.org/divcMore.pdf
  reg [6:0] q;
  reg [3:0] r;
  always @(*) begin
    q = (bc >> 1) + (bc >> 2);
    q = q + (q >> 4);
    q = q >> 3;
    r = bc - q * 10;
    if (r < 10) begin
      b = q;
      c = r;
    end else begin
      b = q + 1;
      c = r - 10;
    end
  end
endmodule
module utils;
  task assert_true;
    input x;
    begin
      if (!x) begin
        $error($time, " Assertion failed");
        $finish_and_return(1);
      end
    end
  endtask

  task assert_equal;
    input [31:0] x;
    input [31:0] y;
    begin
      if (x != y) begin
        $error($time, " %x != %x", x, y);
        $finish_and_return(1);
      end
    end
  endtask

  task timeout;
    input [31:0] n;
    begin
      #n;
      $error($time, " Timed out after %d ticks", n);
      $finish_and_return(1);
    end
  endtask
endmodule
module rng(input wire clk,
           output wire [31:0] out,
           input wire user_input);
  reg [31:0] state = 42;
  reg [31:0] next;
  assign out = state;

  always @(*) begin
    next = state;
    next = next ^ (next << 13);
    next = next ^ (next >> 17);
    next = next ^ (next << 5);

    if (user_input) begin
      next = next ^ (next << 13);
      next = next ^ (next >> 17);
      next = next ^ (next << 5);
    end
  end

  always @(posedge clk) begin
    state <= next;
  end
endmodule
module mem(input wire clk,
           input wire read,
           input wire [11:0] read_idx,
           output reg [7:0] read_byte,
           output reg read_ack = 0,
           input wire write,
           input wire [11:0] write_idx,
           input wire [7:0] write_byte);

  parameter debug = 0;

  reg [7:0] data[0:'hFFF];

  initial $readmemh("font.hex", data, 'h030, 'h07f);
  // for icebram to replace
  initial $readmemh("random.hex", data, 'h200, 'hfff);

  always @(posedge clk) begin
    read_ack <= 0;
    if (read) begin
      if (debug)
        $display($time, " load [%x] = %x", read_idx, data[read_idx]);
      read_byte <= data[read_idx];
      read_ack <= 1;
    end
    if (write) begin
      if (debug)
        $display($time, " store [%x] = %x", write_idx, write_byte);
      data[write_idx] <= write_byte;
    end
  end
endmodule
module top;
  reg [7:0] abc = 0;
  wire [1:0] a;
  wire [3:0] b, c;

  bcd bcd0(abc, a, b, c);

  initial begin
    $monitor($time, " %d -> %d %d %d", abc, a, b, c);
    $dumpfile(`VCD_FILE);
    $dumpvars;

    repeat (256) begin
      #1;
      utils.assert_equal(abc, a * 100 + b * 10 + c);
      utils.assert_true(a < 10 && b < 10 && c < 10);

      abc += 1;
    end
    #1 $finish;
  end
endmodule
module ext18#(parameter DEPTH=18)(
input [DEPTH-1:0] a,
output reg [31:0] b
    );
    always@(a)
    begin
      if(a[DEPTH-1] == 1)//ÓÐ·ûºÅÀ©Õ¹
            begin 
                b[31:0] = 32'hffffffff;
                b[DEPTH-1:0] = a[DEPTH-1:0];
            end
            else
            begin 
                b[31:0] = 32'h00000000;
                b[DEPTH-1:0] = a[DEPTH-1:0];
            end
    end
endmodule
module cpu(
input clk,
input [31:0] inst,
input reset,
input [31:0] mrdata,

output [31:0] pc_out,
output [31:0] maddr,
output [31:0] mwdata,
output IM_R,
output DM_CS,
output DM_R,
output DM_W,
output [31:0]alu_r  
    );
    
wire RF_W,M1,M2,M3,M4,M5,M6,sign_ext,zero;
wire [2:0] ALUC;
wire[31:0] mux1_out,mux2_out,mux3_out,mux4_out,mux5_out,alu_out;
wire [31:0] rf_rdata1,rf_rdata2;
wire [31:0] ext5_out,ext16_out,ext18_out;
wire [31:0] npc_out;
wire [31:0] join_out;
wire [27:0] temp1,temp2;
    
assign alu_r = alu_out;
assign maddr = alu_out;
assign mwdata = rf_rdata2;
assign temp1 = inst[25:0]<<2;
assign temp2 = inst[15:0]<<2;
    
wire [4:0]mux6_out = M6 ? inst[20:16]:inst[15:11];
    
decoder cpu_decoder(inst,clk,zero,IM_R,M3,M4,ALUC,M2,RF_W,M5,M1,DM_CS,DM_R,DM_W,M6,sign_ext);

PC cpu_pc(clk,reset,mux1_out,pc_out);
NPC cpu_npc(pc_out,npc_out);

JOIN cpu_join(temp1,pc_out[31:28],join_out);

regfile cpu_regfile(clk,reset,RF_W,inst[25:21],inst[20:16],mux6_out,mux2_out,rf_rdata1,rf_rdata2);

alu cpu_alu(mux3_out,mux4_out,ALUC,alu_out,zero);

ext5 cpu_ext5(inst[10:6],ext5_out);

ext16 cpu_ext16(inst[15:0],sign_ext,ext16_out);

ext18 cpu_ext18(temp2,ext18_out);

mux2x32 mux1(join_out,mux5_out,M1,mux1_out);

mux2x32 mux2(mrdata,alu_out,M2,mux2_out);

mux2x32 mux3(ext5_out,rf_rdata1,M3,mux3_out);

mux2x32 mux4(rf_rdata2,ext16_out,M4,mux4_out);

mux2x32 mux5(npc_out,(ext18_out+pc_out+4),M5,mux5_out);
    
    


endmodule
module top_tb;
    reg clk_in;
    reg reset;
    wire clk;
    wire [31:0]pc;
    wire [31:0]inst;
    wire IM_R;
    wire DM_CS;
    wire DM_R;
    wire DM_W;

    wire [31:0]alu_r;

    top uut(clk_in,reset,clk,pc,inst,addr,rdata,wdata,IM_R,DM_CS,DM_R,DM_W,alu_r);

    // 不同的initial块是并行的，块内部顺序执行
    initial 
    begin
        clk_in = 0;
        forever #100 clk_in = ~clk_in;
    end

    initial
    begin
        reset = 0;
        #50 reset=1;
        #10 reset=0;
        #2000 $stop;
    end
        
    initial // 用iverilog+gtkwave仿真时用到的
    begin            
        $dumpfile("wave.vcd");        //生成的vcd文件名称
        $dumpvars(0, top_tb);    //tb模块名称
    end

endmodule
module mux2x32#(parameter WIDTH=32)(
input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
input select,
output reg [WIDTH-1:0] r
    );
    always @*
    begin
      case(select)
        1'b0:
        r=a;
        1'b1:
        r=b;
      endcase
    end
endmodule
module imem(
input [31:0] a,
input IM_R,
output [31:0] rd
    );
   
    reg [31:0] RAM[2047:0];
    initial
    begin
      $readmemh("imem.txt",RAM);
    end
    
   assign rd=(IM_R)?RAM[a[31:2]]:32'bx;
endmodule
module decoder(
input [31:0] inst,
input clk,
input zero,
output IM_R,
output M3,
//output M4_0,
//output M4_1,
output M4,
output [2:0] ALUC,
output M2,
output RF_W,
//output RF_CLK,
output M5,
output M1,
output DM_CS,
output DM_R,
output DM_W,
output M6,
output sign_ext
    );
    
wire [5:0] func=inst[5:0];  
wire [5:0] op=inst[31:26];
wire r_type=~|op;
wire addu,subu,ori,sll,lw,sw,beq,j_i;
    
assign addu=r_type &func[5]&~func[4]&~func[3]&~func[2]&~func[1]&func[0];
assign subu=r_type &func[5]&~func[4]&~func[3]&~func[2]&func[1]&func[0];    
assign ori=~op[5]&~op[4]&op[3]&op[2]&~op[1]&op[0];
assign sll=r_type &~func[5]&~func[4]&~func[3]&~func[2]&~func[1]&~func[0];
assign lw=op[5]&~op[4]&~op[3]&~op[2]&op[1]&op[0];
assign sw=op[5]&~op[4]&op[3]&~op[2]&op[1]&op[0];
assign beq=~op[5]&~op[4]&~op[3]&op[2]&~op[1]&~op[0];
assign j_i=~op[5]&~op[4]&~op[3]&~op[2]&op[1]&~op[0];

assign IM_R=1;
 
assign RF_W=addu|subu|ori|sll|lw;

assign DM_CS=lw|sw;
assign DM_R=lw;
assign DM_2=sw;
assign DM_W=sw;

assign ALUC[2]=0;
assign ALUC[1]=ori|sll;
assign ALUC[0]=subu|beq|sll;

assign M1=addu|subu|ori|sll|beq|lw|sw;
assign M2=addu|subu|ori|sll|beq|j_i|sw;
assign M3=addu|subu|ori|j_i|beq|lw|sw;
//assign M4_0=ori;
//assign M4_1=lw|sw;
assign M4=lw|sw|ori;
assign M5=beq&zero;
assign M6=ori|lw;

assign sign_ext=lw | sw;

endmodule
module JOIN(
input [27:0] a,
input [3:0] b,
output [31:0] s
    );
    assign s[31:28]=b;
    assign s[27:0]=a;
endmodule
module ext16#(parameter DEPTH=16)(
input [DEPTH-1:0] a,
input sign_ext,
output reg [31:0] b
    );
always@(a or sign_ext)
begin
  if(sign_ext==1 && a[DEPTH-1]==1)
  begin
    b[31:0]=32'hffffffff;
    b[DEPTH-1:0]=a[DEPTH-1:0];
  end
  else
  begin
     b[31:0]=32'h00000000;
     b[DEPTH-1:0]=a[DEPTH-1:0];
  end
end
endmodule
module top(
input clk_in,
input reset,

output clk,
output [31:0]pc,
output [31:0]inst,
output [31:0]addr,
output [31:0]rdata,
output [31:0]wdata,
output IM_R,
output DM_CS,
output DM_R,
output DM_W,
output [31:0]alu_r      
    );
    
    assign clk = clk_in;
    
    cpu sccpu(clk_in,inst,reset,rdata,pc,addr,wdata,IM_R,DM_CS,DM_R,DM_W,alu_r);
                
    imem imemory(pc, IM_R, inst);
                
    dmem scdmem(clk_in,reset,DM_CS,DM_W,DM_R,addr,wdata,rdata);
endmodule
module ext5 #(parameter DEPTH=5)(
input [DEPTH-1:0] a,
output reg [31:0] b
    );
always@(a)
begin
  if(a[DEPTH-1]==1)
  begin
    b[31:0]=32'hffffffff;
    b[DEPTH-1:0]=a[DEPTH-1:0];
  end
  else
  begin
    b[31:0]=32'h00000000;
    b[DEPTH-1:0]=a[DEPTH-1:0];
  end
end
endmodule
module regfile(
input clk,
input rst,
input we,
input [4:0] raddr1,
input [4:0] raddr2,
input [4:0] waddr,
input [31:0] wdata,
output [31:0] rdata1,
output [31:0] rdata2
    );
reg [31:0] array_reg[31:0];
integer i;

always@(posedge clk,posedge rst)
begin
  if(rst)
  begin
    i=0;
    while(i<32)
    begin
      array_reg[i]=0;
      i=i+1;
    end
  end
  else if(we)
  begin
    if(waddr!=0)
    array_reg[waddr]=wdata;
  end
end

assign rdata1=array_reg[raddr1];
assign rdata2=array_reg[raddr2];

endmodule
module PC(
input clk,
input rst,
input [31:0] data_in,
output reg [31:0] data_out
    );
always@(posedge clk,posedge rst)
begin
if(rst)
    data_out<=32'b0;
else
    data_out<=data_in;
end    
    
endmodule
module alu(
input [31:0] a,
input [31:0] b,
input [2:0] aluc,
output [31:0] r,
output zero
    );
    
reg [31:0] r_1;

always@*
begin
  case(aluc)
  3'b000:
  r_1=a+b;
  3'b001:
  r_1=a-b;
  3'b010:
  r_1=a|b;
  3'b011:
  r_1=b<<a[4:0];
  default:;
  endcase
end

assign r=r_1;
assign zero=r?1'b0:1'b1;
endmodule
module dmem(
input clk,
input reset,
input CS,
input DM_W,
input DM_R,
input [31:0] addr,
input [31:0] wdata,
output [31:0] rdata
    );
    
reg [31:0] ROM [2047:0];
initial
begin
  $readmemh("D:/Downloads/CPU-master/rom.data",ROM);
end


assign rdata=(CS&DM_R)?ROM[addr[31:2]]:32'h0;

always @(posedge clk)
begin
  if(CS)
  begin
    if(DM_W)
      ROM[addr[31:2]]<=wdata;
  end
end
endmodule
module testrotor();	
	reg [2:0] rotor_type_3 = 3'b010;
	reg [2:0] rotor_type_2 = 3'b001;

	reg [4:0] rotor_start_3 = 5'b00000;
	reg [4:0] rotor_start_2 = 5'b00000;
	reg [4:0] rotor_start_1 = 5'b00000;

	reg [4:0] ring_position_3 = 5'b00000;
	reg [4:0] ring_position_2 = 5'b00000;
	reg [4:0] ring_position_1 = 5'b00000;
	reg reflector_type = 1'b0;
	
	reg i_clock = 0;
	
	reg reset;
	reg rotate = 0;
	
	wire [4:0] rotor1;
	wire [4:0] rotor2;
	wire [4:0] rotor3;
	
	integer i;
	
	rotor rotorcontrol(.clock(i_clock),.rotor1(rotor1),.rotor2(rotor2),.rotor3(rotor3),
	        .reset(reset),.rotate(rotate),
	        .rotor_type_2(rotor_type_2),.rotor_type_3(rotor_type_3),
		    .rotor_start_1(rotor_start_1),.rotor_start_2(rotor_start_2),.rotor_start_3(rotor_start_3)
			);
	
	always
		#(5) i_clock <= !i_clock;
 
    initial
	begin
		$dumpfile("testrotor.vcd");
		$dumpvars(0,testrotor);
		
		#5
		reset = 1;
		#10
		reset = 0;
		for (i = 0; i < 128; i = i + 1) 		
		begin
		#10
			rotate = 1;
		#10
			rotate = 0;
		#20
			$display("Rotors [%c] [%c] [%c]",rotor1+65,rotor2+65,rotor3+65);
		end


		#10

		$finish;
	end
endmodule
module enigma_top
  (input  i_Clk,       // Main Clock
   input  i_UART_RX,   // UART RX Data
   output o_UART_TX,    // UART TX Data
   output o_LED_1,
   output o_LED_2,
   output o_LED_3,
   output o_LED_4,
 // Segment1 is upper digit, Segment2 is lower digit
   output o_Segment1_A,
   output o_Segment1_B,
   output o_Segment1_C,
   output o_Segment1_D,
   output o_Segment1_E,
   output o_Segment1_F,
   output o_Segment1_G,
   //
   output o_Segment2_A,
   output o_Segment2_B,
   output o_Segment2_C,
   output o_Segment2_D,
   output o_Segment2_E,
   output o_Segment2_F,
   output o_Segment2_G
   ); 
   
  wire w_RX_DV;
  wire [7:0] w_RX_Byte;
  wire w_TX_Active, w_TX_Serial;
    
  wire o_ready;
  wire o_valid;
  wire [7:0] outputData;
  
  // 25,000,000 / 115,200 = 217
  uart_rx #(.CLKS_PER_BIT(217)) UART_RX_Inst
  (.i_Clock(i_Clk),
   .i_Rx_Serial(i_UART_RX),
   .o_Rx_DV(w_RX_DV),
   .o_Rx_Byte(w_RX_Byte));

  state_machine st(.i_clock(i_Clk),.i_ready(w_RX_DV),.i_inputData(w_RX_Byte),.o_ready(o_ready),.o_outputData(outputData),.o_valid(o_valid));
  
  uart_tx #(.CLKS_PER_BIT(217)) UART_TX_Inst
  (.i_Clock(i_Clk),
   .i_Tx_DV(o_ready),      
   .i_Tx_Byte(outputData),  
   .o_Tx_Active(w_TX_Active),
   .o_Tx_Serial(w_TX_Serial),
   .o_Tx_Done());
   
  // Drive UART line high when transmitter is not active
  assign o_UART_TX = w_TX_Active ? w_TX_Serial : 1'b1; 
      
  hex_to_7seg upper_digit
  (.i_Clk(i_Clk),
   .i_Value(outputData[7:4]),
   .o_Segment_A(o_Segment1_A),
   .o_Segment_B(o_Segment1_B),
   .o_Segment_C(o_Segment1_C),
   .o_Segment_D(o_Segment1_D),
   .o_Segment_E(o_Segment1_E),
   .o_Segment_F(o_Segment1_F),
   .o_Segment_G(o_Segment1_G));
    
  hex_to_7seg lower_digit
  (.i_Clk(i_Clk),
   .i_Value(outputData[3:0]),
   .o_Segment_A(o_Segment2_A),
   .o_Segment_B(o_Segment2_B),
   .o_Segment_C(o_Segment2_C),
   .o_Segment_D(o_Segment2_D),
   .o_Segment_E(o_Segment2_E),
   .o_Segment_F(o_Segment2_F),
   .o_Segment_G(o_Segment2_G));
       
  assign o_LED_1 = 1'b0;
  assign o_LED_2 = 1'b0;
  assign o_LED_3 = o_valid;
  assign o_LED_4 = 1'b0;
endmodule
module test();
	reg i_ready = 0;
	reg [7:0] inputData;
	reg r_Clock = 0;
	wire o_ready;
	wire [7:0] outputData;
	integer i;
	
	state_machine st(.i_clock(r_Clock),.i_ready(i_ready),.i_inputData(inputData),.o_ready(o_ready),.o_outputData(outputData));
	
	always
		#(5) r_Clock <= !r_Clock;
 
	always @(posedge o_ready)
	begin
		$display("data is [%c]",outputData);
	end

    initial
	begin
		$dumpfile("enigma.vcd");
		$dumpvars(0,test);
		inputData = "A";
		for (i = 0; i < 20; i = i + 1) 		
		begin
			#10
			i_ready = 1;
			#30
			i_ready = 0;
		end
		#260
		$finish;
	end
endmodule
module rotorEncode #(parameter REVERSE = 0) (code, rotor_type, val);
	input [4:0] code; 
	output reg [4:0] val;
	input [2:0] rotor_type;
	
    parameter MEM_INIT_FILE = "rotors.mem";

    reg [4:0] rotor_data[0:415];

    initial
		if (MEM_INIT_FILE != "")
			$readmemh(MEM_INIT_FILE, rotor_data);
   
	always @*
		val = rotor_data[((REVERSE) ? 208 : 0) + rotor_type*26 + code];
endmodule
module hex_to_7seg 
  (
   input       i_Clk,
   input [3:0] i_Value,
   output      o_Segment_A,
   output      o_Segment_B,
   output      o_Segment_C,
   output      o_Segment_D,
   output      o_Segment_E,
   output      o_Segment_F,
   output      o_Segment_G
   );
 
  reg [6:0]    out = 7'b0000000;
   
  always @(posedge i_Clk)
    begin
      case (i_Value)
        4'b0000 : out <= 7'b0000001;
        4'b0001 : out <= 7'b1001111;
        4'b0010 : out <= 7'b0010010;
        4'b0011 : out <= 7'b0000110;
        4'b0100 : out <= 7'b1001100;          
        4'b0101 : out <= 7'b0100100;
        4'b0110 : out <= 7'b0100000;
        4'b0111 : out <= 7'b0001111;
        4'b1000 : out <= 7'b0000000;
        4'b1001 : out <= 7'b0000100;
        4'b1010 : out <= 7'b0001000;
        4'b1011 : out <= 7'b1100000;
        4'b1100 : out <= 7'b0110001;
        4'b1101 : out <= 7'b1000010;
        4'b1110 : out <= 7'b0110000;
        4'b1111 : out <= 7'b0111000;
      endcase
    end 
 
  assign o_Segment_A = out[6];
  assign o_Segment_B = out[5];
  assign o_Segment_C = out[4];
  assign o_Segment_D = out[3];
  assign o_Segment_E = out[2];
  assign o_Segment_F = out[1];
  assign o_Segment_G = out[0];
 
endmodule
module decodeASCII(code, ascii);
	input [4:0] code; 
	output [7:0] ascii;

	assign ascii = 8'h41 + code;	
endmodule
module encodeASCII(ascii, code, valid);
	input [7:0] ascii; 
	output [4:0] code;
	output valid;

	assign valid = ((ascii < 8'h41 || ascii > 8'h5A) && (ascii < 8'h61 || ascii > 8'h7A)) ? 0 : 1;
	assign code = (ascii > 8'h5A) ? ascii - 8'h61 : ascii - 8'h41;	
endmodule
module rotor (
	input clock,
	output reg [4:0] rotor1,
	output reg [4:0] rotor2,
	output reg [4:0] rotor3,
	input reset,
	input rotate,
    input [2:0] rotor_type_2,
    input [2:0] rotor_type_3,
    input [4:0] rotor_start_1,
    input [4:0] rotor_start_2,
    input [4:0] rotor_start_3
);

	wire knock1;
	wire knock2;

	reg prev_rotate = 1'b0;
	reg prev_knock1 = 1'b0;
	reg prev_knock2 = 1'b0;
	
	checkKnockpoints checker3(.position(rotor3), .knockpoint(knock1), .rotor_type(rotor_type_3));
	checkKnockpoints checker2(.position(rotor2), .knockpoint(knock2), .rotor_type(rotor_type_2));

	
	always @(posedge clock)
	begin
		if (reset) 
		begin
			rotor1 <= rotor_start_1;
			rotor2 <= rotor_start_2;
			rotor3 <= rotor_start_3;
			prev_rotate <= 0;
			prev_knock1 <= 0;
			prev_knock2 <= 0;

		end
		else
		begin
			if ((prev_rotate==0) && (rotate==1)) rotor3 <= (rotor3 == 25) ? 0 : rotor3 + 1;
			if ((prev_knock1==0) && (knock1==1)) rotor2 <= (rotor2 == 25) ? 0 : rotor2 + 1;
			if ((prev_knock2==0) && (knock2==1)) rotor1 <= (rotor1 == 25) ? 0 : rotor1 + 1;			
			prev_rotate <= rotate;
			prev_knock1 <= knock1;
			prev_knock2 <= knock2;
		end
	end
endmodule
module reflectorEncode (code, val, reflector_type);
	input [4:0] code; 
	output reg [4:0] val;
	input reflector_type;

    always @*
    begin
	  if (reflector_type == 1'b0)
	  begin
		  // Reflector B
		  case (code)
			0 : val = "Y" - 8'h41;
			1 : val = "R" - 8'h41;
			2 : val = "U" - 8'h41;
			3 : val = "H" - 8'h41;
			4 : val = "Q" - 8'h41;
			5 : val = "S" - 8'h41;
			6 : val = "L" - 8'h41;
			7 : val = "D" - 8'h41;
			8 : val = "P" - 8'h41;
			9 : val = "X" - 8'h41;
			10: val = "N" - 8'h41;
			11: val = "G" - 8'h41;
			12: val = "O" - 8'h41;
			13: val = "K" - 8'h41;
			14: val = "M" - 8'h41;
			15: val = "I" - 8'h41;
			16: val = "E" - 8'h41;
			17: val = "B" - 8'h41;
			18: val = "F" - 8'h41;
			19: val = "Z" - 8'h41;
			20: val = "C" - 8'h41;
			21: val = "W" - 8'h41;
			22: val = "V" - 8'h41;
			23: val = "J" - 8'h41;
			24: val = "A" - 8'h41;
			25: val = "T" - 8'h41;		
		  endcase
	  end
	  else
	  begin
		// Reflector C
	  	case (code)
			0 : val = "F" - 8'h41;
			1 : val = "V" - 8'h41;
			2 : val = "P" - 8'h41;
			3 : val = "J" - 8'h41;
			4 : val = "I" - 8'h41;
			5 : val = "A" - 8'h41;
			6 : val = "O" - 8'h41;
			7 : val = "Y" - 8'h41;
			8 : val = "E" - 8'h41;
			9 : val = "D" - 8'h41;
			10: val = "R" - 8'h41;
			11: val = "Z" - 8'h41;
			12: val = "X" - 8'h41;
			13: val = "W" - 8'h41;
			14: val = "G" - 8'h41;
			15: val = "C" - 8'h41;
			16: val = "T" - 8'h41;
			17: val = "K" - 8'h41;
			18: val = "U" - 8'h41;
			19: val = "Q" - 8'h41;
			20: val = "S" - 8'h41;
			21: val = "B" - 8'h41;
			22: val = "N" - 8'h41;
			23: val = "M" - 8'h41;
			24: val = "H" - 8'h41;
			25: val = "L" - 8'h41;		
		  endcase
	  end
    end 
endmodule
module plugboardEncode(input [4:0] code, output [4:0] val);	
	assign val = code;
endmodule
module checkKnockpoints (position, knockpoint, rotor_type);
	input [4:0] position;
	output reg knockpoint;
	input [2:0] rotor_type;

	always @*
	begin
		knockpoint = 0;
		case(rotor_type)
			0 : if (position==16+1) knockpoint = 1;
			1 : if (position== 4+1) knockpoint = 1;
			2 : if (position==21+1) knockpoint = 1;
			3 : if (position== 9+1) knockpoint = 1;
			//4 : if (position==25+1) knockpoint = 1;
			4 : if (position==0)    knockpoint = 1;
			5 : if (position==12+1) knockpoint = 1; else if(position==0) knockpoint = 1; 
			6 : if (position==12+1) knockpoint = 1; else if(position==0) knockpoint = 1;
			7 : if (position==12+1) knockpoint = 1; else if(position==0) knockpoint = 1;
		endcase
	end
endmodule
module calculate_val #(
	parameter INPUT = 1
) (
	input [4:0] value,
	input [4:0] rotor,
	output reg [4:0] out,
	input [4:0] ring_position
);
	reg signed [6:0] val = 7'b0000000;

	always @* 
	begin		
		if (INPUT==1)
			val = value - ring_position + rotor;
		else
			val = value + ring_position - rotor;

		if (val < 0    ) val = val + 7'd26;
		if (val > 7'd25) val = val - 7'd26;
		out = val[4:0];
	end
endmodule
module encode #(
	parameter REVERSE = 0
) (
	input [4:0] inputValue,
	input [4:0] rotor,
	output [4:0] outputValue,
	input [2:0] rotor_type,
	input [4:0] ring_position
);
	wire [4:0] calculated_input;
	wire [4:0] outval;
	
	calculate_val #(.INPUT(1)) cinput(.value(inputValue),.rotor(rotor),.out(calculated_input),.ring_position(ring_position));
	
	rotorEncode #(.REVERSE(REVERSE)) rotEncode(.code(calculated_input),.val(outval),.rotor_type(rotor_type));
	
	calculate_val #(.INPUT(0)) coutput(.value(outval),.rotor(rotor),.out(outputValue),.ring_position(ring_position));
endmodule
module debounce(input clk, input i, output o); 
        reg unsigned [23:0] c;
        reg out_temp;
        
        always @(posedge clk)begin
            if(i == 1)begin
                if(c==24'hFFFFFF)begin
                    out_temp <= 1'b1;           
                end
                else begin
                    out_temp <= 1'b0;
                end
                c <= c+1'b1;
            end
            else begin
                c <= {24{1'b0}};
                out_temp <= 1'b0; 
            end
        end
        assign o = out_temp;
endmodule
module ov7670_registers_verilog(input clk, input resend, input advance, output [15:0] command, output finished);

    reg [15:0] sreg;
    reg finished_temp;
    reg [7:0] address = {8{1'b0}};
    
    assign command = sreg; 
    assign finished = finished_temp;
    
    always@(sreg)
    begin
        if(sreg == 16'b1111111111111111)
            begin
                finished_temp <= 1;
            end
        else
            begin
                finished_temp <= 0;
            end
    end
    
    always@(posedge clk)
        begin
            if(resend == 1)
                begin
                    address <= {8{1'b0}};
                end
            else if(advance == 1)
                begin
                    address <= address+1;
                end
           case (address) 
                0 : sreg <= 4'h1280; 
                1 : sreg <= 4'h1280; 
                2 : sreg <= 4'h1204; 
                3 : sreg <= 4'h1100; 
                4 : sreg <= 4'h0C00; 
                5 : sreg <= 4'h3E00; 
                6 : sreg <= 4'h8C00; 
                7 : sreg <= 4'h0400; 
                8 : sreg <= 4'h4010; 
                9 : sreg <= 4'h3A04; 
                10 : sreg <= 4'h1438; 
                11 : sreg <= 4'h4FB3; 
                12 : sreg <= 4'h50B3; 
                13 : sreg <= 4'h5100; 
                14 : sreg <= 4'h523D; 
                15 : sreg <= 4'h53A7; 
                16 : sreg <= 4'h54E4; 
                17 : sreg <= 4'h589E; 
                18 : sreg <= 4'h3DC0; 
                19 : sreg <= 4'h1100; 
                20 : sreg <= 4'h1711; 
                21 : sreg <= 4'h1861; 
                22 : sreg <= 4'h32A4; 
                23 : sreg <= 4'h1903; 
                24 : sreg <= 4'h1A7B; 
                25 : sreg <= 4'h030A; 
                26 : sreg <= 4'h0E61; 
                27 : sreg <= 4'h0F4B; 
                28 : sreg <= 4'h1602; 
                29 : sreg <= 4'h1E37; 
                30 : sreg <= 4'h2102; 
                31 : sreg <= 4'h2291; 
                32 : sreg <= 4'h2907; 
                33 : sreg <= 4'h330B; 
                34 : sreg <= 4'h350B; 
                35 : sreg <= 4'h371B; 
                36 : sreg <= 4'h3871; 
                37 : sreg <= 4'h392A; 
                38 : sreg <= 4'h3C78; 
                39 : sreg <= 4'h4D40; 
                39 : sreg <= 4'h4D40; 
                40 : sreg <= 4'h4E20; 
                41 : sreg <= 4'h6900; 
                42 : sreg <= 4'h7410; 
                43 : sreg <= 4'h7410; 
                44 : sreg <= 4'h8D4F; 
                45 : sreg <= 4'h8E00; 
                46 : sreg <= 4'h8F00; 
                47 : sreg <= 4'h9000; 
                48 : sreg <= 4'h9100; 
                49 : sreg <= 4'h9600; 
                50 : sreg <= 4'h9A00; 
                51 : sreg <= 4'hB084; 
                52 : sreg <= 4'hB10C; 
                53 : sreg <= 4'hB20E; 
                54 : sreg <= 4'hB382; 
                55 : sreg <= 4'hB80A; 
                default : sreg <= 4'hFFFF;
            endcase  
            
        end
endmodule
module vga(input clk25,
	       output [3:0] vga_red,
	       output [3:0] vga_green,
           output [3:0] vga_blue,
           output vga_hsync,
           output vga_vsync,
           output [18:0] frame_addr,
           input [11:0] frame_pixel); 
	
	
	
	parameter hRez = 640;
	parameter hStartSync = 640+16;
	parameter hEndSync = 640+16+96;
	parameter hMaxCount = 800;

	parameter vRez = 480;
	parameter vStartSync = 480+10;
	parameter vEndSync = 480+10+2;
	parameter vMaxCount = 480+10+2+33;

	parameter hsync_active = 0;
	parameter vsync_active = 0;
	
	reg unsigned [9:0] hCounter = {10{1'b0}};
	reg unsigned [9:0] vCounter = {10{1'b0}};
	reg unsigned [18:0] address = {19{1'b0}};
	reg unsigned [18:0] address_temp = {19{1'b0}};
	reg blank = 1;
	
	reg [3:0] vga_red_temp;
	reg [3:0] vga_blue_temp;
	reg [3:0] vga_green_temp;
	reg vga_hsync_temp;
	reg vga_vsync_temp;
	
        
	always @(posedge clk25)
		begin
			if (hCounter == hMaxCount-1)
				begin
					hCounter <= {10{1'b0}};
					if(vCounter == vMaxCount-1)
						begin
							vCounter <= {10{1'b0}};
						end
                    else 
                        begin
                            vCounter <= vCounter+1;
                        end
				end
			else 
				begin
					hCounter <= hCounter+1;
				end	
			
			
			
			if(blank == 0)
				begin
					vga_red_temp   <= frame_pixel[11:8];
					vga_green_temp <= frame_pixel[7:4];
					vga_blue_temp  <= frame_pixel[3:0];
				end
			else
				begin
					vga_red_temp   <= {4{1'b0}};
					vga_green_temp <= {4{1'b0}};
					vga_blue_temp <= {4{1'b0}};
				end
			
			
			
			if(vCounter >= vRez)
				begin
					address <= {19{1'b0}};
					blank <= 1;
				end
			else
				begin
					if(hCounter < 640)
						begin
							blank <= 0;
							address <= address+1'b1;
						end
					else
						begin
							blank <= 1;
						end
				end
			
			
			if(hCounter > hStartSync && hCounter <= hEndSync)
				begin
					vga_hsync_temp <= hsync_active;
				end
			else
				begin
					vga_hsync_temp <= !hsync_active;
				end
				
			
			if(vCounter >= vStartSync && vCounter < vEndSync)
				begin
					vga_vsync_temp <= vsync_active;
				end
			else
				begin
					vga_vsync_temp <= !vsync_active;
				end
			
		end
	
	assign frame_addr = address;
	assign vga_red = vga_red_temp;
	assign vga_blue = vga_blue_temp;
	assign vga_green = vga_green_temp;
	assign vga_hsync = vga_hsync_temp;
	assign vga_vsync = vga_vsync_temp;
	
	
endmodule
module ov7670_controller_verilog(input clk, input resend, output config_finished, output sioc, inout siod, output reset, output pwdn, output xclk);

    reg sys_clk = 0;
    wire [15:0] command;
    wire finished = 0;
    wire taken = 0;
    reg send;
    reg [7:0] camera_address = 2'h42;
    
    assign config_finished = finished;
    
    
    assign reset = 1;
    assign pwdn = 0;
    assign xclk = sys_clk;
    
    always@(finished)
        begin
            send = ~finished;
        end
    always@(posedge clk)
        begin
            sys_clk = ~sys_clk;
        end
    
    ov7670_registers_verilog orv(.clk(clk),.advance(taken), .command(command), .finished(finished), .resend(resend));
    i2c_sender_verilog isv(.clk(clk), .taken(taken), .siod(siod), .sioc(sioc), .send(send), .id(camera_address), .rega(command[15:8]), .value(command[7:0]));
endmodule
module ov7670_capture_verilog(input pclk,
                              input vsync,
                              input href,
                              input [7:0] d,
                              output [18:0] addr,
                              output [11:0] dout,
                              output we);
                              
    reg [15:0] d_latch = {16{1'b0}};
    reg [18:0] address = {19{1'b0}};
    reg  unsigned [18:0] address_next = {19{1'b0}};
    reg [1:0] wr_hold = {2{1'b0}};
    
    reg [11:0] dout_temp;
    reg we_temp;
    
    assign addr = address;
    assign dout = dout_temp;
    assign we = we_temp;
    
    always@ (posedge pclk)
        begin
            if(vsync == 1)
                begin
                    address <= {19{1'b0}};
                    address_next <= {19{1'b0}};
                    wr_hold <= {2{1'b0}};
                end
            else
                begin
                    dout_temp <= {d_latch[15:12],d_latch[10:7],d_latch[4:1]};
                    address <= address_next;
                    we_temp <= wr_hold[1];
                    wr_hold <= {wr_hold[0], (href && !wr_hold[0])};
                    d_latch <= {d_latch [7:0], d};
                    
                    if(wr_hold[1] == 1)
                        begin
                            address_next <= address_next+1;
                        end
                end
        end
        
endmodule
module clocking_verilog(input clk_in, output clk_out);

    wire clk_in;
    reg clk_out;
 
    always @ (posedge clk_in)
        begin
            clk_out <= !clk_out ; 
        end
endmodule
module OV7670_top_verilog(input clk100, output OV7670_SIOC, inout OV7670_SIOD, output OV7670_RESET,
                          output OV7670_PWDN, input OV7670_VSYNC, input OV7670_HREF, input OV7670_PCLK,
                          output OV7670_XCLK, input [7:0] OV7670_D, output [7:0] LED, output [3:0] vga_red,
                          output [3:0] vga_green, output [3:0] vga_blue, output vga_hsync, output vga_vsync, input btn);
                          
    wire [18:0] frame_addr;
    wire [11:0] frame_pixel;
    wire [18:0] capture_addr;
    wire [11:0] capture_data;
    wire capture_we;
    wire resend;
    wire config_finished;
    
    reg clk_feedback;
    reg clk50u;
    wire clk50;
    reg clk25u;
    wire clk25;
    reg buffered_pclk;
    
    assign LED = 8'b00000000 & config_finished;
                          
    debounce db1(.clk(clk50),.i(btn),.o(resend));
    vga vg1(.clk25(clk25),.vga_red(vga_red),.vga_green(vga_green),.vga_blue(vga_blue),.vga_hsync(vga_hsync),.vga_vsync(vga_vsync),.frame_addr(frame_addr),.frame_pixel(frame_pixel));
    frame_buffer fb1(.clka(OV7670_PCLK),.wea(capture_we),.addra(capture_addr),.dina(capture_data),.clkb(clk50),.addrb(frame_addr),.doutb(frame_pixel));
    ov7670_capture_verilog cap1(.pclk(OV7670_PCLK),.vsync(OV7670_VSYNC),.href(OV7670_HREF),.d(OV7670_D),.addr(capture_addr),.dout(capture_data),.we(capture_we));
    ov7670_controller_verilog con1(.clk(clk50),.sioc(OV7670_SIOC),.resend(resend),.config_finished(config_finished),.siod(OV7670_SIOD),.pwdn(OV7670_PWDN),.reset(OV7670_RESET),.xclk(OV7670_XCLK));
    
    clocking_verilog clk1(.clk_in(clk100),.clk_out(clk50));
    clocking_verilog clk2(.clk_in(clk50),.clk_out(clk25));
    
endmodule
module usbserial_tbx (
        input  pin_clk,

        inout  pin_usb_p,
        inout  pin_usb_n,
        output pin_pu,

        output pin_led,

        output [3:0] debug
    );

    wire clk_48mhz;

    wire clk_locked;

    // Use an icepll generated pll
    pll pll48( .clock_in(pin_clk), .clock_out(clk_48mhz), .locked( clk_locked ) );

    // LED
    reg [22:0] ledCounter;
    always @(posedge clk_48mhz) begin
        ledCounter <= ledCounter + 1;
    end
    assign pin_led = ledCounter[ 22 ];

    // Generate reset signal
    reg [5:0] reset_cnt = 0;
    wire reset = ~reset_cnt[5];
    always @(posedge clk_48mhz)
        if ( clk_locked )
            reset_cnt <= reset_cnt + reset;

    // uart pipeline in
    wire [7:0] uart_in_data;
    wire       uart_in_valid;
    wire       uart_in_ready;

    // assign debug = { uart_in_valid, uart_in_ready, reset, clk_48mhz };

    wire usb_p_tx;
    wire usb_n_tx;
    wire usb_p_rx;
    wire usb_n_rx;
    wire usb_tx_en;

    // usb uart - this instanciates the entire USB device.
    usb_uart uart (
        .clk_48mhz  (clk_48mhz),
        .reset      (reset),

        // pins
        .pin_usb_p( pin_usb_p ),
        .pin_usb_n( pin_usb_n ),

        // uart pipeline in
        .uart_in_data( uart_in_data ),
        .uart_in_valid( uart_in_valid ),
        .uart_in_ready( uart_in_ready ),

        .uart_out_data( uart_in_data ),
        .uart_out_valid( uart_in_valid ),
        .uart_out_ready( uart_in_ready  )

        //.debug( debug )
    );

    // USB Host Detect Pull Up
    assign pin_pu = 1'b1;

endmodule
module MUXF7_L
(
    input  wire I0, I1,
    input  wire S,
    output wire LO
);

    assign LO = (S) ? I1 : I0;

endmodule
module LUT6_D
#(
    parameter [63:0] INIT = 64'h0000000000000000
)
(
    input  wire I0, I1, I2, I3, I4, I5,
    output wire LO,
    output wire O
);
    wire [5:0] _w_idx = { I5, I4, I3, I2, I1, I0 };
    
    assign LO = INIT[_w_idx];
    assign O  = INIT[_w_idx];

endmodule
module SRLC16E
#(
    parameter [15:0] INIT = 16'h0,
    parameter  [0:0] IS_CLK_INVERTED = 1'b0
)
(
    // Clock
    input  wire       CLK,
    // Clock enable
    input  wire       CE,
    // Bit output position
    input  wire       A0, A1, A2, A3,
    // Data in
    input  wire       D,
    // Data out
    output wire       Q,
    // Cascading data out
    output wire       Q15
);

    // 32-bit shift register
    reg  [15:0] _r_srl;
    
    // Bit position
    wire  [3:0] _w_addr = { A3, A2, A1, A0 };
    
    // Power-up value
    initial begin
        _r_srl = INIT;
    end
    
    // Shifter logic
    generate
        if (IS_CLK_INVERTED) begin : GEN_CLK_NEG
            always @(negedge CLK) begin : SHIFTER_16B
            
                if (CE) begin
                    _r_srl <= { _r_srl[14:0], D };
                end
            end
        end
        else begin : GEN_CLK_POS
            always @(posedge CLK) begin : SHIFTER_16B
            
                if (CE) begin
                    _r_srl <= { _r_srl[14:0], D };
                end
            end
        end
    endgenerate
    
    // Data out
    assign Q   = _r_srl[_w_addr];
    
    // Cascading data out
    assign Q15 = _r_srl[15];
    
endmodule
module FDCE
#(
    parameter [0:0] IS_C_INVERTED   = 1'b0,
    parameter [0:0] IS_D_INVERTED   = 1'b0,
    parameter [0:0] IS_CLR_INVERTED = 1'b0,
    parameter [0:0] INIT            = 1'b0
)
(
    // Clock
    input  wire C,
    // Clock enable
    input  wire CE,
    // Asynchronous clear
    input  wire CLR,
    // Data in
    input  wire D,
    // Data out
    output wire Q
);
    reg    _r_Q;
    
    wire   _w_CLR = CLR ^ IS_CLR_INVERTED;
    wire   _w_D   = D   ^ IS_D_INVERTED;
    
    initial begin : INIT_STATE
        _r_Q = INIT[0];
    end

    generate
        if (IS_C_INVERTED) begin : GEN_CLK_NEG
            always @(negedge C or posedge _w_CLR) begin
            
                if (_w_CLR) begin
                    _r_Q <= 1'b0;
                end
                else if (CE) begin
                    _r_Q <= _w_D;
                end
            end
        end
        else begin : GEN_CLK_POS
            always @(posedge C or posedge _w_CLR) begin
            
                if (_w_CLR) begin
                    _r_Q <= 1'b0;
                end
                else if (CE) begin
                    _r_Q <= _w_D;
                end
            end
        end
    endgenerate
    
    assign Q = _r_Q;

endmodule
module LUT2
#(
    parameter [3:0] INIT = 4'b0000
)
(
    input  wire I0, I1,
    output wire O
);
    wire [1:0] _w_idx = { I1, I0 };

    assign O = INIT[_w_idx];

endmodule
module MUXF7
(
    input  wire I0, I1,
    input  wire S,
    output wire O
);

    assign O = (S) ? I1 : I0;

endmodule
module RAM32X1S
#(
    parameter [31:0] INIT = 32'h0,
    parameter  [0:0] IS_WCLK_INVERTED = 1'b0
)
(
    // Write clock
    input  wire       WCLK,
    // Write enable
    input  wire       WE,
    // Read / Write address
    input  wire       A0,
    input  wire       A1,
    input  wire       A2,
    input  wire       A3,
    input  wire       A4,
    // Data in
    input  wire       D,
    // Data out
    output wire       O
);
    // Read / Write address
    wire  [4:0] _w_A = { A4, A3, A2, A1, A0 };
    // 32 x 1-bit Select RAM
    reg  [31:0] _r_mem;
    
    // Power-up value
    initial begin : INIT_STATE
        _r_mem = INIT;
    end
    
    // Synchronous memory write
    generate
        if (IS_WCLK_INVERTED) begin : GEN_WCLK_NEG
            always @(negedge WCLK) begin : MEM_WRITE
            
                if (WE) begin
                    _r_mem[_w_A] <= D;
                end
            end
        end
        else begin : GEN_WCLK_POS
            always @(posedge WCLK) begin : MEM_WRITE
            
                if (WE) begin
                    _r_mem[_w_A] <= D;
                end
            end
        end
    endgenerate
    
    // Asynchronous memory read
    assign O = _r_mem[_w_A];

endmodule