dakies/OSS_Verilog huggingface dataset:
module vita_pkt_gen
  (input clk, input reset, input clear,
   input [15:0] len,
   output [35:0] data_o, output src_rdy_o, input dst_rdy_i);

   reg [15:0] 	     state;
   reg [31:0] 	     seq, data;
   
   wire 	     sof = (state == 0);
   wire 	     eof = (state == (len-1));
   wire 	     consume = src_rdy_o & dst_rdy_i;
   
   assign src_rdy_o = 1;

   always @(posedge clk)
     if(reset | clear)
       begin
	  state <= 0;
	  seq <= 0;
       end
     else
       if(consume)
	 if(eof)
	   begin
	      state <= 0;
	      seq <= seq + 1;
	   end
	 else
	   state <= state + 1;

   always @*
     case(state)
       0 :   data <= {24'h000,seq[3:0],len};
       1 :   data <= seq;
       default : data <= {~state,state};
     endcase // case (state)

   assign data_o = {2'b00, eof, sof, data};
   
endmodule // vita_pkt_gen
module trigger_context_pkt
  #(parameter BASE=0)
   (input clk, input reset, input clear,
    input set_stb, input [7:0] set_addr, input [31:0] set_data,
    input packet_consumed, output reg trigger);

   wire [23:0] cycles;
   wire [15:0] packets;
   wire [6:0]  dummy1;
   wire [14:0] dummy2;
   wire        enable_cycle, enable_consumed;
   reg [30:0]  cycle_count, packet_count;

   
   setting_reg #(.my_addr(BASE+4), .at_reset(0)) sr_cycles
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out({enable_cycle,dummy1,cycles}),.changed());

   setting_reg #(.my_addr(BASE+5), .at_reset(0)) sr_packets
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out({enable_consumed,dummy2,packets}),.changed());

   always @(posedge clk)
     if(reset | clear)
       cycle_count <= 0;
     else
       if(trigger)
	 cycle_count <= 0;
       else if(enable_cycle)
	 cycle_count <= cycle_count + 1;

   always @(posedge clk)
     if(reset | clear)
       packet_count <= 0;
     else
       if(trigger)
	 packet_count <= 0;
       else if(packet_consumed & enable_consumed)
	 packet_count <= packet_count + 1;

   always @(posedge clk)
     if(reset | clear)
       trigger <= 0;
     else
       if((cycle_count > cycles)|(packet_count > packets))
	 trigger <= 1;
       else
	 trigger <= 0;
   
endmodule // trigger_context_pkt
module gen_context_pkt
  #(parameter PROT_ENG_FLAGS=1,
    parameter DSP_NUMBER=0)
   (input clk, input reset, input clear,
    input trigger, output sent,
    input [31:0] streamid,
    input [63:0] vita_time,
    input [31:0] message,
    input [31:0] seqnum,
    output [35:0] data_o, output src_rdy_o, input dst_rdy_i);
   
   localparam CTXT_IDLE = 0;
   localparam CTXT_PROT_ENG = 1;
   localparam CTXT_HEADER = 2;
   localparam CTXT_STREAMID = 3;
   localparam CTXT_TICS = 4;
   localparam CTXT_TICS2 = 5;
   localparam CTXT_MESSAGE = 6;
   localparam CTXT_FLOWCTRL = 7;
   localparam CTXT_DONE = 8;

   reg [33:0] 	 data_int;
   wire 	 src_rdy_int, dst_rdy_int;
   reg [3:0] 	 seqno;
   reg [3:0] 	 ctxt_state;
   reg [63:0] 	 err_time;
   reg [31:0] 	 stored_message;
   
   always @(posedge clk)
     if(reset | clear)
       stored_message <= 0;
     else
       if(trigger)
	 stored_message <= message;
       else if(ctxt_state == CTXT_DONE)
	 stored_message <= 0;

   // Don't want to clear most of this to avoid getting stuck with a half packet in the pipe
   always @(posedge clk)
     if(reset)
       begin
	  ctxt_state <= CTXT_IDLE;
	  seqno <= 0;
       end
     else
       case(ctxt_state)
	 CTXT_IDLE :
	   if(trigger)
	     begin
		err_time <= vita_time;
		if(PROT_ENG_FLAGS)
		  ctxt_state <= CTXT_PROT_ENG;
		else
		  ctxt_state <= CTXT_HEADER;
	     end
	 
	 CTXT_DONE :
	   begin
	      ctxt_state <= CTXT_IDLE;
	      seqno <= seqno + 4'd1;
	   end
	 default :
	   if(dst_rdy_int)
	     ctxt_state <= ctxt_state + 1;
       endcase // case (ctxt_state)

   assign src_rdy_int = ~( (ctxt_state == CTXT_IDLE) | (ctxt_state == CTXT_DONE) );

   always @*
     case(ctxt_state)
       CTXT_PROT_ENG : data_int <= { 2'b01, 13'b0, DSP_NUMBER[0], 1'b1, 1'b1, 16'd24 }; // UDP port 1 or 3
       CTXT_HEADER : data_int <= { 1'b0, (PROT_ENG_FLAGS ? 1'b0 : 1'b1), 12'b010100000001, seqno, 16'd6 };
       CTXT_STREAMID : data_int <= { 2'b00, streamid };
       CTXT_TICS : data_int <= { 2'b00, err_time[63:32] };
       CTXT_TICS2 : data_int <= { 2'b00, err_time[31:0] };
       CTXT_MESSAGE : data_int <= { 2'b00, message };
       CTXT_FLOWCTRL : data_int <= { 2'b10, seqnum };
       default : data_int <= {2'b00, 32'b00};
     endcase // case (ctxt_state)

   fifo_short #(.WIDTH(34)) ctxt_fifo
     (.clk(clk), .reset(reset), .clear(0),
      .datain(data_int), .src_rdy_i(src_rdy_int), .dst_rdy_o(dst_rdy_int),
      .dataout(data_o[33:0]), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i));
   assign data_o[35:34] = 2'b00;
   
endmodule // gen_context_pkt
module vita_packet_demux36
#(
    parameter NUMCHAN = 1,
    parameter SID_BASE = 0
)
(
    input clk, input rst,

    input [35:0] in_data,
    input in_src_rdy,
    output in_dst_rdy,

    output [35:0] out_data,
    output [NUMCHAN-1:0] out_src_rdy,
    input [NUMCHAN-1:0] out_dst_rdy
);

    reg [1:0] state;
    localparam STATE_WAIT_HDR = 0;
    localparam STATE_PROC_SID = 1;
    localparam STATE_WRITE_HDR = 2;
    localparam STATE_FORWARD = 3;

    reg [31:0] hdr;
    reg [NUMCHAN-1:0] sid;
    wire has_sid = in_data[28];
    reg has_sid_reg;

    wire my_out_dst_rdy = out_dst_rdy[sid];
    wire my_out_src_rdy = out_src_rdy[sid];

    always @(posedge clk) begin
        if (rst) begin
            state <= STATE_WAIT_HDR;
        end
        else case(state)

        STATE_WAIT_HDR: begin
            if (in_src_rdy && in_dst_rdy && in_data[32]) begin
                state <= (has_sid)? STATE_PROC_SID : STATE_WRITE_HDR;
            end
            sid <= 0;
            hdr <= in_data[31:0];
            has_sid_reg <= has_sid;
        end

        STATE_PROC_SID: begin
            if (in_src_rdy && in_dst_rdy) begin
                state <= STATE_WRITE_HDR;
                sid <= in_data[31:0] - SID_BASE;
                hdr[28] <= 1'b0; //clear has sid
                hdr[15:0] <= hdr[15:0] - 1'b1; //subtract a line
            end
        end

        STATE_WRITE_HDR: begin
            if (my_out_src_rdy && my_out_dst_rdy) begin
                state <= STATE_FORWARD;
            end
        end

        STATE_FORWARD: begin
            if (my_out_src_rdy && my_out_dst_rdy && out_data[33]) begin
                state <= STATE_WAIT_HDR;
            end
        end

        endcase //state
    end

    assign out_data = (state == STATE_WRITE_HDR)? {4'b0001, hdr} : in_data;
    wire out_src_rdy_i = (state == STATE_WRITE_HDR)? 1'b1 : ((state == STATE_FORWARD)? in_src_rdy : 1'b0);
    assign in_dst_rdy = (state == STATE_WAIT_HDR || state == STATE_PROC_SID)? 1'b1 : ((state == STATE_FORWARD)? my_out_dst_rdy : 1'b0);

    genvar i;
    generate
    for(i = 0; i < NUMCHAN; i = i + 1) begin:valid_assign
        assign out_src_rdy[i] = (i == sid)? out_src_rdy_i : 1'b0;
    end
    endgenerate

endmodule //vita_packet_demux36
module nsgpio
  (input clk_i, input rst_i, 
   input cyc_i, input stb_i, input [4:0] adr_i, input we_i, input [31:0] dat_i, 
   output reg [31:0] dat_o, output reg ack_o,
   input tx, input rx, inout [31:0] gpio
   );

   integer n;
   reg [31:0] ddr;
   reg [31:0] idle_out, rx_out, tx_out, fdx_out;
   reg [31:0] rgpio, igpio;
   
   wire 	wb_acc = cyc_i & stb_i;            // WISHBONE access
   wire 	wb_wr  = wb_acc & we_i;            // WISHBONE write access

   always @(posedge clk_i or posedge rst_i)
     if (rst_i)
       ddr <= 0;
     else if (wb_wr)
       case( adr_i[4:2] )
	 3'b000 : 
           idle_out <= dat_i;
	 3'b001 :
	   rx_out <= dat_i;
	 3'b010 :
	   tx_out <= dat_i;
	 3'b011 :
	   fdx_out <= dat_i;
	 3'b100 :
	   ddr <= dat_i;
       endcase // case ( adr_i[4:2] )
      
   always @(posedge clk_i)
     dat_o <= gpio;
   
   always @(posedge clk_i or posedge rst_i)
     if (rst_i)
       ack_o <= 1'b0;
     else
       ack_o <= wb_acc & !ack_o;

   always @(posedge clk_i)
     case({tx,rx})
       2'b00 : rgpio <= idle_out;
       2'b01 : rgpio <= rx_out;
       2'b10 : rgpio <= tx_out;
       2'b11 : rgpio <= fdx_out;
     endcase // case ({tx,rx})
   
   always @*
     for(n=0;n<32;n=n+1)
       igpio[n] <= ddr[n] ? rgpio[n] : 1'bz;

   assign     gpio = igpio;
   
endmodule
module nsgpio16LE
  (input clk_i, input rst_i, 
   input cyc_i, input stb_i, input [3:0] adr_i, input we_i, input [15:0] dat_i, 
   output reg [15:0] dat_o, output reg ack_o,
   input [31:0] atr, input [31:0] debug_0, input [31:0] debug_1, 
   inout [31:0] gpio
   );

   reg [31:0] 	ctrl, line, ddr, dbg, lgpio;
   
   wire 	wb_acc = cyc_i & stb_i;            // WISHBONE access
   wire 	wb_wr  = wb_acc & we_i;            // WISHBONE write access

   always @(posedge clk_i or posedge rst_i)
     if (rst_i)
       begin
          ctrl <= 32'h0;
          line <= 32'h0;
	  ddr <= 32'h0;
	  dbg <= 32'h0;
       end
     else if (wb_wr)
       case( adr_i[3:1] )
	 3'b000 : 
           line[15:0] <= dat_i;
	 3'b001 : 
           line[31:16] <= dat_i;
	 3'b010 :
	   ddr[15:0] <= dat_i;
	 3'b011 :
	   ddr[31:16] <= dat_i;
	 3'b100 :
	   ctrl[15:0] <= dat_i;
	 3'b101 :
	   ctrl[31:16] <= dat_i;
	 3'b110 :
	   dbg[15:0] <= dat_i;
	 3'b111 :
	   dbg[31:16] <= dat_i;
       endcase // case ( adr_i[3:1] )
   
   always @(posedge clk_i)
     case (adr_i[3:1])
       3'b000 :
	 dat_o <= lgpio[15:0];
       3'b001 :
	 dat_o <= lgpio[31:16];
       3'b010 :
	 dat_o <= ddr[15:0];
       3'b011 :
	 dat_o <= ddr[31:16];
       3'b100 :
	 dat_o <= ctrl[15:0];
       3'b101 :
	 dat_o <= ctrl[31:16];
       3'b110 :
	 dat_o <= dbg[15:0];
       3'b111 :
	 dat_o <= dbg[31:16];
     endcase // case (adr_i[3:1])
   
   
   always @(posedge clk_i or posedge rst_i)
     if (rst_i)
       ack_o <= 1'b0;
     else
       ack_o <= wb_acc & !ack_o;
   
   // latch GPIO input pins
   always @(posedge clk_i)
     lgpio <= gpio;
   
   // assign GPIO outputs
   integer   n;
   reg [31:0] igpio; // temporary internal signal
   
   always @(ctrl or line or debug_1 or debug_0 or atr or ddr or dbg)
     for(n=0;n<32;n=n+1)
       igpio[n] <= ddr[n] ? (dbg[n] ? (ctrl[n] ? debug_1[n] : debug_0[n]) : 
			     (ctrl[n] ?  atr[n] : line[n]) )
	 : 1'bz;
   
   assign     gpio = igpio;
   
endmodule
module v5icap_wb
  (input clk, input reset,
   input cyc_i, input stb_i, input we_i, output ack_o,
   input [31:0] dat_i, output [31:0] dat_o);

   wire 	BUSY, CE, WRITE;
   
   reg [2:0] 	icap_state;
   localparam ICAP_IDLE  = 0;
   localparam ICAP_WR0 	 = 1;
   localparam ICAP_WR1 	 = 2;
   localparam ICAP_RD0 	 = 3;
   localparam ICAP_RD1 	 = 4;

   always @(posedge clk)
     if(reset)
       icap_state 	<= ICAP_IDLE;
     else
       case(icap_state)
	 ICAP_IDLE :
	   begin
	      if(stb_i & cyc_i)
		if(we_i)
		  icap_state <= ICAP_WR0;
		else
		  icap_state <= ICAP_RD0;
	   end
	 ICAP_WR0 :
	   icap_state <= ICAP_WR1;
	 ICAP_WR1 :
	   icap_state <= ICAP_IDLE;
	 ICAP_RD0 :
	   icap_state <= ICAP_RD1;
	 ICAP_RD1 :
	   icap_state <= ICAP_IDLE;
       endcase // case (icap_state)

   assign WRITE 	 = (icap_state == ICAP_WR0) | (icap_state == ICAP_WR1);
   assign CE 		 = (icap_state == ICAP_WR1) | (icap_state == ICAP_RD0);

   assign ack_o = (icap_state == ICAP_WR1) | (icap_state == ICAP_RD1);
   
   ICAP_VIRTEX5 #(.ICAP_WIDTH("X32")) ICAP_VIRTEX5_inst 
     (.BUSY(BUSY),          // Busy output
      .O(dat_o),            // 32-bit data output
      .CE(~CE),              // Clock enable input
      .CLK(clk),            // Clock input
      .I(dat_i),            // 32-bit data input
      .WRITE(~WRITE)         // Write input
      );

endmodule // v5icap_wb
module simple_uart_rx
  #(parameter DEPTH=0)
    (input clk, input rst, 
     output [7:0] fifo_out, input fifo_read, output [7:0] fifo_level, output fifo_empty, 
     input [15:0] clkdiv, input rx);

   reg 		  rx_d1, rx_d2;
   always @(posedge clk)
     if(rst)
       {rx_d2,rx_d1} <= 0;
     else
       {rx_d2,rx_d1} <= {rx_d1,rx};
   
   reg [15:0] 	  baud_ctr;
   reg [3:0] 	  bit_ctr;
   reg [7:0] 	  sr;

   wire 	  neg_trans = rx_d2 & ~rx_d1;
   wire 	  shift_now = baud_ctr == (clkdiv>>1);
   wire 	  stop_now = (bit_ctr == 10) && shift_now;
   wire 	  go_now = (bit_ctr == 0) && neg_trans;
   
   always @(posedge clk)
     if(rst)
       sr <= 0;
     else if(shift_now)
       sr <= {rx_d2,sr[7:1]};
   
   always @(posedge clk)
     if(rst)
       baud_ctr <= 0;
     else
       if(go_now)
	 baud_ctr <= 1;
       else if(stop_now)
	 baud_ctr <= 0;
       else if(baud_ctr >= clkdiv)
	 baud_ctr <= 1;
       else if(baud_ctr != 0)
	 baud_ctr <= baud_ctr + 1;

   always @(posedge clk)
     if(rst)
       bit_ctr <= 0;
     else 
       if(go_now)
	 bit_ctr <= 1;
       else if(stop_now)
	 bit_ctr <= 0;
       else if(baud_ctr == clkdiv)
	 bit_ctr <= bit_ctr + 1;
   
   wire 	  full;
   wire 	  write = ~full & rx_d2 & stop_now;
   
   medfifo #(.WIDTH(8),.DEPTH(DEPTH)) fifo
     (.clk(clk),.rst(rst),
      .datain(sr),.write(write),.full(full),
      .dataout(fifo_out),.read(fifo_read),.empty(fifo_empty),
      .clear(0),.space(),.occupied(fifo_level) );
   
endmodule // simple_uart_rx
module wb_readback_mux_16LE
  (input wb_clk_i,
   input wb_rst_i,
   input wb_stb_i,
   input [15:0] wb_adr_i,
   output [15:0] wb_dat_o,
   output reg wb_ack_o,

   input [31:0] word00,
   input [31:0] word01,
   input [31:0] word02,
   input [31:0] word03,
   input [31:0] word04,
   input [31:0] word05,
   input [31:0] word06,
   input [31:0] word07,
   input [31:0] word08,
   input [31:0] word09,
   input [31:0] word10,
   input [31:0] word11,
   input [31:0] word12,
   input [31:0] word13,
   input [31:0] word14,
   input [31:0] word15
   );

   wire ack_next = wb_stb_i & ~wb_ack_o;

   always @(posedge wb_clk_i)
     if(wb_rst_i)
       wb_ack_o <= 0;
     else
       wb_ack_o <= ack_next;

   reg [31:0] data;
   assign wb_dat_o = data[15:0];

   always @(posedge wb_clk_i)
    if (wb_adr_i[1] & ack_next) begin //upper half
        data[15:0] <= data[31:16];
    end
    else if (~wb_adr_i[1] & ack_next) begin //lower half
     case(wb_adr_i[5:2])
       0 : data <= word00;
       1 : data <= word01;
       2 : data <= word02;
       3 : data <= word03;
       4 : data <= word04;
       5 : data <= word05;
       6 : data <= word06;
       7 : data <= word07;
       8 : data <= word08;
       9 : data <= word09;
       10: data <= word10;
       11: data <= word11;
       12: data <= word12;
       13: data <= word13;
       14: data <= word14;
       15: data <= word15;
     endcase // case(wb_adr_i[5:2])
    end

endmodule // wb_readback_mux
module simple_uart_tx
  #(parameter DEPTH=0)
    (input clk, input rst, 
     input [7:0] fifo_in, input fifo_write, output [7:0] fifo_level, output fifo_full, 
     input [15:0] clkdiv, output baudclk, output reg tx);
   
   reg [15:0] 	  baud_ctr;
   reg [3:0] 	  bit_ctr;
   
   wire 	  read, empty;
   wire [7:0] 	  char_to_send;
   
   medfifo #(.WIDTH(8),.DEPTH(DEPTH)) fifo
     (.clk(clk),.rst(rst),
      .datain(fifo_in),.write(fifo_write),.full(fifo_full),
      .dataout(char_to_send),.read(read),.empty(empty),
      .clear(0),.space(fifo_level),.occupied() );
   
   always @(posedge clk)
     if(rst)
       baud_ctr <= 0;
     else if (baud_ctr >= clkdiv)
       baud_ctr <= 0;
     else
       baud_ctr <= baud_ctr + 1;

   always @(posedge clk)
     if(rst)
       bit_ctr <= 0;
     else if(baud_ctr == clkdiv)
       if(bit_ctr == 9)
	 bit_ctr <= 0;
       else if(bit_ctr != 0)
	 bit_ctr <= bit_ctr + 1;
       else if(~empty)
	 bit_ctr <= 1;
   
   always @(posedge clk)
     if(rst)
       tx <= 1;
     else
       case(bit_ctr)
	 0 : tx <= 1;
	 1 : tx <= 0;
	 2 : tx <= char_to_send[0];
	 3 : tx <= char_to_send[1];
	 4 : tx <= char_to_send[2];
	 5 : tx <= char_to_send[3];
	 6 : tx <= char_to_send[4];
	 7 : tx <= char_to_send[5];
	 8 : tx <= char_to_send[6];
	 9 : tx <= char_to_send[7];
	 default : tx <= 1;
       endcase // case(bit_ctr)

   assign 	  read = (bit_ctr == 9) && (baud_ctr == clkdiv);
   assign 	  baudclk = (baud_ctr == 1);  // Only for debug purposes
   
endmodule // simple_uart_tx
module settings_bus
  #(parameter AWIDTH=16, parameter DWIDTH=32)
    (input wb_clk, 
     input wb_rst, 
     input [AWIDTH-1:0] wb_adr_i,
     input [DWIDTH-1:0] wb_dat_i,
     input wb_stb_i,
     input wb_we_i,
     output reg wb_ack_o,
     output reg strobe,
     output reg [7:0] addr,
     output reg [31:0] data);

   reg 	    stb_int, stb_int_d1;
   
   always @(posedge wb_clk)
     if(wb_rst)
       begin
	  strobe <= 1'b0;
	  addr <= 8'd0;
	  data <= 32'd0;
       end
     else if(wb_we_i & wb_stb_i & ~wb_ack_o)
       begin
	  strobe <= 1'b1;
	  addr <= wb_adr_i[9:2];
	  data <= wb_dat_i;
       end
     else
       strobe <= 1'b0;

   always @(posedge wb_clk)
     if(wb_rst)
       wb_ack_o <= 0;
     else
       wb_ack_o <= wb_stb_i & ~wb_ack_o;

endmodule // settings_bus
module priority_enc
  (input [31:0] in,
   output reg [31:0] out);

   always @*
     casex(in)
       32'b1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 31;
       32'b01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 30;
       32'b001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 29;
       32'b0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 28;
       32'b0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 27;
       32'b0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 26;
       32'b0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 25;
       32'b0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 24;
       32'b0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 23;
       32'b0000_0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 22;
       32'b0000_0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 21;
       32'b0000_0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx : out <= 20;
       32'b0000_0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx : out <= 19;
       32'b0000_0000_0000_01xx_xxxx_xxxx_xxxx_xxxx : out <= 18;
       32'b0000_0000_0000_001x_xxxx_xxxx_xxxx_xxxx : out <= 17;
       32'b0000_0000_0000_0001_xxxx_xxxx_xxxx_xxxx : out <= 16;
       32'b0000_0000_0000_0000_1xxx_xxxx_xxxx_xxxx : out <= 15;
       32'b0000_0000_0000_0000_01xx_xxxx_xxxx_xxxx : out <= 14;
       32'b0000_0000_0000_0000_001x_xxxx_xxxx_xxxx : out <= 13;
       32'b0000_0000_0000_0000_0001_xxxx_xxxx_xxxx : out <= 12;
       32'b0000_0000_0000_0000_0000_1xxx_xxxx_xxxx : out <= 11;
       32'b0000_0000_0000_0000_0000_01xx_xxxx_xxxx : out <= 10;
       32'b0000_0000_0000_0000_0000_001x_xxxx_xxxx : out <=  9;
       32'b0000_0000_0000_0000_0000_0001_xxxx_xxxx : out <=  8;
       32'b0000_0000_0000_0000_0000_0000_1xxx_xxxx : out <=  7;
       32'b0000_0000_0000_0000_0000_0000_01xx_xxxx : out <=  6;
       32'b0000_0000_0000_0000_0000_0000_001x_xxxx : out <=  5;
       32'b0000_0000_0000_0000_0000_0000_0001_xxxx : out <=  4;
       32'b0000_0000_0000_0000_0000_0000_0000_1xxx : out <=  3;
       32'b0000_0000_0000_0000_0000_0000_0000_01xx : out <=  2;
       32'b0000_0000_0000_0000_0000_0000_0000_001x : out <=  1;
       32'b0000_0000_0000_0000_0000_0000_0000_0001 : out <=  0;
       32'b0000_0000_0000_0000_0000_0000_0000_0000 : out <= 32'hFFFF_FFFF;
       default : out <= 32'hFFFF_FFFF;
     endcase // casex (in)
   
endmodule // priority_enc
module decoder_3_8 
  (input [2:0] sel, 
   output reg [7:0] res);

   always @(sel or res)
     begin
        case (sel)
          3'b000 : res = 8'b00000001;
          3'b001 : res = 8'b00000010;
          3'b010 : res = 8'b00000100;
          3'b011 : res = 8'b00001000;
          3'b100 : res = 8'b00010000;
          3'b101 : res = 8'b00100000;
          3'b110 : res = 8'b01000000;
          default : res = 8'b10000000;
        endcase // case(sel)
     end // always @ (sel or res)

endmodule // decoder_3_8
module mux8
  #(parameter WIDTH=32, parameter DISABLED=0)
    (input en,
     input [2:0] sel,
     input [WIDTH-1:0] i0,
     input [WIDTH-1:0] i1,
     input [WIDTH-1:0] i2,
     input [WIDTH-1:0] i3,
     input [WIDTH-1:0] i4,
     input [WIDTH-1:0] i5,
     input [WIDTH-1:0] i6,
     input [WIDTH-1:0] i7,
     output [WIDTH-1:0] o);

   assign 		o = en ? (sel[2] ? (sel[1] ? (sel[0] ? i7 : i6) : (sel[0] ? i5 : i4)) :
				  (sel[1] ? (sel[0] ? i3 : i2) : (sel[0] ? i1 : i0))) :
			DISABLED;
   
endmodule // mux8
module wb_readback_mux
  (input wb_clk_i,
   input wb_rst_i,
   input wb_stb_i,
   input [15:0] wb_adr_i,
   output reg [31:0] wb_dat_o,
   output reg wb_ack_o,
   
   input [31:0] word00,
   input [31:0] word01,
   input [31:0] word02,
   input [31:0] word03,
   input [31:0] word04,
   input [31:0] word05,
   input [31:0] word06,
   input [31:0] word07,
   input [31:0] word08,
   input [31:0] word09,
   input [31:0] word10,
   input [31:0] word11,
   input [31:0] word12,
   input [31:0] word13,
   input [31:0] word14,
   input [31:0] word15
   );

   always @(posedge wb_clk_i)
     if(wb_rst_i)
       wb_ack_o <= 0;
     else
       wb_ack_o <= wb_stb_i & ~wb_ack_o;
   
   always @(posedge wb_clk_i)
     case(wb_adr_i[5:2])
       0 : wb_dat_o <= word00;
       1 : wb_dat_o <= word01;
       2 : wb_dat_o <= word02;
       3 : wb_dat_o <= word03;
       4 : wb_dat_o <= word04;
       5 : wb_dat_o <= word05;
       6 : wb_dat_o <= word06;
       7 : wb_dat_o <= word07;
       8 : wb_dat_o <= word08;
       9 : wb_dat_o <= word09;
       10: wb_dat_o <= word10;
       11: wb_dat_o <= word11;
       12: wb_dat_o <= word12;
       13: wb_dat_o <= word13;
       14: wb_dat_o <= word14;
       15: wb_dat_o <= word15;
     endcase // case(addr_reg[3:0])
      
endmodule // wb_readback_mux
module oneshot_2clk
  (input clk_in,
   input in,
   input clk_out,
   output reg out);

   reg 	  del_in = 0;
   reg 	  sendit = 0, gotit = 0;
   reg 	  sendit_d = 0, gotit_d = 0;
   
   always @(posedge clk_in) del_in <= in;

   always @(posedge clk_in)
     if(in & ~del_in)  // we have a positive edge
       sendit <= 1;
     else if(gotit)
       sendit <= 0;

   always @(posedge clk_out) sendit_d <= sendit;
   always @(posedge clk_out) out <= sendit_d;

   always @(posedge clk_in) gotit_d <= out;
   always @(posedge clk_in) gotit <= gotit_d;

endmodule // oneshot_2clk
module ram_harvard2
  #(parameter AWIDTH=15,
    parameter RAM_SIZE=32768)
   (input wb_clk_i, 
    input wb_rst_i,
    // Instruction fetch port.
    input [AWIDTH-1:0] if_adr,
    output reg [31:0] if_data,
    // Data access port.
    input [AWIDTH-1:0] dwb_adr_i,
    input [31:0] dwb_dat_i, 
    output reg [31:0] dwb_dat_o,
    input dwb_we_i,
    output dwb_ack_o,
    input dwb_stb_i,
    input [3:0] dwb_sel_i);
   
   reg 	  ack_d1;
   reg 	  stb_d1;
   
   assign dwb_ack_o = dwb_stb_i & (dwb_we_i | (stb_d1 & ~ack_d1));

   always @(posedge wb_clk_i) 
     if(wb_rst_i)
       ack_d1 <= 1'b0;
     else 
       ack_d1 <= dwb_ack_o;

   always @(posedge wb_clk_i)
     if(wb_rst_i)
       stb_d1 <= 0;
     else
       stb_d1 <= dwb_stb_i;

   reg [7:0] ram0 [0:(RAM_SIZE/4)-1];
   reg [7:0] ram1 [0:(RAM_SIZE/4)-1];
   reg [7:0] ram2 [0:(RAM_SIZE/4)-1];
   reg [7:0] ram3 [0:(RAM_SIZE/4)-1];
   
   // Port 1, Read only
   always @(posedge wb_clk_i)
     if_data[31:24] <= ram3[if_adr[AWIDTH-1:2]];
   always @(posedge wb_clk_i)
     if_data[23:16] <= ram2[if_adr[AWIDTH-1:2]];
   always @(posedge wb_clk_i)
     if_data[15:8] <= ram1[if_adr[AWIDTH-1:2]];
   always @(posedge wb_clk_i)
     if_data[7:0] <= ram0[if_adr[AWIDTH-1:2]];

   // Port 2, R/W
   always @(posedge wb_clk_i)
     if(dwb_stb_i) dwb_dat_o[31:24] <= ram3[dwb_adr_i[AWIDTH-1:2]];
   always @(posedge wb_clk_i)
     if(dwb_stb_i) dwb_dat_o[23:16] <= ram2[dwb_adr_i[AWIDTH-1:2]];
   always @(posedge wb_clk_i)
     if(dwb_stb_i) dwb_dat_o[15:8] <= ram1[dwb_adr_i[AWIDTH-1:2]];
   always @(posedge wb_clk_i)
     if(dwb_stb_i) dwb_dat_o[7:0] <= ram0[dwb_adr_i[AWIDTH-1:2]];
   
   always @(posedge wb_clk_i)
     if(dwb_we_i & dwb_stb_i & dwb_sel_i[3])
       ram3[dwb_adr_i[AWIDTH-1:2]] <= dwb_dat_i[31:24];
   always @(posedge wb_clk_i)
     if(dwb_we_i & dwb_stb_i & dwb_sel_i[2])
       ram2[dwb_adr_i[AWIDTH-1:2]] <= dwb_dat_i[23:16];
   always @(posedge wb_clk_i)
     if(dwb_we_i & dwb_stb_i & dwb_sel_i[1])
       ram1[dwb_adr_i[AWIDTH-1:2]] <= dwb_dat_i[15:8];
   always @(posedge wb_clk_i)
     if(dwb_we_i & dwb_stb_i & dwb_sel_i[0])
       ram0[dwb_adr_i[AWIDTH-1:2]] <= dwb_dat_i[7:0];
   
endmodule // ram_harvard
module s3a_icap_wb
  (input clk, input reset,
   input cyc_i, input stb_i, input we_i, output ack_o,
   input [31:0] dat_i, output [31:0] dat_o);//, output [31:0] debug_out);

   assign dat_o[31:8] = 24'd0;
   
   wire 	BUSY, CE, WRITE, ICAPCLK;
   
   //changed this to gray-ish code to prevent glitching
   reg [2:0] 	icap_state;
   localparam ICAP_IDLE  = 0;
   localparam ICAP_WR0 	 = 1;
   localparam ICAP_WR1 	 = 5;
   localparam ICAP_RD0 	 = 2;
   localparam ICAP_RD1 	 = 3;

   always @(posedge clk)
     if(reset)
       icap_state 	<= ICAP_IDLE;
     else
       case(icap_state)
	 ICAP_IDLE :
	   begin
	      if(stb_i & cyc_i)
		if(we_i)
		  icap_state <= ICAP_WR0;
		else
		  icap_state <= ICAP_RD0;
	   end
	 ICAP_WR0 :
	   icap_state <= ICAP_WR1;
	 ICAP_WR1 :
	   icap_state <= ICAP_IDLE;
	 ICAP_RD0 :
	   icap_state <= ICAP_RD1;
	 ICAP_RD1 :
	   icap_state <= ICAP_IDLE;
       endcase // case (icap_state)

   assign WRITE 	 = (icap_state == ICAP_WR0) | (icap_state == ICAP_WR1);
   assign CE 		 = (icap_state == ICAP_WR0) | (icap_state == ICAP_RD0);
   assign ICAPCLK        = CE & (~clk);

   assign ack_o = (icap_state == ICAP_WR1) | (icap_state == ICAP_RD1);
   //assign debug_out = {17'd0, BUSY, dat_i[7:0], ~CE, ICAPCLK, ~WRITE, icap_state};
   
   ICAP_SPARTAN3A ICAP_SPARTAN3A_inst 
     (.BUSY(BUSY),          // Busy output
      .O(dat_o[7:0]),            // 32-bit data output
      .CE(~CE),              // Clock enable input
      .CLK(ICAPCLK),            // Clock input
      .I(dat_i[7:0]),            // 32-bit data input
      .WRITE(~WRITE)         // Write input
      );

endmodule // s3a_icap_wb
module dpram32 #(parameter AWIDTH=15, 
		 parameter RAM_SIZE=16384)
  (input clk,
   
   input [AWIDTH-1:0] adr1_i,
   input [31:0] dat1_i,
   output reg [31:0] dat1_o,
   input we1_i,
   input en1_i,
   input [3:0] sel1_i,

   input [AWIDTH-1:0] adr2_i,
   input [31:0] dat2_i,
   output reg [31:0] dat2_o,
   input we2_i,
   input en2_i,
   input [3:0] sel2_i );
   
   reg [7:0]   ram0 [0:(RAM_SIZE/4)-1];
   reg [7:0]   ram1 [0:(RAM_SIZE/4)-1];
   reg [7:0]   ram2 [0:(RAM_SIZE/4)-1];
   reg [7:0]   ram3 [0:(RAM_SIZE/4)-1];

   //  This is how we used to size the RAM -->  
   //      reg [7:0]   ram3 [0:(1<<(AWIDTH-2))-1];
   
   // Port 1
   always @(posedge clk)
     if(en1_i) dat1_o[31:24] <= ram3[adr1_i[AWIDTH-1:2]];
   always @(posedge clk)
     if(en1_i) dat1_o[23:16] <= ram2[adr1_i[AWIDTH-1:2]];
   always @(posedge clk)
     if(en1_i) dat1_o[15:8] <= ram1[adr1_i[AWIDTH-1:2]];
   always @(posedge clk)
     if(en1_i) dat1_o[7:0] <= ram0[adr1_i[AWIDTH-1:2]];
   
   always @(posedge clk)
     if(we1_i & en1_i & sel1_i[3])
       ram3[adr1_i[AWIDTH-1:2]] <= dat1_i[31:24];
   always @(posedge clk)
     if(we1_i & en1_i & sel1_i[2])
       ram2[adr1_i[AWIDTH-1:2]] <= dat1_i[23:16];
   always @(posedge clk)
     if(we1_i & en1_i & sel1_i[1])
       ram1[adr1_i[AWIDTH-1:2]] <= dat1_i[15:8];
   always @(posedge clk)
     if(we1_i & en1_i & sel1_i[0])
       ram0[adr1_i[AWIDTH-1:2]] <= dat1_i[7:0];
   
   // Port 2
   always @(posedge clk)
     if(en2_i) dat2_o[31:24] <= ram3[adr2_i[AWIDTH-1:2]];
   always @(posedge clk)
     if(en2_i) dat2_o[23:16] <= ram2[adr2_i[AWIDTH-1:2]];
   always @(posedge clk)
     if(en2_i) dat2_o[15:8] <= ram1[adr2_i[AWIDTH-1:2]];
   always @(posedge clk)
     if(en2_i) dat2_o[7:0] <= ram0[adr2_i[AWIDTH-1:2]];
   
   always @(posedge clk)
     if(we2_i & en2_i & sel2_i[3])
       ram3[adr2_i[AWIDTH-1:2]] <= dat2_i[31:24];
   always @(posedge clk)
     if(we2_i & en2_i & sel2_i[2])
       ram2[adr2_i[AWIDTH-1:2]] <= dat2_i[23:16];
   always @(posedge clk)
     if(we2_i & en2_i & sel2_i[1])
       ram1[adr2_i[AWIDTH-1:2]] <= dat2_i[15:8];
   always @(posedge clk)
     if(we2_i & en2_i & sel2_i[0])
       ram0[adr2_i[AWIDTH-1:2]] <= dat2_i[7:0];
   
endmodule // dpram32
module longfifo
  #(parameter WIDTH=32, SIZE=9)
    (input clk, input rst,
     input [WIDTH-1:0] datain,
     output [WIDTH-1:0] dataout,
     input read,
     input write,
     input clear,
     output full,
     output empty,
     output reg [15:0] space,
     output reg [15:0] occupied);

   // Read side states
   localparam 	  EMPTY = 0;
   localparam 	  PRE_READ = 1;
   localparam 	  READING = 2;

   reg [SIZE-1:0] wr_addr, rd_addr;
   reg [1:0] 	  read_state;

   reg 	  empty_reg, full_reg;
   always @(posedge clk)
     if(rst)
       wr_addr <= 0;
     else if(clear)
       wr_addr <= 0;
     else if(write)
       wr_addr <= wr_addr + 1;

   ram_2port #(.DWIDTH(WIDTH),.AWIDTH(SIZE))
     ram (.clka(clk),
	  .ena(1'b1),
	  .wea(write),
	  .addra(wr_addr),
	  .dia(datain),
	  .doa(),

	  .clkb(clk),
	  .enb((read_state==PRE_READ)|read),
	  .web(0),
	  .addrb(rd_addr),
	  .dib(0),
	  .dob(dataout));

   always @(posedge clk)
     if(rst)
       begin
	  read_state <= EMPTY;
	  rd_addr <= 0;
	  empty_reg <= 1;
       end
     else
       if(clear)
	 begin
	    read_state <= EMPTY;
	    rd_addr <= 0;
	    empty_reg <= 1;
	 end
       else 
	 case(read_state)
	   EMPTY :
	     if(write)
	       begin
		  //rd_addr <= wr_addr;
		  read_state <= PRE_READ;
	       end
	   PRE_READ :
	     begin
		read_state <= READING;
		empty_reg <= 0;
		rd_addr <= rd_addr + 1;
	     end
	   
	   READING :
	     if(read)
	       if(rd_addr == wr_addr)
		 begin
		    empty_reg <= 1;
		    if(write)
		      read_state <= PRE_READ;
		    else
		      read_state <= EMPTY;
		 end
	       else
		 rd_addr <= rd_addr + 1;
	 endcase // case(read_state)

   wire [SIZE-1:0] dont_write_past_me = rd_addr - 3;
   wire 	   becoming_full = wr_addr == dont_write_past_me;
     
   always @(posedge clk)
     if(rst)
       full_reg <= 0;
     else if(clear)
       full_reg <= 0;
     else if(read & ~write)
       full_reg <= 0;
     //else if(write & ~read & (wr_addr == (rd_addr-3)))
     else if(write & ~read & becoming_full)
       full_reg <= 1;

   //assign empty = (read_state != READING);
   assign empty = empty_reg;

   // assign full = ((rd_addr - 1) == wr_addr);
   assign full = full_reg;

   //////////////////////////////////////////////
   // space and occupied are for diagnostics only
   // not guaranteed exact

   localparam NUMLINES = (1<<SIZE)-2;
   always @(posedge clk)
     if(rst)
       space <= NUMLINES;
     else if(clear)
       space <= NUMLINES;
     else if(read & ~write)
       space <= space + 1;
     else if(write & ~read)
       space <= space - 1;
   
   always @(posedge clk)
     if(rst)
       occupied <= 0;
     else if(clear)
       occupied <= 0;
     else if(read & ~write)
       occupied <= occupied - 1;
     else if(write & ~read)
       occupied <= occupied + 1;
   
   /*
   wire [SIZE-1:0] fullness = wr_addr - rd_addr;  // Approximate, for simulation only
   assign occupied = {{16-SIZE{1'b0}},fullness};

   wire [SIZE-1:0] free_space = rd_addr - wr_addr - 2;  // Approximate, for SERDES flow control
   assign space = {{16-SIZE{1'b0}},free_space};
    */  

   
endmodule // longfifo
module simple_uart
  #(parameter TXDEPTH = 1,
    parameter RXDEPTH = 1,
    parameter CLKDIV_DEFAULT = 16'd0)
   (input clk_i, input rst_i,
    input we_i, input stb_i, input cyc_i, output reg ack_o,
    input [2:0] adr_i, input [31:0] dat_i, output reg [31:0] dat_o,
    output rx_int_o, output tx_int_o, output tx_o, input rx_i, output baud_o);
   
   // Register Map
   localparam SUART_CLKDIV = 0;
   localparam SUART_TXLEVEL = 1;
   localparam SUART_RXLEVEL = 2;
   localparam SUART_TXCHAR = 3;
   localparam SUART_RXCHAR = 4;
   
   wire       wb_acc = cyc_i & stb_i;            // WISHBONE access
   wire       wb_wr  = wb_acc & we_i;            // WISHBONE write access
   
   reg [15:0] clkdiv;
   wire [7:0] rx_char;
   wire       tx_fifo_full, rx_fifo_empty;   
   wire [7:0] tx_fifo_level, rx_fifo_level;
   
   always @(posedge clk_i)
     if (rst_i)
       ack_o <= 1'b0;
     else
       ack_o <= wb_acc & ~ack_o;
   
   always @(posedge clk_i)
     if (rst_i)
       clkdiv <= CLKDIV_DEFAULT;
     else if (wb_wr)
       case(adr_i)
	 SUART_CLKDIV : clkdiv <= dat_i[15:0];
       endcase // case(adr_i)
   
   always @(posedge clk_i)
     case (adr_i)
       SUART_TXLEVEL : dat_o <= tx_fifo_level;
       SUART_RXLEVEL : dat_o <= rx_fifo_level;
       SUART_RXCHAR : dat_o <= rx_char;
     endcase // case(adr_i)
   
   simple_uart_tx #(.DEPTH(TXDEPTH)) simple_uart_tx
     (.clk(clk_i),.rst(rst_i),
      .fifo_in(dat_i[7:0]),.fifo_write(ack_o && wb_wr && (adr_i == SUART_TXCHAR)),
      .fifo_level(tx_fifo_level),.fifo_full(tx_fifo_full),
      .clkdiv(clkdiv),.baudclk(baud_o),.tx(tx_o));
   
   simple_uart_rx #(.DEPTH(RXDEPTH)) simple_uart_rx
     (.clk(clk_i),.rst(rst_i),
      .fifo_out(rx_char),.fifo_read(ack_o && ~wb_wr && (adr_i == SUART_RXCHAR)),
      .fifo_level(rx_fifo_level),.fifo_empty(rx_fifo_empty),
      .clkdiv(clkdiv),.rx(rx_i));
   
   assign     tx_int_o = ~tx_fifo_full;
   assign     rx_int_o = ~rx_fifo_empty;
   
endmodule // simple_uart
module medfifo
  #(parameter WIDTH=32,
    parameter DEPTH=1)
    (input clk, input rst,
     input [WIDTH-1:0] datain,
     output [WIDTH-1:0] dataout,
     input read,
     input write,
     input clear,
     output full,
     output empty,
     output [7:0] space,
     output [7:0] occupied);

   localparam 		NUM_FIFOS = (1<<DEPTH);
   
   wire [WIDTH-1:0] 	dout [0:NUM_FIFOS-1];
   wire [0:NUM_FIFOS-1] full_x;
   wire [0:NUM_FIFOS-1] empty_x;

   shortfifo #(.WIDTH(WIDTH))
     head (.clk(clk),.rst(rst),
	   .datain(datain),.write(write),.full(full),
	   .dataout(dout[0]),.read(~empty_x[0] & ~full_x[1]),.empty(empty_x[0]),
	   .clear(clear),.space(space[4:0]),.occupied() );
   
   shortfifo #(.WIDTH(WIDTH))
     tail (.clk(clk),.rst(rst),
	   .datain(dout[NUM_FIFOS-2]),.write(~empty_x[NUM_FIFOS-2] & ~full_x[NUM_FIFOS-1]),.full(full_x[NUM_FIFOS-1]),
	   .dataout(dataout),.read(read),.empty(empty),
	   .clear(clear),.space(),.occupied(occupied[4:0]) );

   genvar 		i;
   generate
      for(i = 1; i < NUM_FIFOS-1 ; i = i + 1)
	begin : gen_depth
	   shortfifo #(.WIDTH(WIDTH))
	     shortfifo (.clk(clk),.rst(rst),
			.datain(dout[i-1]),.write(~full_x[i] & ~empty_x[i-1]),.full(full_x[i]),
			.dataout(dout[i]),.read(~full_x[i+1] & ~empty_x[i]),.empty(empty_x[i]),
			.clear(clear),.space(),.occupied() );
	end
   endgenerate

   assign space[7:5] = 0;
   assign occupied[7:5] = 0;
   
endmodule // medfifo
module ram_harvard
  #(parameter AWIDTH=15,
    parameter RAM_SIZE=16384,
    parameter ICWIDTH=6,
    parameter DCWIDTH=6)
   
    (input wb_clk_i, 
     input wb_rst_i,
     // Firmware download port.
     input [AWIDTH-1:0] ram_loader_adr_i,
     input [31:0] ram_loader_dat_i,
     input [3:0] ram_loader_sel_i,
     input ram_loader_stb_i,
     input ram_loader_we_i,
     input ram_loader_done_i,    
     // Instruction fetch port.
     input [AWIDTH-1:0] if_adr,
     output [31:0] if_data,
     // Data access port.
     input [AWIDTH-1:0] dwb_adr_i,
     input [31:0] dwb_dat_i, 
     output [31:0] dwb_dat_o,
     input dwb_we_i,
     output dwb_ack_o,
     input dwb_stb_i,
     input [3:0] dwb_sel_i );

   reg 	   ack_d1;
   reg 	   stb_d1;
   
   dpram32 #(.AWIDTH(AWIDTH),.RAM_SIZE(RAM_SIZE)) 
   sys_ram
     (.clk(wb_clk_i),
      .adr1_i(ram_loader_done_i ? if_adr : ram_loader_adr_i),
      .dat1_i(ram_loader_dat_i),
      .dat1_o(if_data),
      .we1_i(ram_loader_done_i ? 1'b0 : ram_loader_we_i),
      .en1_i(ram_loader_done_i ? 1'b1 : ram_loader_stb_i),
      //.sel1_i(ram_loader_done_i ? 4'hF : ram_loader_sel_i),
      .sel1_i(ram_loader_sel_i), // Sel is only for writes anyway
      .adr2_i(dwb_adr_i),
      .dat2_i(dwb_dat_i),
      .dat2_o(dwb_dat_o),
      .we2_i(dwb_we_i),
      .en2_i(dwb_stb_i),
      .sel2_i(dwb_sel_i) 
      );

   assign dwb_ack_o = dwb_stb_i & (dwb_we_i | (stb_d1 & ~ack_d1));

   always @(posedge wb_clk_i) 
     if(wb_rst_i)
       ack_d1 <= 1'b0;
     else 
       ack_d1 <= dwb_ack_o;

   always @(posedge wb_clk_i)
     if(wb_rst_i)
       stb_d1 <= 0;
     else
       stb_d1 <= dwb_stb_i;

endmodule // ram_harvard
module gray_send
  #(parameter WIDTH = 8)
    (input clk_in, input [WIDTH-1:0] addr_in,
     input clk_out, output reg [WIDTH-1:0] addr_out);

   reg [WIDTH-1:0] gray_clkin, gray_clkout, gray_clkout_d1;
   wire [WIDTH-1:0] gray, bin;

   bin2gray #(.WIDTH(WIDTH)) b2g (.bin(addr_in), .gray(gray) );

   always @(posedge clk_in)
     gray_clkin <= gray;

   always @(posedge clk_out)
     gray_clkout <= gray_clkin;

   always @(posedge clk_out)
     gray_clkout_d1 <= gray_clkout;
   
   gray2bin #(.WIDTH(WIDTH)) g2b (.gray(gray_clkout_d1), .bin(bin) );

   // FIXME we may not need the next register, but it may help timing
   always @(posedge clk_out)
     addr_out <= bin;
   
endmodule // gray_send
module settings_bus_crossclock
  #(parameter FLOW_CTRL=0)
  (input clk_i, input rst_i, input set_stb_i, input [7:0] set_addr_i, input [31:0] set_data_i,
   input clk_o, input rst_o, output set_stb_o, output [7:0] set_addr_o, output [31:0] set_data_o, input blocked);

   wire  full, empty;
   
   fifo_xlnx_16x40_2clk settings_fifo
     (.rst(rst_i),
      .wr_clk(clk_i), .din({set_addr_i,set_data_i}), .wr_en(set_stb_i & ~full), .full(full),
      .rd_clk(clk_o), .dout({set_addr_o,set_data_o}), .rd_en(set_stb_o), .empty(empty));

   assign set_stb_o = ~empty & (~blocked | ~FLOW_CTRL);

endmodule // settings_bus_crossclock
module wb_bus_writer (input start,
		      output done,
		      output reg [15:0] rom_addr,
		      input [47:0] rom_data,
		      // WB Master Interface, don't need wb_dat_i
		      input wb_clk_i,
		      input wb_rst_i,
		      output [31:0] wb_dat_o,
		      input wb_ack_i,
		      output [15:0] wb_adr_o,
		      output wb_cyc_o,
		      output [3:0] wb_sel_o,
		      output wb_stb_o,
		      output wb_we_o
		      );

`define IDLE 0
`define READ 1
   
   reg [3:0] 		     state;
   
   assign 		     done = (state != `IDLE) && (&rom_data);  // Done when we see all 1s
   
   always @(posedge wb_clk_i)
     if(wb_rst_i)
       begin
	  rom_addr <= #1 0;
	  state <= #1 0;
       end
     else if(start)
       begin
	  rom_addr <= #1 0;
	  state <= #1 `READ;
       end
     else if((state == `READ) && wb_ack_i)
       if(done)
	 state <= #1 `IDLE;
       else
	 rom_addr <= #1 rom_addr + 1;
   
   assign wb_dat_o = rom_data[31:0];
   assign wb_adr_o = rom_data[47:32];
   assign wb_sel_o = 4'b1111;    // All writes are the full 32 bits
   
   assign wb_cyc_o = !done & (state != `IDLE);
   assign wb_stb_o = !done & (state != `IDLE);
   assign wb_we_o = !done & (state != `IDLE);
   
endmodule // wb_bus_writer
module wb_output_pins32
  (wb_rst_i, wb_clk_i, wb_dat_i, wb_dat_o,
   wb_we_i, wb_sel_i, wb_stb_i, wb_ack_o, wb_cyc_i,
   port_output);

   input wb_rst_i;
   input wb_clk_i;
   input wire [31:0] wb_dat_i;
   output wire [31:0] wb_dat_o;
   input  wb_we_i;
   input  wire [3:0] 	 wb_sel_i;
   input  wb_stb_i;
   output wb_ack_o;
   input  wb_cyc_i;

   output wire [31:0] port_output;

   reg [31:0] internal_reg;

   always @(posedge wb_clk_i)
     if(wb_rst_i)
       internal_reg <= #1 32'b0;
     else
       begin
	  if(wb_stb_i & wb_we_i & wb_sel_i[0])
	    internal_reg[7:0] <= #1 wb_dat_i[7:0];
	  if(wb_stb_i & wb_we_i & wb_sel_i[1])
	    internal_reg[15:8] <= #1 wb_dat_i[15:8];
	  if(wb_stb_i & wb_we_i & wb_sel_i[2])
	    internal_reg[23:16] <= #1 wb_dat_i[23:16];
	  if(wb_stb_i & wb_we_i & wb_sel_i[3])
	    internal_reg[31:24] <= #1 wb_dat_i[31:24];
       end // else: !if(wb_rst_i)

   assign wb_dat_o = internal_reg;
   assign port_output = internal_reg;
   assign wb_ack_o = wb_stb_i;
   	     
endmodule // wb_output_pins32
module wb_ram_dist
  #(parameter AWIDTH=8)
    (input clk_i,
     input stb_i,
     input we_i,
     input [AWIDTH-1:0] adr_i,
     input [31:0] dat_i,
     input [3:0] sel_i,
     output [31:0] dat_o,
     output ack_o);

   reg [31:0] distram [0:1<<(AWIDTH-1)];

   always @(posedge clk_i)
     begin
	if(stb_i & we_i & sel_i[3])
	  distram[adr_i][31:24] <= dat_i[31:24];
	if(stb_i & we_i & sel_i[2])
	  distram[adr_i][24:16] <= dat_i[24:16];
	if(stb_i & we_i & sel_i[1])
	  distram[adr_i][15:8] <= dat_i[15:8];
	if(stb_i & we_i & sel_i[0])
	  distram[adr_i][7:0] <= dat_i[7:0];
     end // always @ (posedge clk_i)

   assign dat_o = distram[adr_i];
   assign ack_o = stb_i;

endmodule // wb_ram_dist
module system_control_tb();
   
   reg 	aux_clk, clk_fpga;
   wire wb_clk, dsp_clk;
   wire wb_rst, dsp_rst, rl_rst, proc_rst;

   reg 	rl_done, clock_ready;
   
   initial aux_clk = 1'b0;
   always #25 aux_clk = ~aux_clk;

   initial clk_fpga = 1'b0;

   initial clock_ready = 1'b0;
   initial
     begin
	@(negedge proc_rst);
	#1003 clock_ready <= 1'b1;
     end

   always #7 clk_fpga = ~clk_fpga;
      
   initial begin
      $dumpfile("system_control_tb.vcd");
      $dumpvars(0,system_control_tb);
   end

   initial #10000 $finish;

   initial
     begin
	@(negedge rl_rst);
	rl_done <= 1'b0;
	#1325 rl_done <= 1'b1;
     end

   initial
     begin
	@(negedge proc_rst);
	clock_ready <= 1'b0;
	#327 clock_ready <= 1'b1;
     end
     
   system_control 
     system_control(.aux_clk_i(aux_clk),.clk_fpga_i(clk_fpga),
		    .dsp_clk_o(dsp_clk),.wb_clk_o(wb_clk),
		    .ram_loader_rst_o(rl_rst),
		    .processor_rst_o(proc_rst),
		    .wb_rst_o(wb_rst),
		    .dsp_rst_o(dsp_rst),
		    .ram_loader_done_i(rl_done),
		    .clock_ready_i(clock_ready),
		    .debug_o());
   
endmodule // system_control_tb
module ram_2port
  #(parameter DWIDTH=32,
    parameter AWIDTH=9)
    (input clka,
     input ena,
     input wea,
     input [AWIDTH-1:0] addra,
     input [DWIDTH-1:0] dia,
     output reg [DWIDTH-1:0] doa,
     
     input clkb,
     input enb,
     input web,
     input [AWIDTH-1:0] addrb,
     input [DWIDTH-1:0] dib,
     output reg [DWIDTH-1:0] dob);
   
   reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
   integer 	    i;
   initial
     for(i=0;i<(1<<AWIDTH);i=i+1)
       ram[i] <= {DWIDTH{1'b0}};
   
   always @(posedge clka) begin
      if (ena)
        begin
           if (wea)
             ram[addra] <= dia;
           doa <= ram[addra];
        end
   end
   always @(posedge clkb) begin
      if (enb)
        begin
           if (web)
             ram[addrb] <= dib;
           dob <= ram[addrb];
        end
   end
endmodule // ram_2port
module pic
  (input clk_i, input rst_i, input cyc_i, input stb_i,
   input [2:0] adr_i, 
   input we_i, 
   input [31:0] dat_i, 
   output reg [31:0] dat_o, 
   output reg ack_o, 
   output reg int_o,
   input [31:0] irq
   );

   reg [31:0] 	pol, edgen, pending, mask;   // register bank
   reg [31:0] 	lirq, dirq;                  // latched irqs, delayed latched irqs
   
   // latch interrupt inputs
   always @(posedge clk_i)
     lirq <=  irq;
   
   // generate delayed latched irqs
   always @(posedge clk_i)
     dirq <=  lirq;

   // generate actual triggers
   function trigger;
      input 	edgen, pol, lirq, dirq;
      reg 	edge_irq, level_irq;
      begin
	 edge_irq  = pol ? (lirq & ~dirq) : (dirq & ~lirq);
	 level_irq = pol ? lirq : ~lirq;
	 trigger = edgen ? edge_irq : level_irq;
      end
   endfunction
   
   reg  [31:0] irq_event;
   integer     n;
   always @(posedge clk_i)
     for(n = 0; n < 32; n = n+1)
       irq_event[n] <=  trigger(edgen[n], pol[n], lirq[n], dirq[n]);

   // generate wishbone register bank writes
   wire        wb_acc = cyc_i & stb_i;                   // WISHBONE access
   wire        wb_wr  = wb_acc & we_i;                   // WISHBONE write access

   always @(posedge clk_i)
     if (rst_i)
       begin
          pol   <=  0;              // clear polarity register
          edgen <=  0;              // clear edge enable register
          mask  <=  0;              // mask all interrupts
       end
     else if(wb_wr)                               // wishbone write cycle??
       case (adr_i) // synopsys full_case parallel_case
         3'd0 : edgen <=  dat_i;        // EDGE-ENABLE register
         3'd1 : pol   <=  dat_i;        // POLARITY register
         3'd2 : mask  <=  dat_i;        // MASK register
         3'd3 : ;                       // PENDING register is a special case (see below)
	 3'd4 : ;                       // Priority encoded live (pending & ~mask)
       endcase

   // pending register is a special case
   always @(posedge clk_i)
     if (rst_i)
       pending <=  0;            // clear all pending interrupts
     else if ( wb_wr & (adr_i == 3'd3) )
       pending <=  (pending & ~dat_i) | irq_event;
     else
       pending <=  pending | irq_event;

   wire [31:0] live_enc;
   priority_enc priority_enc ( .in(pending & ~mask), .out(live_enc) );
   
   always @(posedge clk_i)
      case (adr_i) // synopsys full_case parallel_case
        3'd0 : dat_o <= edgen;
        3'd1 : dat_o <= pol;
        3'd2 : dat_o <= mask;
        3'd3 : dat_o <= pending;
	3'd4 : dat_o <= live_enc;
      endcase

   always @(posedge clk_i)
     ack_o <=  wb_acc & !ack_o;

   always @(posedge clk_i)
     if(rst_i)
       int_o <=  0;
     else
       int_o <=  |(pending & ~mask);
   
endmodule
module clock_control
  (input reset,
   input aux_clk,            // 25MHz, for before fpga clock is active
   input clk_fpga,           // real 100 MHz FPGA clock
   output [1:0] clk_en,      // controls source of reference clock
   output [1:0] clk_sel,     // controls source of reference clock
   input clk_func,          // FIXME needs to be some kind of out SYNC or reset to 9510
   input clk_status,         // Monitor PLL or SYNC status
   
   output sen,        // Enable for the AD9510
   output sclk,       // FIXME these need to be shared
   input sdi,
   output sdo
   );
   
   wire   read = 1'b0;    // Always write for now
   wire [1:0] w = 2'b00;  // Always send 1 byte at a time
   
   assign     clk_sel = 2'b00;  // Both outputs from External Ref (SMA)
   assign     clk_en = 2'b11;   // Both outputs enabled
   
   reg [20:0] addr_data;

   reg [5:0]  entry;
   reg 	      start;
   reg [7:0]  counter;
   reg [23:0] command;
   
   always @*
     case(entry)
       6'd00 : addr_data = {13'h00,8'h10};   // Serial setup
       6'd01 : addr_data = {13'h45,8'h00};   // CLK2 drives distribution, everything on
       6'd02 : addr_data = {13'h3D,8'h80};   // Turn on output 1, normal levels
       6'd03 : addr_data = {13'h4B,8'h80};   // Bypass divider 1 (div by 1)
       6'd04 : addr_data = {13'h08,8'h47};   // POS PFD, Dig LK Det, Charge Pump normal	
       6'd05 : addr_data = {13'h09,8'h70};   // Max Charge Pump current
       6'd06 : addr_data = {13'h0A,8'h04};   // Normal operation, Prescalar Div by 2, PLL On
       6'd07 : addr_data = {13'h0B,8'h00};   // RDIV MSB (6 bits)
       6'd08 : addr_data = {13'h0C,8'h01};   // RDIV LSB (8 bits), Div by 1
       6'd09 : addr_data = {13'h0D,8'h00};   // Everything normal, Dig Lock Det
       6'd10 : addr_data = {13'h07,8'h00};	// Disable LOR detect - LOR causes failure...
       6'd11 : addr_data = {13'h04,8'h00};	// A Counter = Don't Care
       6'd12 : addr_data = {13'h05,8'h00};	// B Counter MSB = 0
       6'd13 : addr_data = {13'h06,8'h05};   // B Counter LSB = 5
       default : addr_data = {13'h5A,8'h01}; // Register Update
     endcase // case(entry)

   wire [5:0]  lastentry = 6'd15;
   wire        done = (counter == 8'd49);
   
   always @(posedge aux_clk)
     if(reset)
       begin
	  entry <= #1 6'd0;
	  start <= #1 1'b1;
       end
     else if(start)
       start <= #1 1'b0;
     else if(done && (entry<lastentry))
       begin
	  entry <= #1 entry + 6'd1;
	  start <= #1 1'b1;
       end
   
   always @(posedge aux_clk)
     if(reset)
       begin
	  counter <= #1 7'd0;
	  command <= #1 20'd0;
       end
     else if(start)
       begin
	  counter <= #1 7'd1;
	  command <= #1 {read,w,addr_data};
       end
     else if( |counter && ~done )
       begin
	  counter <= #1 counter + 7'd1;
	  if(~counter[0])
	    command <= {command[22:0],1'b0};
       end
   
   
   assign sen = (done | counter == 8'd0);  // CSB is high when we're not doing anything
   assign sclk = ~counter[0];
   assign sdo = command[23];
   
endmodule // clock_control