dakies/OSS_Verilog huggingface dataset:
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),
		.do(q),
		.wclk(wclk),
		.wrst(1'b0),
		.wce(1'b1),
		.we(wreq),
		.waddr(wptr),
		.di(d)
	);

endmodule
module vga_clkgen (
	pclk_i, rst_i, pclk_o, dvi_pclk_p_o, dvi_pclk_m_o, pclk_ena_o
);

	// inputs & outputs

	input  pclk_i;       // pixel clock in
	input  rst_i;        // reset input

	output pclk_o;       // pixel clock out

	output dvi_pclk_p_o; // dvi cpclk+ output
	output dvi_pclk_m_o; // dvi cpclk- output

	output pclk_ena_o;   // pixel clock enable output

	//
	// variable declarations
	//
	reg dvi_pclk_p_o;
	reg dvi_pclk_m_o;

	//////////////////////////////////
	//
	// module body
	//

	// These should be registers in or near IO buffers
	always @(posedge pclk_i)
	  if (rst_i) begin
	    dvi_pclk_p_o <= #1 1'b0;
	    dvi_pclk_m_o <= #1 1'b0;
	  end else begin
	    dvi_pclk_p_o <= #1 ~dvi_pclk_p_o;
	    dvi_pclk_m_o <= #1 dvi_pclk_p_o;
	  end


`ifdef VGA_12BIT_DVI
	// DVI circuit
	// pixel clock is half of the input pixel clock

	reg pclk_o, pclk_ena_o;

	always @(posedge pclk_i)
	  if (rst_i)
	    pclk_o <= #1 1'b0;
	  else
	    pclk_o <= #1 ~pclk_o;

	always @(posedge pclk_i)
	  if (rst_i)
	    pclk_ena_o <= #1 1'b1;
	  else
	    pclk_ena_o <= #1 ~pclk_ena_o;

`else
	// No DVI circuit
	// Simply reroute the pixel clock input

	assign pclk_o     = pclk_i;
	assign pclk_ena_o = 1'b1;
`endif

endmodule
module vga_csm_pb (clk_i, req0_i, ack0_o, adr0_i, dat0_i, dat0_o, we0_i, req1_i, ack1_o, adr1_i, dat1_i, dat1_o, we1_i);
		
	//
	// parameters
	//
	parameter DWIDTH = 32; // databus width
	parameter AWIDTH = 8;  // address bus width

	//
	// inputs & outputs
	//
	
	input clk_i;                    // clock input

	// wishbone slave0 connections
	input  [ AWIDTH   -1:0] adr0_i; // address input
	input  [ DWIDTH   -1:0] dat0_i; // data input
	output [ DWIDTH   -1:0] dat0_o; // data output
	input                   we0_i;  // write enable input
	input                   req0_i; // access request input
	output                  ack0_o; // access acknowledge output

	// wishbone slave1 connections
	input  [ AWIDTH   -1:0] adr1_i; // address input
	input  [ DWIDTH   -1:0] dat1_i; // data input
	output [ DWIDTH   -1:0] dat1_o; // data output
	input                   we1_i;  // write enable input
	input                   req1_i; // access request input
	output                  ack1_o; // access acknowledge output

	//
	// variable declarations
	//

	// multiplexor select signal
	wire acc0, acc1;
	reg  dacc0, dacc1;
	wire sel0, sel1;
	reg  ack0, ack1;
	
	// memory data output
	wire [DWIDTH -1:0] mem_q;


	//
	// module body
	//

	// generate multiplexor select signal
	assign acc0 = req0_i;
	assign acc1 = req1_i && !sel0;

	always@(posedge clk_i)
		begin
			dacc0 <= #1 acc0 & !ack0_o;
			dacc1 <= #1 acc1 & !ack1_o;
		end

	assign sel0 = acc0 && !dacc0;
	assign sel1 = acc1 && !dacc1;

	always@(posedge clk_i)
		begin
			ack0 <= #1 sel0 && !ack0_o;
			ack1 <= #1 sel1 && !ack1_o;
		end

	wire [AWIDTH -1:0] mem_adr = sel0 ? adr0_i : adr1_i;
	wire [DWIDTH -1:0] mem_d   = sel0 ? dat0_i : dat1_i;
	wire               mem_we  = sel0 ? req0_i && we0_i : req1_i && we1_i;

	// hookup generic synchronous single port memory
	generic_spram #(AWIDTH, DWIDTH) clut_mem(
		.clk(clk_i),
		.rst(1'b0),       // no reset
		.ce(1'b1),        // always enable memory
		.we(mem_we),
		.oe(1'b1),        // always output data
		.addr(mem_adr),
		.di(mem_d),
		.do(mem_q)
	);

	// assign DAT_O outputs
	assign dat0_o = mem_q;
	assign dat1_o = mem_q;

	// generate ack outputs
	assign ack0_o = ( (sel0 && we0_i) || ack0 );
	assign ack1_o = ( (sel1 && we1_i) || ack1 );
endmodule
module picosoc_regs (
	input clk, wen,
	input [5:0] waddr,
	input [5:0] raddr1,
	input [5:0] raddr2,
	input [31:0] wdata,
	output [31:0] rdata1,
	output [31:0] rdata2
);
	reg [31:0] regs [0:31];

	always @(posedge clk)
		if (wen) regs[waddr[4:0]] <= wdata;

	assign rdata1 = regs[raddr1[4:0]];
	assign rdata2 = regs[raddr2[4:0]];
endmodule
module picosoc_mem #(
	parameter integer WORDS = 256
) (
	input clk,
	input [3:0] wen,
	input [21:0] addr,
	input [31:0] wdata,
	output reg [31:0] rdata
);
	reg [31:0] mem [0:WORDS-1];

	always @(posedge clk) begin
		rdata <= mem[addr];
		if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0];
		if (wen[1]) mem[addr][15: 8] <= wdata[15: 8];
		if (wen[2]) mem[addr][23:16] <= wdata[23:16];
		if (wen[3]) mem[addr][31:24] <= wdata[31:24];
	end
endmodule
module simpleuart #(parameter integer DEFAULT_DIV = 1) (
	input clk,
	input resetn,

	output ser_tx,
	input  ser_rx,

	input   [3:0] reg_div_we,
	input  [31:0] reg_div_di,
	output [31:0] reg_div_do,

	input         reg_dat_we,
	input         reg_dat_re,
	input  [31:0] reg_dat_di,
	output [31:0] reg_dat_do,
	output        reg_dat_wait
);
	reg [31:0] cfg_divider;

	reg [3:0] recv_state;
	reg [31:0] recv_divcnt;
	reg [7:0] recv_pattern;
	reg [7:0] recv_buf_data;
	reg recv_buf_valid;

	reg [9:0] send_pattern;
	reg [3:0] send_bitcnt;
	reg [31:0] send_divcnt;
	reg send_dummy;

	assign reg_div_do = cfg_divider;

	assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
	assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;

	always @(posedge clk) begin
		if (!resetn) begin
			cfg_divider <= DEFAULT_DIV;
		end else begin
			if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
			if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
			if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
			if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
		end
	end

	always @(posedge clk) begin
		if (!resetn) begin
			recv_state <= 0;
			recv_divcnt <= 0;
			recv_pattern <= 0;
			recv_buf_data <= 0;
			recv_buf_valid <= 0;
		end else begin
			recv_divcnt <= recv_divcnt + 1;
			if (reg_dat_re)
				recv_buf_valid <= 0;
			case (recv_state)
				0: begin
					if (!ser_rx)
						recv_state <= 1;
					recv_divcnt <= 0;
				end
				1: begin
					if (2*recv_divcnt > cfg_divider) begin
						recv_state <= 2;
						recv_divcnt <= 0;
					end
				end
				10: begin
					if (recv_divcnt > cfg_divider) begin
						recv_buf_data <= recv_pattern;
						recv_buf_valid <= 1;
						recv_state <= 0;
					end
				end
				default: begin
					if (recv_divcnt > cfg_divider) begin
						recv_pattern <= {ser_rx, recv_pattern[7:1]};
						recv_state <= recv_state + 1;
						recv_divcnt <= 0;
					end
				end
			endcase
		end
	end

	assign ser_tx = send_pattern[0];

	always @(posedge clk) begin
		if (reg_div_we)
			send_dummy <= 1;
		send_divcnt <= send_divcnt + 1;
		if (!resetn) begin
			send_pattern <= ~0;
			send_bitcnt <= 0;
			send_divcnt <= 0;
			send_dummy <= 1;
		end else begin
			if (send_dummy && !send_bitcnt) begin
				send_pattern <= ~0;
				send_bitcnt <= 15;
				send_divcnt <= 0;
				send_dummy <= 0;
			end else
			if (reg_dat_we && !send_bitcnt) begin
				send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
				send_bitcnt <= 10;
				send_divcnt <= 0;
			end else
			if (send_divcnt > cfg_divider && send_bitcnt) begin
				send_pattern <= {1'b1, send_pattern[9:1]};
				send_bitcnt <= send_bitcnt - 1;
				send_divcnt <= 0;
			end
		end
	end
endmodule
module top(
	input SYSCLK,
	output LED_RED,
	output LED_BLUE,
	output LED_GREEN
	);

	reg [2:0] led_reg;
	reg [32:0] counter;

	assign LED_RED = led_reg[0];
	assign LED_BLUE = led_reg[1];
	assign LED_GREEN = led_reg[2];

	always @(posedge SYSCLK) begin
		if (counter < 25000000)
			counter <= counter + 1;
		else begin
			counter <= 0;
			led_reg <= led_reg + 1;
		end
	end
endmodule
module mux16 #( parameter W = 1 ) (
    sel,
    i1111,
    i1110,
    i1101,
    i1100,
    i1011,
    i1010,
    i1001,
    i1000,
    i0111,
    i0110,
    i0101,
    i0100,
    i0011,
    i0010,
    i0001,
    i0000,
    o
);

input [3:0] sel;
input [W-1:0]
    i1111,
    i1110,
    i1101,
    i1100,
    i1011,
    i1010,
    i1001,
    i1000,
    i0111,
    i0110,
    i0101,
    i0100,
    i0011,
    i0010,
    i0001,
    i0000;

output [W-1:0] o;

reg [W-1:0] o;

always @ (
    sel,
    i1111,
    i1110,
    i1101,
    i1100,
    i1011,
    i1010,
    i1001,
    i1000,
    i0111,
    i0110,
    i0101,
    i0100,
    i0011,
    i0010,
    i0001,
    i0000
) begin
    case (sel)
    0:  o = i0000;
    1:  o = i0001;
    2:  o = i0010;
    3:  o = i0011;
    4:  o = i0100;
    5:  o = i0101;
    6:  o = i0110;
    7:  o = i0111;
    8:  o = i1000;
    9:  o = i1001;
    10: o = i1010;
    11: o = i1011;
    12: o = i1100;
    13: o = i1101;
    14: o = i1110;
    default o = i1111;
    endcase
end

endmodule
module tail_length (ir, len);

input [3:0] ir;
output [3:0] len;

reg [3:0] len;
reg ir32;

/*
      ..00  ..01  ..10  ..11
00..  1     0     0     0
01..  1     ?     ?     0
10..  1     1     0     0
11..  1     1     0     0
len[0] = (ir[3] & !ir[1]) | (!ir[1] & !ir[0]);

      ..00  ..01  ..10  ..11
00..  0     1     0     0
01..  0     ?     ?     0
10..  0     0     0     0
11..  0     0     0     0
len[1] = !ir[3] & !ir[2] & !ir[1] & ir[0];

      ..00  ..01  ..10  ..11
00..  0     0     1     0
01..  0     ?     ?     0
10..  0     0     0     0
11..  0     0     0     0
len[2] = !ir[3] & !ir[2] & ir[1] & !ir[0];

      ..00  ..01  ..10  ..11
00..  0     0     0     1
01..  0     ?     ?     0
10..  0     0     0     0
11..  0     0     0     0
len[3] = !ir[3] & !ir[2] & ir[1] & ir[0];

    ..00  ..01  ..10  ..11
00..  1     2     4     8
01..  1     ?     ?     0
10..  1     1     0     0
11..  1     1     0     0
*/

always @ (ir)
begin
    len = {
        (ir == 4'b0011),
        (ir == 4'b0010),
        (ir == 4'b0001),
        ((ir | 4'b0101) == 4'b1101) | ((ir | 4'b1100) == 4'b1100)
    };
end

// 107.89 / 121.08
// always @ (ir)
// begin
//     ir32 = |ir[3:2];
//     len = {
//         (!ir32 &  ir[1] &  ir[0]),
//         (!ir32 &  ir[1] & !ir[0]),
//         (!ir32 & !ir[1] &  ir[0]),
//         ((ir[3] & !ir[1]) | (!ir[1] & !ir[0]))
//     };
// end

// always @ (ir)
//     casez (ir)
//     4'b??00: len = 1;
//     4'b1?0?: len = 1;
//     4'b0001: len = 2;
//     4'b0010: len = 4;
//     4'b0011: len = 8;
//     default  len = 0;
//     endcase

endmodule
module usb_loopback (
		input clk,
		input [7:0] btn,
`ifdef BADGE_V3
		output [10:0] ledc,
		output [2:0] leda,
		inout [29:0] genio,
`else
		output [8:0] led,
		inout [27:0] genio,
`endif
		output uart_tx,
		input uart_rx,
`ifdef BADGE_V3
		output irda_tx,
		input irda_rx,
		output irda_sd,
`endif
		output pwmout,
		output [17:0] lcd_db,
		output lcd_rd,
		output lcd_wr,
		output lcd_rs,
		output lcd_cs,
		input lcd_id,
		output lcd_rst,
		input lcd_fmark,
		output lcd_blen,
		output psrama_nce,
		output psrama_sclk,
		inout [3:0] psrama_sio,
		output psramb_nce,
		output psramb_sclk,
		inout [3:0] psramb_sio,
		output flash_cs,
		inout flash_miso,
		inout flash_mosi,
		inout flash_wp,
		inout flash_hold,
		output fsel_d,
		output fsel_c,
		output programn,

		output [3:0] gpdi_dp, gpdi_dn,
		inout usb_dp,
		inout usb_dm,
		output usb_pu,
		input usb_vdet,

		inout [5:0] sao1,
		inout [5:0] sao2,
		inout [7:0] pmod,

		output adcrefout,
		input adcref4
	);


	//
	// Clocks
	//

	// This is so Diamond can run something.  It is insufficently accurate to run USB
	/*
		wire clkint;
		OSCG #(
			.DIV( 2 ) //155MHz approx
		) oscint (
			.OSC(clkint)
		);
	*/

    wire clock_48mhz;
    clock_pll c_pll (.CLKI( clk ), .CLKOP( clock_48mhz ));

	//
	// RESET
	//

    reg [5:0] reset_counter = 0;
    wire reset = ~reset_counter[5];
    always @(posedge clock_48mhz)
        reset_counter <= reset_counter + reset;


	//
	// Config
	//

	reg fpga_reload=0;
	assign programn = ~fpga_reload;
	always @( posedge clock_48mhz )
		if ( ~btn[4] )
			fpga_reload <= 1;

	//
	// LED
	//

	reg [28:0] led_counter = 0;
	always @( posedge clock_48mhz ) begin
		if ( reset ) begin
		end else begin
			led_counter <= led_counter + 1'H1;
		end
	end

	`ifdef BADGE_V3
		assign ledc[ 8 ] = led_counter[ 25:19 ] == 0;
		assign leda = 1;
	`else
		assign led[ 8 ] = led_counter[ 25:19 ] == 0;
	`endif

	//
	// USB CDC ACM
	//

    // uart pipeline in and out
    localparam PipeSpec = `PS_d8s;
    wire [`P_m( PipeSpec ):0 ] pipe;

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

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

        // uart pipeline, in and out
        .pipe_in( pipe ),
        .pipe_out( pipe )

        //.debug( debug )
    );

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

endmodule
module clock_pll
(
    input CLKI, // 8 MHz, 0 deg
    output CLKOP, // 48 MHz, 0 deg
    output locked
);
(* FREQUENCY_PIN_CLKI="8" *)
(* FREQUENCY_PIN_CLKOP="48" *)
(* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *)
EHXPLLL #(
        .PLLRST_ENA("DISABLED"),
        .INTFB_WAKE("DISABLED"),
        .STDBY_ENABLE("DISABLED"),
        .DPHASE_SOURCE("DISABLED"),
        .OUTDIVIDER_MUXA("DIVA"),
        .OUTDIVIDER_MUXB("DIVB"),
        .OUTDIVIDER_MUXC("DIVC"),
        .OUTDIVIDER_MUXD("DIVD"),
        .CLKI_DIV(1),
        .CLKOP_ENABLE("ENABLED"),
        .CLKOP_DIV(12),
        .CLKOP_CPHASE(5),
        .CLKOP_FPHASE(0),
        .FEEDBK_PATH("CLKOP"),
        .CLKFB_DIV(6)
    ) pll_i (
        .RST(1'b0),
        .STDBY(1'b0),
        .CLKI(CLKI),
        .CLKOP(CLKOP),
        .CLKFB(CLKOP),
        .CLKINTFB(),
        .PHASESEL0(1'b0),
        .PHASESEL1(1'b0),
        .PHASEDIR(1'b1),
        .PHASESTEP(1'b1),
        .PHASELOADREG(1'b1),
        .PLLWAKESYNC(1'b0),
        .ENCLKOP(1'b0),
        .LOCK(locked)
	);
endmodule
module simpleuart (
	input clk,
	input resetn,

	output ser_tx,
	input  ser_rx,

	input   [3:0] reg_div_we,
	input  [31:0] reg_div_di,
	output [31:0] reg_div_do,

	input         reg_dat_we,
	input         reg_dat_re,
	input  [31:0] reg_dat_di,
	output [31:0] reg_dat_do,
	output        reg_dat_wait
);
	reg [31:0] cfg_divider;

	reg [3:0] recv_state;
	reg [31:0] recv_divcnt;
	reg [7:0] recv_pattern;
	reg [7:0] recv_buf_data;
	reg recv_buf_valid;

	reg [9:0] send_pattern;
	reg [3:0] send_bitcnt;
	reg [31:0] send_divcnt;
	reg send_dummy;

	assign reg_div_do = cfg_divider;

	assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
	assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;

	always @(posedge clk) begin
		if (!resetn) begin
			cfg_divider <= 1;
		end else begin
			if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
			if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
			if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
			if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
		end
	end

	always @(posedge clk) begin
		if (!resetn) begin
			recv_state <= 0;
			recv_divcnt <= 0;
			recv_pattern <= 0;
			recv_buf_data <= 0;
			recv_buf_valid <= 0;
		end else begin
			recv_divcnt <= recv_divcnt + 1;
			if (reg_dat_re)
				recv_buf_valid <= 0;
			case (recv_state)
				0: begin
					if (!ser_rx)
						recv_state <= 1;
					recv_divcnt <= 0;
				end
				1: begin
					if (2*recv_divcnt > cfg_divider) begin
						recv_state <= 2;
						recv_divcnt <= 0;
					end
				end
				10: begin
					if (recv_divcnt > cfg_divider) begin
						recv_buf_data <= recv_pattern;
						recv_buf_valid <= 1;
						recv_state <= 0;
					end
				end
				default: begin
					if (recv_divcnt > cfg_divider) begin
						recv_pattern <= {ser_rx, recv_pattern[7:1]};
						recv_state <= recv_state + 1;
						recv_divcnt <= 0;
					end
				end
			endcase
		end
	end

	assign ser_tx = send_pattern[0];

	always @(posedge clk) begin
		if (reg_div_we)
			send_dummy <= 1;
		send_divcnt <= send_divcnt + 1;
		if (!resetn) begin
			send_pattern <= ~0;
			send_bitcnt <= 0;
			send_divcnt <= 0;
			send_dummy <= 1;
		end else begin
			if (send_dummy && !send_bitcnt) begin
				send_pattern <= ~0;
				send_bitcnt <= 15;
				send_divcnt <= 0;
				send_dummy <= 0;
			end else
			if (reg_dat_we && !send_bitcnt) begin
				send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
				send_bitcnt <= 10;
				send_divcnt <= 0;
			end else
			if (send_divcnt > cfg_divider && send_bitcnt) begin
				send_pattern <= {1'b1, send_pattern[9:1]};
				send_bitcnt <= send_bitcnt - 1;
				send_divcnt <= 0;
			end
		end
	end
endmodule
module testbench();

	reg clk;

	always #5 clk = (clk === 1'b0);

	initial begin
		$dumpfile("testbench.vcd");
		$dumpvars(0, testbench);

		repeat (10) begin
			repeat (50000) @(posedge clk);
			$display("+50000 cycles");
		end
		$finish;
	end

	wire [7:0] led;

    wire uart_tx;
    reg  uart_rx;

	always @(led) begin
		#1 $display("%b", led);
	end

	led_uart_soc uut (
		.clk      (clk      ),
		.led      (led      ),
        .uart_rx  ( uart_rx ),
        .uart_tx  ( uart_tx )
	);
endmodule
module top(
    input clk,
    output [7:0] led,
    inout [7:0] pmod
);

wire clk;
wire [7:0] int_led;

wire clock_48mhz;
clock_pll c_pll (.CLKI( clk ), .CLKOP( clock_48mhz ));


led_uart_soc soc(
    .clk(clock_48mhz),
    .led(int_led),
    .uart_tx(pmod[0]),
    .uart_rx(pmod[1])
);

assign led = ~int_led;

endmodule
module pipe_fifo #( parameter PipeSpec = `PS_d8s, parameter MemoryWidth = 3 ) (
        input clock,
        input reset,

        inout [`P_m(PipeSpec):0] pipe_in,
        inout [`P_m(PipeSpec):0] pipe_out
    );

    wire [`P_Payload_m(PipeSpec):0] in_payload;
    wire in_valid;
    wire in_ready;
    wire [`P_Payload_m(PipeSpec):0] out_payload;
    wire out_valid;
    wire out_ready;

    p_unpack_payload #( .PipeSpec(PipeSpec) ) p_up_p( .pipe(pipe_in), .payload(in_payload) );
    p_unpack_valid_ready #( .PipeSpec(PipeSpec) ) p_up_vr( .pipe(pipe_in), .valid(in_valid), .ready(in_ready) );
    p_pack_payload   #( .PipeSpec(PipeSpec) ) p_p_p( .payload(out_payload), .pipe(pipe_out) );
    p_pack_valid_ready  #( .PipeSpec(PipeSpec) ) p_p_vr( .valid(out_valid), .ready(out_ready), .pipe(pipe_out) );

    // Store the whole payload
    reg [`P_Payload_m(PipeSpec):0] memory [0:1<<MemoryWidth];

    // MemoryWidth + 1 (extra rX, wX, so read != write when full)
    reg [MemoryWidth:0] read_address;
    reg [MemoryWidth:0] write_address;

    // Are we ready? There's room if r != w or rX == wX
    assign in_ready = ( read_address[MemoryWidth] == write_address[MemoryWidth] ) ||
                      ( read_address[MemoryWidth-1:0] != write_address[MemoryWidth-1:0] );

    // Write logic
    always @(posedge clock) begin
        if ( reset ) begin
            write_address <= 0;
        end else begin
            if ( in_ready ) begin
                if ( in_valid ) begin
                    memory[ write_address[MemoryWidth-1:0] ] <= in_payload;
                    write_address <= write_address + 1;
                end
            end
        end
    end

    // Are we valid? (any time the whole read and write addresses are not exactly equal)
    assign out_valid = ( read_address != write_address );

    // Read logic
    always @(posedge clock) begin
        if ( reset ) begin
            read_address <= 0;
        end else begin
            if ( out_valid ) begin
                if ( out_ready ) begin
                    read_address <= read_address + 1;
                end
            end
        end
    end

    assign out_payload = ( out_valid ) ? memory[ read_address[MemoryWidth-1:0] ] : 0;

endmodule
module p_pack_payload #( parameter PipeSpec = `PS_def ) (
        input [`P_Payload_w(PipeSpec)-1:0] payload,
        inout [`P_m(PipeSpec):0]   pipe
    );

    assign pipe[`P_Payload_m(PipeSpec):0] = payload;

endmodule
module p_unpack_payload #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]       pipe,
        output [`P_Payload_w(PipeSpec)-1:0] payload
    );

    assign payload  = pipe[`P_Payload_m(PipeSpec):0];

endmodule
module p_pack_valid_ready #( parameter PipeSpec = `PS_def ) (
        input                    valid,
        output                   ready,
        inout [`P_m(PipeSpec):0] pipe
    );

    assign pipe[ `P_Valid_b(PipeSpec) ] = valid;
    assign ready = pipe[ `P_Ready_b(PipeSpec) ];

endmodule
module p_pack_valid #( parameter PipeSpec = `PS_def ) (
        input                    valid,
        inout [`P_m(PipeSpec):0] pipe
    );

    assign pipe[ `P_Valid_b(PipeSpec) ] = valid;

endmodule
module p_unpack_valid_ready #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        output                   valid,
        input                    ready
    );

    assign valid = pipe[ `P_Valid_b(PipeSpec) ];
    assign pipe[ `P_Ready_b(PipeSpec) ] = ready;

endmodule
module p_monitor_valid_ready #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        output                   valid,
        output                    ready
    );

    assign valid = pipe[ `P_Valid_b(PipeSpec) ];
    assign ready = pipe[ `P_Ready_b(PipeSpec) ];

endmodule
module p_pack_start_stop #( parameter PipeSpec = `PS_def ) (
        input                    start,
        input                    stop,
        inout [`P_m(PipeSpec):0] pipe
    );

    generate
        if ( `P_Start_w( PipeSpec ) )
            assign pipe[ `P_Start_b(PipeSpec) ] = start;
        if ( `P_Stop_w( PipeSpec ) )
            assign pipe[ `P_Stop_b(PipeSpec) ]  = stop;
    endgenerate

endmodule
module p_unpack_start_stop #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        output                   start,
        output                   stop
    );

    generate
        if ( `P_Start_w( PipeSpec ) )
            assign start = pipe[ `P_Start_b(PipeSpec) ];
        else
            assign start = 1'B0;
        if ( `P_Stop_w( PipeSpec ) )
            assign stop  = pipe[ `P_Stop_b(PipeSpec) ];
        else
            assign stop = 1'B0;
    endgenerate

endmodule
module p_pack_data #( parameter PipeSpec = `PS_def ) (
        input [`P_Data_w(PipeSpec)-1:0] data,
        inout [`P_m(PipeSpec):0]      pipe
    );

    generate
        if ( `P_Data_w( PipeSpec ) )
            assign pipe[ `P_Data_m(PipeSpec):`P_Data_l(PipeSpec) ] = data;
    endgenerate

endmodule
module p_unpack_data #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]       pipe,
        output [`P_Data_w(PipeSpec)-1:0] data
    );

    generate
        if ( `P_Data_w( PipeSpec ) )
            assign data  = pipe[ `P_Data_m(PipeSpec):`P_Data_l(PipeSpec) ];
    endgenerate

endmodule
module p_pack_data_size #( parameter PipeSpec = `PS_def ) (
        input [`P_DataSize_w(PipeSpec)-1:0] data_size,
        inout [`P_m(PipeSpec):0]          pipe
    );

    generate
        if ( `P_DataSize_w( PipeSpec ) )
            assign pipe[`P_DataSize_m(PipeSpec):`P_DataSize_l(PipeSpec)] = data_size;
    endgenerate

endmodule
module p_unpack_data_size #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]          pipe,
        output [`P_DataSize_w(PipeSpec)-1:0] data_size
    );

    generate
        if ( `P_DataSize_w( PipeSpec ) )
            assign data_size = pipe[`P_DataSize_m(PipeSpec):`P_DataSize_l(PipeSpec)];
        else
            assign data_size = 0;
    endgenerate

endmodule
module p_pack_rev_valid_ready #( parameter PipeSpec = `PS_def ) (
        output                   rev_valid,
        input                    rev_ready,
        inout [`P_m(PipeSpec):0] pipe
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        assign rev_valid = pipe[ `P_RevValid_l(PipeSpec) ];
        assign pipe[ `P_RevReady_l(PipeSpec) ] = rev_ready;
    end

endmodule
module p_pack_rev_ready #( parameter PipeSpec = `PS_def ) (
        input                    rev_ready,
        inout [`P_m(PipeSpec):0] pipe
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        assign pipe[ `P_RevReady_l(PipeSpec) ] = rev_ready;
    end

endmodule
module p_unpack_rev_valid_ready #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        input                    rev_valid,
        output                   rev_ready
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        assign pipe[ `P_RevValid_l(PipeSpec) ] = rev_valid;
        assign rev_ready = pipe[ `P_RevReady_l(PipeSpec) ];
    end

endmodule
module p_monitor_rev_valid_ready #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        output                   rev_valid,
        output                   rev_ready
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        assign rev_valid = pipe[ `P_RevValid_l(PipeSpec) ];
        assign rev_ready = pipe[ `P_RevReady_l(PipeSpec) ];
    end

endmodule
module p_pack_rev_start_stop #( parameter PipeSpec = `PS_def ) (
        output                   rev_start,
        output                   rev_stop,
        inout [`P_m(PipeSpec):0] pipe
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevStart_w( PipeSpec ) )
            assign rev_start = pipe[ `P_RevStart_l(PipeSpec) ];
        if ( `P_Stop_w( PipeSpec ) )
            assign rev_stop  = pipe[ `P_RevStop_l(PipeSpec) ];
    end

endmodule
module p_unpack_rev_start_stop #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        input                    rev_start,
        input                    rev_stop
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevStart_w( PipeSpec ) )
            assign pipe[ `P_RevStart_l(PipeSpec) ] = rev_start;
        if ( `P_RevStop_w( PipeSpec ) )
            assign pipe[ `P_RevStop_l(PipeSpec) ]  = rev_stop;
    end

endmodule
module p_monitor_rev_start_stop #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        output                   rev_start,
        output                   rev_stop
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevStart_w( PipeSpec ) )
            assign rev_start = pipe[ `P_RevStart_l(PipeSpec) ];
        if ( `P_Stop_w( PipeSpec ) )
            assign rev_stop  = pipe[ `P_RevStop_l(PipeSpec) ];
    end

endmodule
module p_pack_rev_data #( parameter PipeSpec = `PS_def ) (
        output [`P_RevData_w(PipeSpec)-1:0] rev_data,
        inout [`P_m(PipeSpec):0]      pipe
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevData_w( PipeSpec ) )
            assign rev_data  = pipe[ `P_RevData_m(PipeSpec):`P_RevData_l(PipeSpec) ];
    end

endmodule
module p_unpack_rev_data #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]       pipe,
        input [`P_RevData_w(PipeSpec)-1:0] rev_data
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevData_w( PipeSpec ) )
            assign pipe[ `P_RevData_m(PipeSpec):`P_RevData_l(PipeSpec) ] = rev_data;
    end

endmodule
module p_monitor_rev_data #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]            pipe,
        output [`P_RevData_w(PipeSpec)-1:0] rev_data
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevData_w( PipeSpec ) )
            assign rev_data  = pipe[ `P_RevData_m(PipeSpec):`P_RevData_l(PipeSpec) ];
    end

endmodule
module p_pack_rev_data_size #( parameter PipeSpec = `PS_def ) (
        output [`P_RevDataSize_w(PipeSpec)-1:0] rev_data_size,
        inout [`P_m(PipeSpec):0]          pipe
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevDataSize_w( PipeSpec ) )
            assign rev_data_size = pipe[`P_RevDataSize_m(PipeSpec):`P_RevDataSize_l(PipeSpec)];
        else
            assign rev_data_size = 0;
    end

endmodule
module p_unpack_rev_data_size #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]            pipe,
        input [`P_RevDataSize_w(PipeSpec)-1:0] rev_data_size
    );

    if ( `PS_Reverse_v( PipeSpec ) ) begin
        if ( `P_RevDataSize_w( PipeSpec ) )
            assign pipe[`P_RevDataSize_m(PipeSpec):`P_RevDataSize_l(PipeSpec)] = rev_data_size;
    end

endmodule
module p_pack_command #( parameter PipeSpec = `PS_def ) (
        input [`P_Command_w(PipeSpec)-1:0] command,
        inout [`P_m(PipeSpec):0]      pipe
    );

    generate
        if ( `P_Command_w( PipeSpec ) )
            assign pipe[ `P_Command_m(PipeSpec):`P_Command_l(PipeSpec) ] = command;
    endgenerate

endmodule
module p_unpack_command #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]       pipe,
        output [`P_Command_w(PipeSpec)-1:0] command
    );

    generate
        if ( `P_Command_w( PipeSpec ) )
            assign command  = pipe[ `P_Command_m(PipeSpec):`P_Command_l(PipeSpec) ];
    endgenerate

endmodule
module p_pack_result #( parameter PipeSpec = `PS_def ) (
        output [`P_Result_w(PipeSpec)-1:0] result,
        inout [`P_m(PipeSpec):0]      pipe
    );

    generate
        if ( `P_Result_w( PipeSpec ) )
            assign result  = pipe[ `P_Result_m(PipeSpec):`P_Result_l(PipeSpec) ];
    endgenerate

endmodule
module p_unpack_result #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]       pipe,
        input [`P_Result_w(PipeSpec)-1:0] result
    );

    generate
        if ( `P_Result_w( PipeSpec ) )
            assign pipe[ `P_Result_m(PipeSpec):`P_Result_l(PipeSpec) ] = result;
    endgenerate

endmodule
module p_monitor_result #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]      pipe,
        output [`P_Result_w(PipeSpec)-1:0] result
    );

    generate
        if ( `P_Result_w( PipeSpec ) )
            assign result  = pipe[ `P_Result_m(PipeSpec):`P_Result_l(PipeSpec) ];
    endgenerate

endmodule
module p_pack_request #( parameter PipeSpec = `PS_def ) (
        output [`P_Request_w(PipeSpec)-1:0] request,
        inout [`P_m(PipeSpec):0]      pipe
    );

    generate
        if ( `P_Request_w( PipeSpec ) )
            assign request  = pipe[ `P_Request_m(PipeSpec):`P_Request_l(PipeSpec) ];
    endgenerate

endmodule
module p_unpack_request #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0]       pipe,
        input [`P_Request_w(PipeSpec)-1:0] request
    );

    generate
        if ( `P_Request_w( PipeSpec ) )
            assign pipe[ `P_Request_m(PipeSpec):`P_Request_l(PipeSpec) ] = request;
    endgenerate

endmodule
module p_info #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe,
        output             start,
        output             stop,
        output [`P_Data_m(PipeSpec):0] data,
        output             valid,
        output             ready
    );
    generate
        if ( `P_Start_w( PipeSpec ) )
            assign start = pipe[ `P_Start_b(PipeSpec) ];
        else
            assign start = 0;
        if ( `P_Stop_w( PipeSpec ) )
            assign stop  = pipe[ `P_Stop_b(PipeSpec) ];
        else
            assign stop = 0;
    endgenerate

    assign data  = pipe[ `P_Data_m(PipeSpec):`P_Data_l(PipeSpec) ];
    assign valid = pipe[ `P_Valid_b(PipeSpec) ];
    assign ready = pipe[ `P_Ready_b(PipeSpec) ];

endmodule
module p_pack_ssdvrp #( parameter PipeSpec = `PS_def ) (
        input                               start,
        input                               stop,
        input [`P_Data_w(PipeSpec)-1:0]     data,
        input                               valid,
        output                              ready,

        inout [`P_w(PipeSpec)-1:0]          pipe
    );

    generate
        if ( `P_Start_w( PipeSpec ) )
            assign pipe[ `P_Start_b(PipeSpec) ] = start;
        if ( `P_Stop_w( PipeSpec ) )
            assign pipe[ `P_Stop_b(PipeSpec) ]  = stop;
    endgenerate

    assign pipe[ `P_Data_w(PipeSpec)-1:`P_Data_l(PipeSpec) ] = data;
    assign pipe[ `P_Valid_b(PipeSpec) ] = valid;
    assign ready = pipe[ `P_Ready_b(PipeSpec) ];

endmodule
module p_unpack_pssdvr #( parameter PipeSpec = `PS_def ) (
        inout [`P_w(PipeSpec)-1:0]           pipe,

        output                               start,
        output                               stop,
        output [`P_Data_w(PipeSpec)-1:0]     data,
        output                               valid,
        input                                ready
    );

    generate
        if ( `P_Start_w( PipeSpec ) )
            assign start = pipe[ `P_Start_b(PipeSpec) ];
        if ( `P_Stop_w( PipeSpec ) )
            assign stop  = pipe[ `P_Stop_b(PipeSpec) ];
    endgenerate

    assign data  = pipe[ `P_Data_m(PipeSpec):`P_Data_l(PipeSpec) ];
    assign valid = pipe[ `P_Valid_b(PipeSpec) ];
    assign pipe[ `P_Ready_b(PipeSpec) ] = ready;

endmodule
module p_pack_dvr #( parameter PipeSpec = `PS_def ) (
        input [`P_Data_w(PipeSpec)-1:0]     data,
        input                               valid,
        output                              ready,

        inout [`P_w(PipeSpec)-1:0]          pipe
    );

    assign pipe[ `P_Data_w(PipeSpec)-1:`P_Data_l(PipeSpec) ] = data;
    assign pipe[ `P_Valid_b(PipeSpec) ] = valid;
    assign ready = pipe[ `P_Ready_b(PipeSpec) ];

endmodule
module p_unpack_dvr #( parameter PipeSpec = `PS_def ) (
        inout [`P_w(PipeSpec)-1:0]           pipe,

        output [`P_Data_w(PipeSpec)-1:0]     data,
        output                               valid,
        input                                ready
    );

    assign data  = pipe[ `P_Data_m(PipeSpec):`P_Data_l(PipeSpec) ];
    assign valid = pipe[ `P_Valid_b(PipeSpec) ];
    assign pipe[ `P_Ready_b(PipeSpec) ] = ready;

endmodule
module p_pack #( parameter PipeSpec = `PS_def ) (
        input                               start,
        input                               stop,
        input [`P_Data_w(PipeSpec)-1:0]     data,
        input [`P_DataSize_w(PipeSpec)-1:0] datasize,
        input                               valid,
        output                              ready,

        inout [`P_w(PipeSpec)-1:0]            pipe
    );

    generate
        if ( `P_Start_w( PipeSpec ) )
            assign pipe[ `P_Start_b(PipeSpec) ] = start;
        if ( `P_Stop_w( PipeSpec ) )
            assign pipe[ `P_Stop_b(PipeSpec) ]  = stop;
    endgenerate

    generate
        if ( `P_DataSize_w( PipeSpec ) )
            assign pipe[ `P_DataSize_m(PipeSpec):`P_DataSize_l(PipeSpec) ] = datasize;
    endgenerate

    assign pipe[ `P_Data_m(PipeSpec):`P_Data_l(PipeSpec) ] = data;
    assign pipe[ `P_Valid_b(PipeSpec) ] = valid;
    assign ready = pipe[ `P_Ready_b(PipeSpec) ];

endmodule
module p_unpack #( parameter PipeSpec = `PS_def ) (
        inout [`P_w(PipeSpec)-1:0]           pipe,

        output                               start,
        output                               stop,
        output [`P_Data_w(PipeSpec)-1:0]     data,
        output [`P_DataSize_w(PipeSpec)-1:0] datasize,
        output                               valid,
        input                                ready
    );

    generate
        if ( `P_Start_w( PipeSpec ) )
            assign start = pipe[ `P_Start_b(PipeSpec) ];
        if ( `P_Stop_w( PipeSpec ) )
            assign stop  = pipe[ `P_Stop_b(PipeSpec) ];
    endgenerate

    generate
        if ( `P_DataSize_w( PipeSpec ) )
            assign datasize = pipe[ `P_DataSize_m(PipeSpec):`P_DataSize_l(PipeSpec) ];
    endgenerate

    assign data  = pipe[ `P_Data_m(PipeSpec):`P_Data_l(PipeSpec) ];
    assign valid = pipe[ `P_Valid_b(PipeSpec) ];
    assign pipe[ `P_Ready_b(PipeSpec) ] = ready;

endmodule
module p_null_source #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe_out
    );

    // doing nothing
    assign pipe_out[`P_Payload_m(PipeSpec):0] = 0;
    assign pipe_out[`P_Valid_b(PipeSpec)] = 0;

endmodule
module p_null_sink #( parameter PipeSpec = `PS_def ) (
        inout [`P_m(PipeSpec):0] pipe_in
    );

    // receiving everything
    assign pipe_in[ `P_Ready_b(PipeSpec) ] = 1;

endmodule
module p_pipe2data #( parameter PipeSpec = `PS_def ) (
        input clock,
        input reset,

        inout [`P_m(PipeSpec):0] pipe,

        output [`P_Data_m(PipeSpec):0] data,
        output data_valid
    );

    wire [`P_Data_m(PipeSpec):0] in_data;
    wire in_valid;
    reg  in_ready;

    p_unpack_valid_ready #( .PipeSpec(PipeSpec) ) p_u_v( pipe, in_valid, in_ready );
    p_unpack_data #( .PipeSpec(PipeSpec) ) p_u_d( pipe, in_data  );

    reg [`P_Data_m(PipeSpec):0] p2d_data;
    reg                         p2d_data_valid;

    always @(posedge clock) begin
        if ( reset ) begin
            p2d_data <= 0;
            p2d_data_valid <= 0;
            in_ready <= 1;
        end else begin
            if ( in_valid ) begin
                p2d_data <= in_data;
                p2d_data_valid <= 1;
            end
        end
    end

    assign data = p2d_data;
    assign data_valid = p2d_data_valid;

endmodule
module p_data2pipe #( parameter PipeSpec = `PS_def ) (
        input clock,
        input reset,

        input send,

        input [`P_Data_m(PipeSpec):0] data,
        input data_valid,

        inout [`P_m(PipeSpec):0] pipe
    );

    reg [`P_Data_m(PipeSpec):0] out_data;
    reg out_valid;
    wire out_ready;
    reg out_start;
    reg out_stop;

    reg send_previous;

    p_pack_valid_ready #( .PipeSpec(PipeSpec) ) p_p_v( out_valid, out_ready, pipe );
    p_pack_data #( .PipeSpec(PipeSpec) ) p_p_d( out_data, pipe );
    p_pack_start_stop #( .PipeSpec(PipeSpec) ) p_p_ss( out_start, out_stop, pipe );

    reg [`P_Data_m(PipeSpec):0] transferred_data;
    reg transferred_any;

    always @(posedge clock) begin
        if ( reset ) begin
            out_data <= 0;
            out_valid <= 0;
            out_start <= 0;
            out_stop <= 0;
            transferred_data <= 0;
            transferred_any <= 0;
            send_previous <= 0;
        end else begin
            send_previous <= send;
            if ( out_valid && out_ready ) begin
                transferred_data <= out_data;
                if ( data_valid && (( data != out_data ) || ( send && ~send_previous ) ) ) begin
                    out_data <= data;
                end else begin
                    out_data <= 0;
                    out_valid <= 0;
                    out_start <= 0;
                    out_stop <= 0;
                end
            end else begin
                if ( data_valid ) begin
                    if ( ( data != transferred_data ) || !transferred_any ||  ( send && ~send_previous ) ) begin
                        transferred_any <= 1;
                        out_start <= 1;
                        out_stop <= 1;
                        out_data <= data;
                        out_valid <= 1;
                    end else begin
                        out_start <= 0;
                        out_stop <= 0;
                        out_data <= 0;
                        out_valid <= 0;
                    end
                end
            end
        end
    end

endmodule
module add_accum( clock, reset, x, valid, accumsum );
    input clock;
    input reset;
    input [3:0] x;
    input valid;
    output reg [7:0] accumsum;

    always @(posedge clock) begin
        if ( reset )
            accumsum <= 0;
        else
            if ( valid )
                accumsum <= accumsum + x;
    end
endmodule
module add_sat( x, y, satsum );
  parameter limit = 8'H0A;
  input [3:0] x;
  input [3:0] y;
  output reg [4:0] satsum;
  always @(*) begin
    if ( x + y > limit)
      satsum = limit;
    else
      satsum = x + y;
    end
endmodule
module image_spec_check( input [31:0] in, output [31:0] out );

    localparam IS = `IS( 0, 0, 100, 100, 0, 1, 0, 8, 8, 8, 0, 0 );

    localparam X_l = `IS_X_l;
    localparam X_m = `IS_X_m;

    localparam Y_l = `IS_X_l;

    assign out = X_l;

    localparam ISw = `IS_w;

    assign out = ISw;

    localparam PS = `IS_PIPE_SPEC( IS );

    assign out = PS;

    localparam P_D_w = `P_Data_w( PS );
    assign out = P_D_w;

    localparam P_DS_w = `P_DataSize_w( PS );
    assign out = P_DS_w;

    localparam P_RDS_w = `P_RevDataSize_w( PS );
    assign out = P_RDS_w;

    localparam P_w = `P_w( PS );
    assign out = P_w;

    localparam Iw = `I_w( IS );
    assign out = Iw;

endmodule
module uart_out  #( parameter PipeSpec = `PS_DATA( 8 ), parameter ClockFrequency = 12000000, parameter BaudRate = 9600 ) (
        input clock,
        input reset,

        inout [`P_w(PipeSpec)-1:0] pipe_in,

        output pin_tx
    );

    wire [`P_Data_w(PipeSpec)-1:0] in_data;
    wire                     in_valid;
    wire                     in_ready;

    p_unpack_data        #( .PipeSpec( PipeSpec ) ) in_unpack_d ( pipe_in, in_data);
    p_unpack_valid_ready #( .PipeSpec( PipeSpec ) ) in_unpack_vr( pipe_in, in_valid, in_ready );

    // start and stop signals are ignored - packetization has to be escaped
    uart_out_np #( .ClockFrequency( ClockFrequency ), .BaudRate( BaudRate ) )  u_o_np (
            clock, reset,

            in_data, in_valid, in_ready,

            pin_tx
        );

endmodule
module uart_out_np #( parameter ClockFrequency = 12000000, parameter BaudRate = 9600 )(
        input clock,
        input reset,

        input [7:0] out_data,
        input       out_valid,
        output      out_ready,

        output uart_tx
    );

    // Assert out_valid for (at least) one clock cycle to start transmission of out_data
    // out_data is latched so that it doesn't have to stay valid while it is being sent

    generate
        if( ClockFrequency < BaudRate * 8 && ( ClockFrequency % BaudRate != 0 ) ) ASSERTION_ERROR PARAMETER_OUT_OF_RANGE("Frequency incompatible with requested BaudRate rate");
    endgenerate

    `ifdef SIMULATION
        wire BitTick = 1'b1;  // output one bit per clock cycle
    `else
        wire BitTick;
        uart_out_baudrate_gen #( ClockFrequency, BaudRate ) tickgen( .clock( clock ), .enable( ~out_ready ), .tick( BitTick ) );
    `endif

    reg [3:0] uart_state = 0;
    wire uart_ready = (uart_state==0);
    assign out_ready = uart_ready;

    reg [7:0] uart_shift = 0;
    always @(posedge clock)
    begin
        if ( reset ) begin
            uart_state <= 0;
        end else begin
            if( uart_ready & out_valid )
                uart_shift <= out_data;
            else
                if(uart_state[3] & BitTick)
                    uart_shift <= (uart_shift >> 1);

            case(uart_state)
                4'b0000: if(out_valid) uart_state <= 4'b0100;
                4'b0100: if(BitTick) uart_state <= 4'b1000;  // start bit
                4'b1000: if(BitTick) uart_state <= 4'b1001;  // bit 0
                4'b1001: if(BitTick) uart_state <= 4'b1010;  // bit 1
                4'b1010: if(BitTick) uart_state <= 4'b1011;  // bit 2
                4'b1011: if(BitTick) uart_state <= 4'b1100;  // bit 3
                4'b1100: if(BitTick) uart_state <= 4'b1101;  // bit 4
                4'b1101: if(BitTick) uart_state <= 4'b1110;  // bit 5
                4'b1110: if(BitTick) uart_state <= 4'b1111;  // bit 6
                4'b1111: if(BitTick) uart_state <= 4'b0010;  // bit 7
                4'b0010: if(BitTick) uart_state <= 4'b0000;  // stop1  -  state<=4'b0011 for stop2
                4'b0011: if(BitTick) uart_state <= 4'b0000;  // stop2
                default: if(BitTick) uart_state <= 4'b0000;
            endcase
        end
    end

    assign uart_tx = (uart_state<4) | (uart_state[3] & uart_shift[0]);  // put together the start, data and stop bits

endmodule
module uart_out_baudrate_gen #( parameter ClockFrequency = 12000000, parameter BaudRate = 9600,  parameter Oversampling = 1 )(
        input clock, enable,
        output tick  // generate a tick at the specified baud rate * oversampling
    );

    // A quicky for an int log2
    function integer log2(input integer v); begin
        log2=0;
        while(v>>log2)
            log2=log2+1;
        end
    endfunction

    localparam Count = (ClockFrequency/BaudRate); // for the oversampling = 1.  Um... I don't know for what.
    localparam CountWidth = log2(Count) + 2; // don't want to accidentally fill it with a load!

    reg [CountWidth-1:0] Counter = 0;

    always @(posedge clock)
        if( !enable )
            Counter <= Count - Oversampling - Oversampling - 1;
        else if ( Counter[CountWidth-1] )
            Counter <= Counter + Count - Oversampling;
        else
            Counter <= Counter - Oversampling;

    assign tick = Counter[CountWidth-1];
endmodule
module uart_baudrate_gen_Orig(
        input clock, enable,
        output tick  // generate a tick at the specified baud rate * oversampling
    );

    parameter ClockFrequency = 25000000;
    parameter BaudRate = 115200;
    parameter Oversampling = 1;

    // A quicky for an int log2
    function integer log2(input integer v); begin
        log2=0;
        while(v>>log2)
            log2=log2+1;
        end
    endfunction

    localparam AccWidth = log2(ClockFrequency/BaudRate)+8;  // +/- 2% max timing error over a byte
    reg [AccWidth:0] Acc = 0;
    localparam ShiftLimiter = log2(BaudRate*Oversampling >> (31-AccWidth));  // this makes sure Inc calculation doesn't overflow
    localparam Inc = ((BaudRate*Oversampling << (AccWidth-ShiftLimiter))+(ClockFrequency>>(ShiftLimiter+1)))/(ClockFrequency>>ShiftLimiter);

    localparam ActualCounter = (1<<AccWidth);
    localparam ActualDivider = ActualCounter/Inc;
    localparam ActualErrorCounts = Inc*ActualDivider-ActualCounter;
    localparam ActualErrorPercentage = 100 * ActualErrorCounts / ActualCounter;

    always @(posedge clock)
        if(enable)
            Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0];
        else
            Acc <= Inc[AccWidth:0];

    assign tick = Acc[AccWidth];
endmodule