dakies/OSS_Verilog huggingface dataset:
module uart(
   input wire clk,
   input wire resetq,

   output wire uart_busy,       // High means UART is transmitting
   output reg uart_tx,          // UART transmit wire

   input wire uart_wr_i,        // Raise to transmit byte
   input wire [7:0] uart_dat_i
);
  reg [3:0] bitcount;           // 0 means idle, so this is a 1-based counter
  reg [8:0] shifter;

  assign uart_busy = |bitcount;
  wire sending = |bitcount;

  wire ser_clk;

  baudgen _baudgen(
    .clk(clk),
    .ser_clk(ser_clk));

  always @(negedge resetq or posedge clk)
  begin
    if (!resetq) begin
      uart_tx <= 1;
      bitcount <= 0;
      shifter <= 0;
    end else begin
      if (uart_wr_i) begin
        { shifter, uart_tx } <= { uart_dat_i[7:0], 1'b0, 1'b1 };
        bitcount <= 1 + 8 + 1;    // 1 start, 8 data, 1 stop
      end else if (ser_clk & sending) begin
        { shifter, uart_tx } <= { 1'b1, shifter };
        bitcount <= bitcount - 4'd1;
      end
    end
  end

endmodule
module rxuart(
   input wire clk,
   input wire resetq,
   input wire uart_rx,      // UART recv wire
   input wire rd,           // read strobe
   output wire valid,       // has data 
   output wire [7:0] data); // data
  reg [4:0] bitcount;
  reg [7:0] shifter;

  // bitcount == 11111: idle
  //             0-17:  sampling incoming bits
  //             18:    character received

  // On starting edge, wait 3 half-bits then sample, and sample every 2 bits thereafter

  wire idle = &bitcount;
  assign valid = (bitcount == 18);

  wire sample;
  reg [2:0] hh = 3'b111;
  wire [2:0] hhN = {hh[1:0], uart_rx};
  wire startbit = idle & (hhN[2:1] == 2'b10);
  wire [7:0] shifterN = sample ? {hh[1], shifter[7:1]} : shifter;

  wire ser_clk;

  baudgen2 _baudgen(
    .clk(clk),
    .restart(startbit),
    .ser_clk(ser_clk));

  reg [4:0] bitcountN;
  always @*
    if (startbit)
      bitcountN = 0;
    else if (!idle & !valid & ser_clk)
      bitcountN = bitcount + 5'd1;
    else if (valid & rd)
      bitcountN = 5'b11111;
    else
      bitcountN = bitcount;

  // 3,5,7,9,11,13,15,17
  assign sample = (|bitcount[4:1]) & bitcount[0] & ser_clk;
  assign data = shifter;

  always @(negedge resetq or posedge clk)
  begin
    if (!resetq) begin
      hh <= 3'b111;
      bitcount <= 5'b11111;
      shifter <= 0;
    end else begin
      hh <= hhN;
      bitcount <= bitcountN;
      shifter <= shifterN;
    end
  end
endmodule
module buart(
   input wire clk,
   input wire resetq,
   input wire rx,           // recv wire
   output wire tx,          // xmit wire
   input wire rd,           // read strobe
   input wire wr,           // write strobe
   output wire valid,       // has recv data 
   output wire busy,        // is transmitting
   input wire [7:0] tx_data,
   output wire [7:0] rx_data // data
);
  rxuart _rx (
     .clk(clk),
     .resetq(resetq),
     .uart_rx(rx),
     .rd(rd),
     .valid(valid),
     .data(rx_data));
  uart _tx (
     .clk(clk),
     .resetq(resetq),
     .uart_busy(busy),
     .uart_tx(tx),
     .uart_wr_i(wr),
     .uart_dat_i(tx_data));
endmodule
module inpin(
  input clk,
  input pin,
  output rd);

  SB_IO #(.PIN_TYPE(6'b0000_00)) _io (
        .PACKAGE_PIN(pin),
        .INPUT_CLK(clk),
        .D_IN_0(rd));
endmodule
module outpin(
  input clk,
  output pin,
  input we,
  input wd,
  output rd);

  SB_IO #(.PIN_TYPE(6'b0101_01)) _io (
        .PACKAGE_PIN(pin),
        .CLOCK_ENABLE(we),
        .OUTPUT_CLK(clk),
        .D_OUT_0(wd),
        .D_IN_0(rd));
endmodule
module vga_fifo_dc (rclk, wclk, rclr, wclr, wreq, d, rreq, q, empty, full);

	// parameters
	parameter AWIDTH = 7;  //128 entries
	parameter DWIDTH = 16; //16bit databus

	// inputs & outputs
	input rclk;             // read clock
	input wclk;             // write clock
	input rclr;             // active high synchronous clear, synchronous to read clock
	input wclr;             // active high synchronous clear, synchronous to write clock
	input wreq;             // write request
	input [DWIDTH -1:0] d;  // data input
	input rreq;             // read request
	output [DWIDTH -1:0] q; // data output

	output empty;           // FIFO is empty, synchronous to read clock
	reg empty;
	output full;            // FIFO is full, synchronous to write clock
	reg full;

	// variable declarations
	reg rrst, wrst, srclr, ssrclr, swclr, sswclr;
	reg [AWIDTH -1:0] rptr, wptr, rptr_gray, wptr_gray;

	//
	// module body
	//


	function [AWIDTH:1] bin2gray;
		input [AWIDTH:1] bin;
		integer n;
	begin
		for (n=1; n<AWIDTH; n=n+1)
			bin2gray[n] = bin[n+1] ^ bin[n];

		bin2gray[AWIDTH] = bin[AWIDTH];
	end
	endfunction

	function [AWIDTH:1] gray2bin;
		input [AWIDTH:1] gray;
	begin
		// same logic as bin2gray
		gray2bin = bin2gray(gray);
	end
	endfunction

	//
	// Pointers
	//

	// generate synchronized resets
	always @(posedge rclk)
	begin
	    swclr  <= #1 wclr;
	    sswclr <= #1 swclr;
	    rrst   <= #1 rclr | sswclr;
	end

	always @(posedge wclk)
	begin
	    srclr  <= #1 rclr;
	    ssrclr <= #1 srclr;
	    wrst   <= #1 wclr | ssrclr;
	end


	// read pointer
	always @(posedge rclk)
	  if (rrst) begin
	      rptr      <= #1 0;
	      rptr_gray <= #1 0;
	  end else if (rreq) begin
	      rptr      <= #1 rptr +1'h1;
	      rptr_gray <= #1 bin2gray(rptr +1'h1);
	  end

	// write pointer
	always @(posedge wclk)
	  if (wrst) begin
	      wptr      <= #1 0;
	      wptr_gray <= #1 0;
	  end else if (wreq) begin
	      wptr      <= #1 wptr +1'h1;
	      wptr_gray <= #1 bin2gray(wptr +1'h1);
	  end

	//
	// status flags
	//
	reg [AWIDTH-1:0] srptr_gray, ssrptr_gray;
	reg [AWIDTH-1:0] swptr_gray, sswptr_gray;

	// from one clock domain, to the other
	always @(posedge rclk)
	begin
	    swptr_gray  <= #1 wptr_gray;
	    sswptr_gray <= #1 swptr_gray;
	end

	always @(posedge wclk)
	begin
	    srptr_gray  <= #1 rptr_gray;
	    ssrptr_gray <= #1 srptr_gray;
	end

	// EMPTY
	// WC: wptr did not increase
	always @(posedge rclk)
	  if (rrst)
	    empty <= #1 1'b1;
	  else if (rreq)
	    empty <= #1 bin2gray(rptr +1'h1) == sswptr_gray;
	  else
	    empty <= #1 empty & (rptr_gray == sswptr_gray);


	// FULL
	// WC: rptr did not increase
	always @(posedge wclk)
	  if (wrst)
	    full <= #1 1'b0;
	  else if (wreq)
	    full <= #1 bin2gray(wptr +2'h2) == ssrptr_gray;
	  else
	    full <= #1 full & (bin2gray(wptr + 2'h1) == ssrptr_gray);


	// hookup generic dual ported memory
	generic_dpram #(AWIDTH, DWIDTH) fifo_dc_mem(
		.rclk(rclk),
		.rrst(1'b0),
		.rce(1'b1),
		.oe(1'b1),
		.raddr(rptr),
		.dout(q),
		.wclk(wclk),
		.wrst(1'b0),
		.wce(1'b1),
		.we(wreq),
		.waddr(wptr),
		.di(d)
	);

endmodule
module generic_dpram(
	// Generic synchronous dual-port RAM interface
	rclk, rrst, rce, oe, raddr, dout,
	wclk, wrst, wce, we, waddr, di
);

	//
	// Default address and data buses width
	//
	parameter aw = 5;  // number of bits in address-bus
	parameter dw = 16; // number of bits in data-bus

	//
	// Generic synchronous double-port RAM interface
	//
	// read port
	input           rclk;  // read clock, rising edge trigger
	input           rrst;  // read port reset, active high
	input           rce;   // read port chip enable, active high
	input           oe;	   // output enable, active high
	input  [aw-1:0] raddr; // read address
	output [dw-1:0] dout;    // data output

	// write port
	input          wclk;  // write clock, rising edge trigger
	input          wrst;  // write port reset, active high
	input          wce;   // write port chip enable, active high
	input          we;    // write enable, active high
	input [aw-1:0] waddr; // write address
	input [dw-1:0] di;    // data input

	//
	// Module body
	//

	//
	// Instantiation synthesizeable FPGA memory
	//
	// This code has been tested using LeonardoSpectrum and Synplicity.
	// The code correctly instantiates Altera EABs and Xilinx BlockRAMs.
	//

	// NOTE:
	// 'synthesis syn_ramstyle="block_ram"' is a Synplify attribute.
	// It instructs Synplify to map to BlockRAMs instead of the default SelectRAMs

	reg [dw-1:0] mem [(1<<aw) -1:0] /* synthesis syn_ramstyle="block_ram" */;
	reg [aw-1:0] ra;                // register read address

	// read operation
	always @(posedge rclk)
	  if (rce)
	    ra <= #1 raddr;

    assign dout = mem[ra];

	// write operation
	always @(posedge wclk)
		if (we && wce)
			mem[waddr] <= #1 di;

endmodule
module smallfifo16(input rst,
		 
		   input         clk_in,
		   input [15:0]  fifo_in,
		   input         fifo_en,

		   output        fifo_full,

		   input         clk_out,
		   output [15:0] fifo_out,
		   output        fifo_empty,
		   input         fifo_rd);


   vga_fifo_dc#(.AWIDTH(4),.DWIDTH(16)) 
   fifo0(.rclk (clk_out),
         .wclk (clk_in),
         .rclr (~rst),
         .wclr (~rst),
         .wreq (fifo_en),
         .d (fifo_in),
         .rreq (fifo_rd),
         .q (fifo_out),
         .empty (fifo_empty),
         .full (fifo_full));
   
   
endmodule
module vram(input clk,
	    
	    input [19:0]     p1_addr,
	    input [7:0]      p1_data,
            output reg [7:0] p1_data_out, 
	    input            p1_we,
            input            p1_re,

	    input [19:0]     p2_addr,
	    output reg [7:0] p2_data);

   reg [7:0] 		 mem[0:153600-1];


   always @(posedge clk)
     begin
	if (p1_we) begin
	   mem[p1_addr] <= p1_data;
	end else if (p1_re) begin
           p1_data_out <= mem[p1_addr];
        end
	p2_data <= mem[p2_addr];
     end

endmodule
module vgatopgfx(input clk, // 100MHz clk
	         input        rst,
	         input        clk25mhz,

	         output       hsync,
	         output       vsync,
	         output [3:0] rgb,

                 input        clsrq,
                 output reg   clsack,

                 input        bufswap,

	         input [19:0] vmem_in_addr,
	         input [7:0]  vmem_in_data,
	         input        vmem_we,
                 input        vmem_re,
                 output [7:0] vmem_p1_out_data,

                 output       vga_scan
                 );


   wire [19:0] 		   vmem_out_addr;
   wire [7:0] 		   vmem_out_data;

   reg                     clsing;
   reg [19:0]              clsaddr;
   

   wire [19:0]             vmem_in_addr_x;
   wire [7:0]              vmem_in_data_x;
   wire                    vmem_we_x;

   reg [19:0]              vmem_in_addr_r;
   reg [7:0]               vmem_in_data_r;
   reg                     vmem_we_r;

   assign vmem_in_addr_x = clsing?clsaddr:vmem_in_addr_r;
   assign vmem_in_data_x = clsing?0:vmem_in_data_r;
   assign vmem_we_x = clsing|vmem_we_r;


   wire                    vmem_re_x;
   
   
   assign vmem_re_x = clsing?0:vmem_re;
   

   always @(posedge clk)
     if (!rst) begin
        clsing <= 0;
        clsack <= 0;
        clsaddr <= 0;
        vmem_in_addr_r <= 0;
        vmem_in_data_r <= 0;
        vmem_we_r <= 0;
     end else begin
        vmem_in_addr_r <= vmem_in_addr;
        vmem_in_data_r <= vmem_in_data;
        vmem_we_r <= vmem_we;
        if (clsack) clsack <= 0;
        else if (clsrq && !clsing) begin
           clsing <= 1;
           clsaddr <= 0;
           clsack <= 0;
        end else if (clsing) begin
           clsaddr <= clsaddr + 1;
           if (clsaddr == 153600) begin
              clsack <= 1;
              clsing <= 0;
           end
        end
     end // else: !if(!rst)

   wire buf1;
   wire buf2;

   assign buf1 = bufswap;
   assign buf2 = ~bufswap;


   wire [7:0] vmem_out_data_1;
   wire [7:0] vmem_out_data_2;

   assign vmem_out_data = buf1?vmem_out_data_1:vmem_out_data_2;
   
   wire [7:0] vmem_p1_out_data_1;
   wire [7:0] vmem_p1_out_data_2;

   assign vmem_p1_out_data = buf2?vmem_p1_out_data_1:vmem_p1_out_data_2;
   
   
   vram vram1(.clk(clk),

	      .p1_addr(vmem_in_addr_x),
	      .p1_data(vmem_in_data_x),
	      .p1_we(buf2?vmem_we_x:0),
              .p1_re(buf2?vmem_re_x:0),
              .p1_data_out(vmem_p1_out_data_1),

	      .p2_addr(vmem_out_addr),
	      .p2_data(vmem_out_data_1)
	      );

   vram vram2(.clk(clk),

	      .p1_addr(vmem_in_addr_x),
	      .p1_data(vmem_in_data_x),
	      .p1_we(buf1?vmem_we_x:0),
              .p1_re(buf2?vmem_re_x:0),
              .p1_data_out(vmem_p1_out_data_2),

	      .p2_addr(vmem_out_addr),
	      .p2_data(vmem_out_data_2)
	      );

   vgagfx vga1(.clk(clk),
	       .rst(rst),
	       .clk25mhz(clk25mhz),
	       
	       .vmem_data(vmem_out_data),
	       .vmem_addr(vmem_out_addr),
	       
	       .hsync(hsync),
	       .vsync(vsync),
	       .rgb(rgb),
               .scan(vga_scan));

endmodule
module uartmm(input clk,
              input             rst,

              input             RX,
              output            TX,
              
              output reg [31:0] data_b,
              output reg        strobe_b,
              input [31:0]      addr_b,
              input [31:0]      data_b_in,
              input [31:0]      data_b_we);

   reg [7:0]                uart_din_r;
   reg                      uart_valid_r;
   reg                      uart_ready_r;
   
   reg [7:0]                input_axis_tdata;
   reg                      input_axis_tvalid;
   wire                     input_axis_tready;
   
   
   wire [7:0]               output_axis_tdata;
   wire                     output_axis_tvalid;
   reg                      output_axis_tready;
   
   uart _uart (
               .clk(clk),
               .rst(~rst),
               
               .rxd(RX),
               .txd(TX),

               .input_axis_tdata(input_axis_tdata),
               .input_axis_tvalid(input_axis_tvalid),
               .input_axis_tready(input_axis_tready),

               .output_axis_tdata(output_axis_tdata),
               .output_axis_tvalid(output_axis_tvalid),
               .output_axis_tready(output_axis_tready),
               
               //  100MHz
               .prescale(100000000/(115200*8)));
   
   assign strobe_b_next = (addr_b == 65537) | (addr_b == 65538) | (addr_b == 65539);
   assign data_b_next = (addr_b == 65537)?uart_valid_r:
                        (addr_b == 65538)?uart_ready_r:
                        (addr_b == 65539)?uart_din_r:0;

   always @(posedge clk)
     if (~rst) begin
        uart_din_r <= 0;
        uart_valid_r <= 0;
        uart_ready_r <= 0;
        input_axis_tdata <= 0;
        input_axis_tvalid <= 0;
        output_axis_tready <= 0;
     end else begin

        data_b <= data_b_next;
        strobe_b <= strobe_b_next;
        
        if (input_axis_tvalid) begin
           input_axis_tvalid <= 0;
        end
        
        if (output_axis_tvalid & ~output_axis_tready) begin
           output_axis_tready <= 1;
        end

        uart_ready_r <= input_axis_tready; // delay

        if (output_axis_tvalid) begin
           output_axis_tready <= 0;
           uart_din_r <= output_axis_tdata;
           uart_valid_r <= 1;
        end else if ((addr_b == 65539) & ~data_b_we & uart_valid_r) begin
           uart_valid_r <= 0;
        end else if ((addr_b == 65539) & data_b_we & input_axis_tready & ~input_axis_tvalid) begin
           input_axis_tdata <= data_b[7:0];
           input_axis_tvalid <= 1;
        end
     end
   

endmodule
module ledwriter (input clk,
                  input rst,

                  output reg [15:0] LED,
                  
                  input [31:0]     addr_b,
                  input [31:0]     data_b_in,
                  input [31:0]     data_b_we);

   always @(posedge clk)
     if (~rst) begin
        LED <= 0;
     end else begin
        if (addr_b == 65540)
          LED <= data_b_in[15:0];
     end

endmodule
module socram(input clk,
              input             rst,

              output reg [31:0] data_a,
              input [31:0]      addr_a,
              
              output reg [31:0] data_b,
              output reg        strobe_b,
              input [31:0]      addr_b,
              input [31:0]      data_b_in,
              input [31:0]      data_b_we);

   parameter RAM_DEPTH = 8192 * 2;
   parameter INIT_FILE = "../../custom.hex";
   
   reg [31:0]                   mem [0:RAM_DEPTH-1];

   initial begin
      if (INIT_FILE != "")
         $readmemh(INIT_FILE, mem);
   end
    
   always @(posedge clk)
     begin
        if (data_b_we & (addr_b[31:16] == 0)) begin
           mem[addr_b] <= data_b_in;
        end
        data_a <= mem[addr_a];
        data_b <= mem[addr_b];
        strobe_b <= (addr_b[31:16] == 0);
     end

endmodule
module generic_mul ( a, b, clk, pdt);
   parameter size = 32, level = 5;
   input [size-1 : 0] a;
   input [size-1 : 0] b;
   input              clk;
   output [2*size-1 : 0] pdt;
   reg [size-1 : 0]      a_int, b_int;
   reg [2*size-1 : 0]    pdt_int [level-1 : 0];
   integer               i;
   
   assign pdt = pdt_int [level-1];
   
   always @ (posedge clk)
     begin
        a_int <= a;
        b_int <= b;
        pdt_int[0] <= a_int * b_int;
        for(i =1;i <level;i =i +1)
          pdt_int [i] <= pdt_int [i-1];
     end
endmodule
module hls_Mul(input clk,
               input reset,

               input [31:0]  p0,
               input [31:0]  p1,
               output [31:0] out);

   reg [31:0]                p0t;
   reg [31:0]                p1t;
   reg [31:0]                tmp1;
   reg [31:0]                tmp2;
   reg [31:0]                tmp3;
   reg [31:0]                tmp4;
   assign out = tmp4;

   generic_mul #(.size(32),.level(3)) mul1 (.clk(clk),
                                            .a(p0),
                                            .b(p1),
                                            .pdt(out));
endmodule
module hlsblockram (input         clk,
                    
                    input [ABITWIDTH-1:0]      readaddr1,
                    output reg [BITWIDTH-1:0] readout1,
                    input [ABITWIDTH-1:0]      writeaddr1,
                    input [BITWIDTH-1:0]      writein1,
                    input                     we
                    );
   

   parameter SIZE = 32;
   parameter BITWIDTH = 32;
   parameter ABITWIDTH = 32;
   
   reg [BITWIDTH-1:0] mem [0:SIZE-1];
 
   // Expect 2-port (1ro+1wo) to be inferred
   always @(posedge clk)
     begin
        if (we) begin
           mem[writeaddr1] = writein1;
        end
        readout1 <= mem[readaddr1];
     end

endmodule // toyblockram
module hls_Div(input clk,
               input         reset,

               input [31:0]  p0,
               input [31:0]  p1,

               output [31:0] out);

   wire                      div0, ovf;
   wire [31:0]               rem;
   
   div_pipelined2 #(.WIDTH(32)) d(.clk(clk),
                                  .rst(reset),
                                  .z(p0),
                                  .d(p1),
                                  .quot(out),
                                  .rem(rem));
endmodule
module hls_Rem(input clk,
               input         reset,

               input [31:0]  p0,
               input [31:0]  p1,

               output [31:0] out);

   wire [31:0]               quot;
   
   div_pipelined2 #(.WIDTH(32)) d(.clk(clk),
                                  .rst(reset),
                                  .z(p0),
                                  .d(p1),
                                  .quot(quot),
                                  .rem(out));

endmodule
module sevenseg(input clk100mhz,
                input [2:0]      addr,
                input [7:0]      data,
                input            we,
                output reg [7:0] seg,
                output reg [7:0] an);

   reg [7:0]                 mem[0:7];

   always @(posedge clk100mhz)
     begin
        if (we) mem[addr] <= data;
     end

   reg [15:0] counter;
   wire [2:0] caddr;
   reg [2:0]  pcaddr;

   assign caddr = counter[15:13];
   
   always @(posedge clk100mhz)
     begin
        counter <= counter + 1;
        if (caddr != pcaddr) begin
           // Common anode must be driven to low
           if (caddr == 0) an <= (255-1);
           else an <= (an << 1)|1'b1;
           seg <= ~(mem[caddr]);
           pcaddr <= caddr;
        end
     end

endmodule // sevenseg
module sevensegmm(input clk,
                  input        rst,

                  input [31:0] addr_b,
                  input [31:0] data_b_in,
                  input [31:0] data_b_we,
                  
                  output [7:0] seg,
                  output [7:0] an);

   wire [2:0]                      addr;
   wire [7:0]                      data;
   wire                            we;
   
   sevenseg s7 (.clk100mhz(clk),
                .addr(addr),
                .data(data),
                .we(we),
                .seg(seg), .an(an));

   assign we = (addr_b == 65553)?data_b_we:0;
   assign data = data_b_in[7:0];
   assign addr = data_b_in[10:8];

endmodule // sevensegmm
module vram(input clk,
	    
	    input [19:0]     p1_addr,
	    input [7:0]      p1_data,
            output [7:0] p1_data_out, 
	    input            p1_we,
            input            p1_re,

	    input [19:0]     p2_addr,
	    output [7:0] p2_data);

   reg [7:0] 		 mem[0:153600-1];
   assign p1_data_out = p1_re?mem[p1_addr]:0;
   assign p2_data = mem[p2_addr];

   always @(posedge clk)
     begin
	if (p1_we) begin
	   mem[p1_addr] <= p1_data;
	end
     end

endmodule
module vgatopgfxsim(input clk, // 100MHz clk
	            input        rst,
	           
                    input        clsrq,
                    output reg   clsack,

	            input [19:0] vmem_in_addr,
	            input [7:0]  vmem_in_data,
	            input        vmem_we,
                    input        vmem_re,
                    output [7:0] vmem_p1_out_data,

                    input [19:0] vmem_out_addr,
                    output [7:0] vmem_out_data
                    );


   reg                     clsing;
   reg [19:0]              clsaddr;
   

   wire [19:0]             vmem_in_addr_x;
   wire [7:0]              vmem_in_data_x;
   wire                    vmem_we_x;

   assign vmem_in_addr_x = clsing?clsaddr:vmem_in_addr;
   assign vmem_in_data_x = clsing?0:vmem_in_data;
   assign vmem_we_x = clsing|vmem_we;


   wire                    vmem_re_x;
   
   assign vmem_re_x = clsing?0:vmem_re;
   


   always @(posedge clk)
     if (!rst) begin
        clsing <= 0;
        clsack <= 0;
        clsaddr <= 0;
     end else begin
        if (clsack) clsack <= 0;
        else if (clsrq && !clsing) begin
           clsing <= 1;
           clsaddr <= 0;
           clsack <= 0;
        end else if (clsing) begin
           clsaddr <= clsaddr + 1;
           if (clsaddr == 153600) begin
              clsack <= 1;
              clsing <= 0;
           end
        end
     end
   
   vram vram1(.clk(clk),

	      .p1_addr(vmem_in_addr_x),
	      .p1_data(vmem_in_data_x),
	      .p1_we(vmem_we_x),
              .p1_re(vmem_re_x),
              .p1_data_out(vmem_p1_out_data),

	      .p2_addr(vmem_out_addr),
	      .p2_data(vmem_out_data)
	      );

endmodule
module uartmm(input clk,
              input            rst,


              input [7:0]      uart_din,
	      input            uart_valid,
	      output reg [7:0] uart_dout,
	      output reg       uart_wr,

              output [31:0]    data_b,
              output           strobe_b,
              input [31:0]     addr_b,
              input [31:0]     data_b_in,
              input [31:0]     data_b_we);
   
   reg [7:0]                uart_din_r;
   reg                      uart_valid_r;
   reg                      uart_ready_r;

   reg                      uart_rd;
 
   wire                     uart_busy;
   wire                     uart_ready;
   
   assign uart_ready = ~uart_busy;
   assign uart_busy = 0;

   assign strobe_b =   (addr_b == 65537) | (addr_b == 65538) | (addr_b == 65539);
   assign data_b = (addr_b == 65537)?uart_valid_r:
                   (addr_b == 65538)?uart_ready_r:
                   (addr_b == 65539)?uart_din_r:0;

   always @(posedge clk)
     if (~rst) begin
        
     end else begin
        if (uart_wr) begin
           uart_wr <= 0;
        end
        
        if (uart_valid & ~uart_rd) begin
           uart_rd <= 1; // TODO: read into a FIFO / raise an IRQ (when we had a support for them)
        end

        uart_ready_r <= uart_ready; // delay

        if (uart_rd) begin
           uart_rd <= 0;
           uart_din_r <= uart_dout;
           uart_valid_r <= 1;
        end else if ((addr_b == 65539) & ~data_b_we & uart_valid_r) begin
           uart_valid_r <= 0;
        end else if ((addr_b == 65539) & data_b_we & uart_ready & ~uart_wr) begin
           uart_dout <= data_b[7:0];
           uart_wr <= 1;
        end
     end
   
   
endmodule
module ledwriter (input clk,
                  input rst,

                  output reg [7:0] LED,
                  
                  input [31:0]     addr_b,
                  input [31:0]     data_b_in,
                  input [31:0]     data_b_we);

   always @(posedge clk)
     if (~rst) begin
        LED <= 0;
     end else begin
        if (addr_b == 65540) begin
          LED <= data_b_in[7:0];
        end
     end

endmodule // ledwriter
module vgadumper (input clk,
                  input        rst,
                  
                  output reg   vga_dump,
                  
                  input [31:0] addr_b,
                  input [31:0] data_b_in,
                  input [31:0] data_b_we);

   always @(posedge clk)
     if (~rst) begin
        vga_dump <= 0;
     end else begin
        if (vga_dump) begin
           vga_dump <= 0;
        end else if (addr_b == 65599 && data_b_we) begin
           vga_dump <= 1;
        end
     end

endmodule
module socram(input clk,
              input             rst,

              output reg [31:0] data_a,
              input [31:0]      addr_a,
              
              output reg [31:0] data_b,
              output reg        strobe_b,
              input [31:0]      addr_b,
              input [31:0]      data_b_in,
              input [31:0]      data_b_we);

   parameter RAM_DEPTH = 2048;
   
   reg [31:0]                   mem [0:RAM_DEPTH-1];

   always @(posedge clk)
     begin
        if (data_b_we & (addr_b[31:16] == 0)) begin
           mem[addr_b] <= data_b_in;
        end
        data_a <= mem[addr_a];
        data_b <= mem[addr_b];
        strobe_b <= (addr_b[31:16] == 0);
     end

endmodule
module socram(input clk,
              input         rst,
              
              output [31:0] data_a,
              input [31:0]  addr_a,
              
              output [31:0] data_b,
              output        strobe_b,
              input [31:0]  addr_b,
              input [31:0]  data_b_in,
              input [31:0]  data_b_we);

   parameter RAM_DEPTH = 16384;
   
   reg [31:0]                   mem [0:RAM_DEPTH-1];
   
   assign data_a = mem[addr_a];
   assign data_b = mem[addr_b];
   assign strobe_b = (addr_b[31:16] == 0);

   always @(posedge clk)
     begin
        if (data_b_we & (addr_b[31:16] == 0)) begin
           mem[addr_b] <= data_b_in;
        end
     end

endmodule
module hls_Mul(input clk,
               input reset,

               input [31:0]  p0,
               input [31:0]  p1,
               output [31:0] out);

   wire [15:0]               a = p0r[31:16];
   wire [15:0]               b = p0r[15:0];
   wire [15:0]               c = p1r[31:16];
   wire [15:0]               d = p1r[15:0];

   wire [15:0]               ad = a * d;
   wire [15:0]               bc = b * c;
   wire [31:0]               bd = b * d;

   reg [15:0]                adr;
   
   reg [31:0]                p0r;
   reg [31:0]                p1r;
   reg [31:0]                t1;
   reg [31:0]                t2;
   reg [31:0]                t3;
   assign out = t3;
   

   always @(posedge clk)
     begin
        p0r <= p0; p1r <= p1;
        t1 <= bd + {bc[15:0], 16'b0}; adr <= ad[15:0];
        t2 <= t1 + {adr[15:0], 16'b0};
        t3 <= t2;
        
     end
   
   
endmodule // hls_Mul
module mul32x32_fsm(input clk,
                    input             rst,
                    input             req,
               
                    input [31:0]      p0,
                    input [31:0]      p1,
                    output reg        ack,
                    output reg [31:0] out);

   wire [31:0]               m_o;
   
   reg [15:0]                m_a;
   reg [15:0]                m_b;
   reg [31:0]                acc;
   reg [2:0]                 stage;
   

   wire [15:0]               a = p0[31:16];
   wire [15:0]               b = p0[15:0];
   wire [15:0]               c = p1[31:16];
   wire [15:0]               d = p1[15:0];

   mul16x16 m (.a(m_a),
               .b(m_b),
               .o(m_o));

   wire [31:0]               next_acc;

   assign next_acc = acc + {m_o[15:0], 16'b0};
   always @(posedge clk) begin
      if (req) begin
         stage <= 1;
         m_a <= b; m_b <= d;
         acc <= 0;
         out <= 0;
         ack <= 0;
      end else begin
         case(stage)
           0: begin
              ack <= 0;
           end
           1:  begin
              acc <= m_o;
              m_a <= b; m_b <= c;
              stage <= 2;
           end
           2: begin
              acc <= next_acc;
              m_a <= a; m_b <= d;
              stage <= 3;
           end
           3: begin
              ack <= 1;
              out <= next_acc;
              stage <= 0;
           end
         endcase // case (stage)
      end // else: !if(req)
   end
endmodule // mul32x32_fsm
module div_pipelined2(clk, rst, z, d,
                      quot, rem);
   parameter WIDTH = 32;
   localparam ZBITS = WIDTH*2;
   
   localparam DBITS = ZBITS/2;
   localparam STAGES = DBITS/2;
	
   input clk;
   input rst;
   input [WIDTH -1:0] z;
   input [DBITS -1:0] d;
   output [DBITS -1:0] quot;
   output [DBITS -1:0] rem;
   reg [DBITS-1:0]     quot;
   reg [DBITS-1:0]     rem;

   function [ZBITS:0] remainder;
      input [ZBITS:0]  rem_i; input [ZBITS:0]  d_i;
      begin
	 remainder = (rem_i[ZBITS])?({rem_i[ZBITS-1:0], 1'b0} + d_i):
	                            ({rem_i[ZBITS-1:0], 1'b0} - d_i);
      end
   endfunction // remainder
   
   function [ZBITS-1:0] remainder_final;
      input [ZBITS:0] rem_i; input [ZBITS:0] d_i;
      begin
	 remainder_final = (rem_i[ZBITS]?(rem_i + d_i):rem_i);
      end
   endfunction // remainder_final

   function [DBITS-1:0] quotient;
      input [DBITS-1:0] quot_i; input [ZBITS:0] rem_i;
      begin
	 quotient = {quot_i[DBITS-2:0], ~rem_i[ZBITS]};
      end
   endfunction

   reg [ZBITS:0]   d_stage  [STAGES:0];
   reg [DBITS-1:0] quot_stage  [STAGES:0];
   reg [ZBITS:0]   rem_stage  [STAGES:0];

   wire [ZBITS-1:0] quot_stage_wire  [STAGES:0];
   wire [ZBITS:0]   rem_stage_wire  [STAGES:0];

   wire [ZBITS:0]  rem_next;
   assign rem_next = remainder_final(rem_stage_wire[STAGES], d_stage[STAGES]);

   integer         stage, stage0;

   generate genvar stage1;
      for(stage1=0; stage1 <= STAGES; stage1=stage1+1) begin
         assign rem_stage_wire[stage1] = remainder(rem_stage[stage1], d_stage[stage1]);
         if (stage1>0)
           assign quot_stage_wire[stage1] = quotient(quot_stage[stage1], rem_stage[stage1]);
         else assign quot_stage_wire[stage1] = 0;
      end
   endgenerate
   
   always @(posedge clk)
     if (!rst) begin
        quot <= 0;
        rem <= 0;
        for (stage=0; stage <=STAGES; stage=stage+1) begin
           rem_stage[stage] <= 0;
           quot_stage[stage] <= 0;
           d_stage[stage] <= 0;
        end
     end  else begin
        d_stage[0] <= { 1'b0, d, { (ZBITS-DBITS){1'b0} } };
        rem_stage[0] <= z;
        quot_stage[0] <= 0;
        
        for(stage0=1; stage0 <= STAGES; stage0=stage0+1) begin
           d_stage[stage0] <= d_stage[stage0-1];
	   rem_stage[stage0] <= remainder(rem_stage_wire[stage0-1], d_stage[stage0-1]);
           quot_stage[stage0] <= quotient(quot_stage_wire[stage0-1], rem_stage_wire[stage0-1]);
        end

        quot <= quot_stage_wire[STAGES];
        rem <= rem_next[ZBITS-1:ZBITS-DBITS];
     end // else: !if(!rst)
      
endmodule
module smallfifo16x(input rst,
		 
		   input         clk_in,
		   input [15:0]  fifo_in,
		   input         fifo_en,

		   output        fifo_full,

		   input         clk_out,
		   output [15:0] fifo_out,
		   output        fifo_empty,
		   input         fifo_rd);


   vga_fifo_dc#(.AWIDTH(4),.DWIDTH(16)) 
   fifo0(.rclk (clk_out),
         .wclk (clk_in),
         .rclr (~rst),
         .wclr (~rst),
         .wreq (fifo_en),
         .d (fifo_in),
         .rreq (fifo_rd),
         .q (fifo_out),
         .empty (fifo_empty),
         .full (fifo_full));
   
   
endmodule
module soundctl (input clk,
                 input        rst,

                 output       sound_clr_full,
                 input [15:0] sound_clr_sample,
                 input [15:0] sound_clr_rate,
                 input        sound_clr_req,
                 output reg   pwm_out
);


   wire [15:0]                fifo_out;
   wire                       fifo_empty;
   reg                        fifo_rd;

   smallfifo16x fifo1(.rst(rst),
                     .clk_in(clk),
                     .fifo_in(sound_clr_sample),
                     .fifo_en(sound_clr_req),
                     .fifo_full(sound_clr_full),
                     
                     .clk_out(clk),
                     .fifo_out(fifo_out),
                     .fifo_empty(fifo_empty),
                     .fifo_rd(fifo_rd));

   reg [15:0]                 counter;
   reg [8:0]                 sample;
   
   always @(posedge clk)
    if (~rst) begin
       fifo_rd <= 0;
       counter <= 0;
       pwm_out <= 0;
       sample <= 1024;  // 50% duty cycle default level
    end else begin
       pwm_out <= (counter < sample)?1:0;
       if (fifo_rd) begin
          sample <= fifo_out;
          fifo_rd <= 0;
       end 
       else if (counter >= sound_clr_rate) begin
          counter <= 0;
          if (~fifo_empty) fifo_rd <= 1; else  begin
             fifo_rd <= 0;
             sample <= 1024;
          end
       end else begin
          fifo_rd <= 0;
          counter <= counter + 1;
       end
    end
   

endmodule
module regfile
             #(parameter [0:0] MICROOPS_ENABLED = 1)
              (input clk,
               input             rst,

               input [31:0]      PC,

               input [4:0]       addr1,
               input [4:0]       addr2,

               input [4:0]       addrw,

`ifdef  REGFILE_REGISTERED_OUT
               output reg [31:0] out1,
               output reg [31:0] out2,
`else
               output [31:0]     out1,
               output [31:0]     out2,
`endif

               input [4:0]       dbgreg,
               input             dbgreg_en,

               input [31:0]      wdata,
               input             we,
               input [31:0]      clkcounter);

   reg [31:0]                   mem [0:31];

   wire [31:0]                  out1_next;
   wire [31:0]                  out2_next;

// PC+1 if microops enabled, otherwise PC+2

   wire [31:0]                   delta1;
   wire [31:0]                   delta2;
   

   assign delta1 = MICROOPS_ENABLED?1:2;
`ifdef REGFILE_REGISTERED_OUT
   assign delta2 = 0;
`else
   assign delta2 = -1;
`endif
   
   assign out1_next = addr1==0?0:
                      (addr1==1?1:
                       (addr1==31?(PC+(delta1+delta2)):
                        (addrw==addr1?wdata:mem[addr1])));
   assign out2_next = addr2==0?0:
                      (addr2==1?1:
                       (addr2==31?(PC+(delta1+delta2)):
                        (addrw==addr2?wdata:mem[addr2])));

`ifndef  REGFILE_REGISTERED_OUT
   assign out1 = out1_next;
   assign out2 = out2_next;
`endif
   
   always @(posedge clk)
      begin
        if (we) begin
           mem[addrw] <= wdata;
        end
`ifdef  REGFILE_REGISTERED_OUT
         out1 <= out1_next;
         out2 <= out2_next;
`endif
         if (dbgreg_en)
           $write("[R%0d=%0d]", dbgreg, mem[dbgreg]);
      end
   
endmodule
module div_pipelined(clk, rst, z, d,
                     quot, rem);
   parameter  WIDTH = 32;
   
   localparam ZBITS = WIDTH*2;
   localparam DBITS = ZBITS / 2;
	
   input clk;
   input rst;
   input [WIDTH -1:0] z;
   input [DBITS -1:0] d;
   output [DBITS -1:0] quot;
   output [DBITS -1:0] rem;
   reg [DBITS-1:0]     quot;
   reg [DBITS-1:0]     rem;

   function [ZBITS:0] remainder;
      input [ZBITS:0]  rem_i; input [ZBITS:0]  d_i;
      begin
	 remainder = (rem_i[ZBITS])?({rem_i[ZBITS-1:0], 1'b0} + d_i):
	                            ({rem_i[ZBITS-1:0], 1'b0} - d_i);
      end
   endfunction // remainder
   
   function [DBITS-1:0] remainder_final;
      input [ZBITS:0] rem_i; input [ZBITS:0] d_i;
      begin
	 remainder_final = (rem_i[ZBITS]?(rem_i + d_i):rem_i);
      end
   endfunction // remainder_final
                     

   function [DBITS-1:0] quotient;
      input [DBITS-1:0] quot_i; input [ZBITS:0] rem_i;
      begin
	 quotient = {quot_i[DBITS-2:0], ~rem_i[ZBITS]};
      end
   endfunction

   reg [ZBITS:0]   d_stage  [DBITS:0];
   reg [DBITS-1:0] quot_stage  [DBITS:0];
   reg [ZBITS:0]   rem_stage  [DBITS:0];

   wire [ZBITS:0]  rem_next;
   assign rem_next = remainder_final(rem_stage[DBITS], d_stage[DBITS]);

   integer         stage, stage0;
   
   always @(posedge clk)
     if (!rst) begin
        quot <= 0;
        rem <= 0;
        for (stage=0; stage <=DBITS; stage=stage+1) begin
           rem_stage[stage] <= 0;
           quot_stage[stage] <= 0;
           d_stage[stage] <= 0;
        end
     end  else begin
        d_stage[0] <= { 1'b0, d, { (ZBITS-DBITS){1'b0} } };
        rem_stage[0] <= z;
        quot_stage[0] <= 0; quot_stage[1] <= 0;
        
        for(stage0=1; stage0 <= DBITS; stage0=stage0+1) begin
           if (stage0>1)
	     quot_stage[stage0] <= quotient(quot_stage[stage0-1], rem_stage[stage0-1]);
           d_stage[stage0] <= d_stage[stage0-1];
	   rem_stage[stage0] <= remainder(rem_stage[stage0-1], d_stage[stage0-1]);
        end

	quot <= quotient(quot_stage[DBITS], rem_stage[DBITS]);
	  rem <= rem_next[ZBITS-1:ZBITS-DBITS];
     end // else: !if(!rst)
      
endmodule
module uartmm(input clk,
              input             rst,

              input             RX,
              output            TX,
              
              output reg [31:0] data_b,
              output reg        strobe_b,
              input [31:0]      addr_b,
              input [31:0]      data_b_in,
              input [31:0]      data_b_we);

   wire [7:0]                uart_din;
   wire                      uart_valid;
   wire                      uart_ready;
   reg                       uart_wr;
   reg                       uart_rd;
   reg [7:0]                 uart_dout;

   reg [7:0]                 uart_din_r;
   reg                      uart_valid_r;
   reg                      uart_ready_r;
   
   
   wire                 uart_RXD;
   inpin _rcxd(.clk(clk), .pin(RX), .rd(uart_RXD));

   wire                     uart_busy;

   assign uart_ready = ~uart_busy;
   
   buart _uart (
                .clk(clk),
                .resetq(1'b1),
                .rx(uart_RXD),
                .tx(TX),
                .rd(uart_rd),
                .wr(uart_wr),
                .valid(uart_valid),
                .busy(uart_busy),
                .tx_data(uart_dout),
                .rx_data(uart_din));

   wire                     strobe_b_next;
   wire [31:0]              data_b_next;
   

   assign strobe_b_next =   (addr_b == 65537) | (addr_b == 65538) | (addr_b == 65539);
   assign data_b_next = (addr_b == 65537)?uart_valid_r:
                        (addr_b == 65538)?uart_ready_r:
                        (addr_b == 65539)?uart_din_r:0;

   always @(posedge clk)
     if (~rst) begin
        uart_wr <= 0;
        uart_rd <= 0;
        uart_valid_r <= 0;
        uart_din_r <= 0;
        uart_dout <= 0;
        strobe_b <= 0;
        data_b <= 0;
        
     end else begin
        strobe_b <= strobe_b_next;
        data_b <= data_b_next;
        
        if (uart_wr) begin
           uart_wr <= 0;
        end
        
        if (uart_valid & ~uart_rd) begin
           uart_rd <= 1; // TODO: read into a FIFO / raise an IRQ (when we had a support for them)
        end

        uart_ready_r <= uart_ready; // delay

        if (uart_rd) begin
           uart_rd <= 0;
           uart_din_r <= uart_din;
           uart_valid_r <= 1;
        end else if ((addr_b == 65539) & ~data_b_we & uart_valid_r) begin
           uart_valid_r <= 0;
        end else if ((addr_b == 65539) & data_b_we & uart_ready & ~uart_wr) begin
           uart_dout <= data_b[7:0];
           uart_wr <= 1;
        end
     end
   

endmodule
module socram(input clk,
              input             rst,

              output reg [31:0] data_a,
              input [31:0]      addr_a,
              
              output reg [31:0] data_b,
              output reg        strobe_b,
              input [31:0]      addr_b,
              input [31:0]      data_b_in,
              input [31:0]      data_b_we);

   parameter RAM_DEPTH = 1024;
`ifdef ENABLE_EXT
   parameter INIT_FILE = "../../custom_ice.hex";
`else
   parameter INIT_FILE = "ram.hex";
`endif
   
   reg [31:0]                   mem [0:RAM_DEPTH-1];
   
   initial begin
      if (INIT_FILE != "")
         $readmemh(INIT_FILE, mem);
   end

   
   always @(posedge clk)
     begin
        if (data_b_we & (addr_b[31:16] == 0)) begin
           mem[addr_b] <= data_b_in;
        end
        data_a <= mem[addr_a];
        data_b <= mem[addr_b];
        strobe_b <= (addr_b[31:16] == 0);
     end
   
endmodule
module testbench;


   reg clk = 1;
   always #5 clk = ~clk;


   wire LED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8;

   wire [7:0] LEDS;

   assign LEDS = {LED8, LED7, LED6, LED5, LED4, LED3, LED2, LED1};

   wire [7:0] PCdebug;

   wire dummy;
   reg  rdummy;
   reg  rst;
   
   always @(posedge clk) rdummy <= dummy;

   reg [31:0] clkcounter;
   reg [7:0]  prev_LED;
   
   always @(posedge clk)
     if (rst) clkcounter <= clkcounter + 1; else clkcounter <= 0;
   
   top soc ( .sys_clk_in(clk),
	     .LED1(LED1),
	     .LED2(LED2),
	     .LED3(LED3),
	     .LED4(LED4),
	     .LED5(LED5),
	     .LED6(LED6),
	     .LED7(LED7),
	     .LED8(LED8),
             .RX(1'b0),
             .TX(dummy),
             .PCdebug1(PCdebug[0]),
             .PCdebug2(PCdebug[1]),
             .PCdebug3(PCdebug[2]),
             .PCdebug4(PCdebug[3]),
             .PCdebug5(PCdebug[4]),
             .PCdebug6(PCdebug[5]),
             .PCdebug7(PCdebug[6]),
             .PCdebug8(PCdebug[7]),
             .sys_reset(rst)
             );
   

   	initial begin
           rst <= 0;
           prev_LED <= 0;
           
           repeat (50) @(posedge clk);
           rst <= 1;
	end

   always @(posedge clk)
     if (rst) begin
        $display(">>> PC=%d", PCdebug);
        
        if (LEDS != prev_LED) begin
           $display("LED=%b @ %d", LEDS, clkcounter);
           prev_LED <= LEDS;
        end
        if (clkcounter > 1000) $finish;
        
     end

endmodule
module uart #
(
    parameter DATA_WIDTH = 8
)
(
    input  wire                   clk,
    input  wire                   rst,

    /*
     * AXI input
     */
    input  wire [DATA_WIDTH-1:0]  input_axis_tdata,
    input  wire                   input_axis_tvalid,
    output wire                   input_axis_tready,

    /*
     * AXI output
     */
    output wire [DATA_WIDTH-1:0]  output_axis_tdata,
    output wire                   output_axis_tvalid,
    input  wire                   output_axis_tready,

    /*
     * UART interface
     */
    input  wire                   rxd,
    output wire                   txd,

    /*
     * Status
     */
    output wire                   tx_busy,
    output wire                   rx_busy,
    output wire                   rx_overrun_error,
    output wire                   rx_frame_error,

    /*
     * Configuration
     */
    input  wire [15:0]            prescale

);

uart_tx #(
    .DATA_WIDTH(DATA_WIDTH)
)
uart_tx_inst (
    .clk(clk),
    .rst(rst),
    // axi input
    .input_axis_tdata(input_axis_tdata),
    .input_axis_tvalid(input_axis_tvalid),
    .input_axis_tready(input_axis_tready),
    // output
    .txd(txd),
    // status
    .busy(tx_busy),
    // configuration
    .prescale(prescale)
);

uart_rx #(
    .DATA_WIDTH(DATA_WIDTH)
)
uart_rx_inst (
    .clk(clk),
    .rst(rst),
    // axi output
    .output_axis_tdata(output_axis_tdata),
    .output_axis_tvalid(output_axis_tvalid),
    .output_axis_tready(output_axis_tready),
    // input
    .rxd(rxd),
    // status
    .busy(rx_busy),
    .overrun_error(rx_overrun_error),
    .frame_error(rx_frame_error),
    // configuration
    .prescale(prescale)
);

endmodule
module uart_rx #
(
    parameter DATA_WIDTH = 8
)
(
    input  wire                   clk,
    input  wire                   rst,

    /*
     * AXI output
     */
    output wire [DATA_WIDTH-1:0]  output_axis_tdata,
    output wire                   output_axis_tvalid,
    input  wire                   output_axis_tready,

    /*
     * UART interface
     */
    input  wire                   rxd,

    /*
     * Status
     */
    output wire                   busy,
    output wire                   overrun_error,
    output wire                   frame_error,

    /*
     * Configuration
     */
    input  wire [15:0]            prescale

);

reg [DATA_WIDTH-1:0] output_axis_tdata_reg = 0;
reg output_axis_tvalid_reg = 0;

reg rxd_reg = 1;

reg busy_reg = 0;
reg overrun_error_reg = 0;
reg frame_error_reg = 0;

reg [DATA_WIDTH-1:0] data_reg = 0;
reg [18:0] prescale_reg = 0;
reg [3:0] bit_cnt = 0;

assign output_axis_tdata = output_axis_tdata_reg;
assign output_axis_tvalid = output_axis_tvalid_reg;

assign busy = busy_reg;
assign overrun_error = overrun_error_reg;
assign frame_error = frame_error_reg;

always @(posedge clk or posedge rst) begin
    if (rst) begin
        output_axis_tdata_reg <= 0;
        output_axis_tvalid_reg <= 0;
        rxd_reg <= 1;
        prescale_reg <= 0;
        bit_cnt <= 0;
        busy_reg <= 0;
        overrun_error_reg <= 0;
        frame_error_reg <= 0;
    end else begin
        rxd_reg <= rxd;
        overrun_error_reg <= 0;
        frame_error_reg <= 0;

        if (output_axis_tvalid & output_axis_tready) begin
            output_axis_tvalid_reg <= 0;
        end

        if (prescale_reg > 0) begin
            prescale_reg <= prescale_reg - 1;
        end else if (bit_cnt > 0) begin
            if (bit_cnt > DATA_WIDTH+1) begin
                if (~rxd_reg) begin
                    bit_cnt <= bit_cnt - 1;
                    prescale_reg <= (prescale << 3)-1;
                end else begin
                    bit_cnt <= 0;
                    prescale_reg <= 0;
                end
            end else if (bit_cnt > 1) begin
                bit_cnt <= bit_cnt - 1;
                prescale_reg <= (prescale << 3)-1;
                data_reg <= {rxd_reg, data_reg[DATA_WIDTH-1:1]};
            end else if (bit_cnt == 1) begin
                bit_cnt <= bit_cnt - 1;
                if (rxd_reg) begin
                    output_axis_tdata_reg <= data_reg;
                    output_axis_tvalid_reg <= 1;
                    overrun_error_reg <= output_axis_tvalid_reg;
                end else begin
                    frame_error_reg <= 1;
                end
            end
        end else begin
            busy_reg <= 0;
            if (~rxd_reg) begin
                prescale_reg <= (prescale << 2)-2;
                bit_cnt <= DATA_WIDTH+2;
                data_reg <= 0;
                busy_reg <= 1;
            end
        end
    end
end

endmodule
module smallfifo1(input rst,
		 
		 input        clk_in,
		 input [7:0]  fifo_in,
		 input        fifo_en,

		 output       fifo_full,

		 input        clk_out,
		 output [7:0] fifo_out,
		 output       fifo_empty,
		 input        fifo_rd);


   vga_fifo_dc#(.AWIDTH(4),.DWIDTH(8)) 
   fifo0(.rclk (clk_out),
         .wclk (clk_in),
         .rclr (~rst),
         .wclr (~rst),
         .wreq (fifo_en),
         .d (fifo_in),
         .rreq (fifo_rd),
         .q (fifo_out),
         .empty (fifo_empty),
         .full (fifo_full));
   
   
endmodule