dakies/OSS_Verilog huggingface dataset:
module pa_lsu_lm(
  cp0_lsu_icg_en,
  cpurst_b,
  forever_cpuclk,
  ifu_lsu_warm_up,
  lm_clr,
  lm_lr_bus,
  lm_pass,
  lm_sc_bus,
  lm_set,
  lm_set_gate,
  pad_yy_icg_scan_en,
  rtu_lsu_expt_ack,
  rtu_lsu_expt_exit
);

// &Ports; @21
input           cp0_lsu_icg_en;    
input           cpurst_b;          
input           forever_cpuclk;    
input           ifu_lsu_warm_up;   
input           lm_clr;            
input   [33:0]  lm_lr_bus;         
input   [33:0]  lm_sc_bus;         
input           lm_set;            
input           lm_set_gate;       
input           pad_yy_icg_scan_en; 
input           rtu_lsu_expt_ack;  
input           rtu_lsu_expt_exit; 
output          lm_pass;           

// &Regs; @22
reg     [33:0]  lm_bus_f;          
reg             lm_cur_state;      
reg             lm_next_state;     

// &Wires; @23
wire            cp0_lsu_icg_en;    
wire            cpurst_b;          
wire            forever_cpuclk;    
wire            ifu_lsu_warm_up;   
wire            lm_clk;            
wire            lm_clk_en;         
wire            lm_clr;            
wire    [33:0]  lm_lr_bus;         
wire            lm_pass;           
wire    [33:0]  lm_sc_bus;         
wire            lm_set;            
wire            lm_set_gate;       
wire            pad_yy_icg_scan_en; 
wire            rtu_lsu_expt_ack;  
wire            rtu_lsu_expt_exit; 


parameter LM_OPEN = 1'b0;
parameter LM_EXCL = 1'b1;

always@(posedge lm_clk or negedge cpurst_b)
begin
  if (!cpurst_b) 
    lm_cur_state <= LM_OPEN;
  else
    lm_cur_state <= lm_next_state;
end
      
// &CombBeg; @36
always @( rtu_lsu_expt_ack
       or lm_clr
       or lm_cur_state
       or lm_set
       or rtu_lsu_expt_exit)
begin
  case (lm_cur_state)
    LM_OPEN:begin
      if (lm_set & !rtu_lsu_expt_ack & !rtu_lsu_expt_exit)
        lm_next_state = LM_EXCL;
      else
        lm_next_state = LM_OPEN;
    end
    LM_EXCL:begin
      if (rtu_lsu_expt_ack | rtu_lsu_expt_exit | lm_clr)
        lm_next_state = LM_OPEN;
      else
        lm_next_state = LM_EXCL;
    end
    default: lm_next_state = LM_OPEN;
  endcase
// &CombEnd; @52
end
   
always@(posedge lm_clk)
begin
  if (ifu_lsu_warm_up)
    lm_bus_f[33:0] <= 34'b0;
  else if (lm_set)
    lm_bus_f[33:0] <= lm_lr_bus[33:0];
end

assign lm_pass = lm_cur_state & (lm_bus_f[33:0] == lm_sc_bus[33:0]);

assign lm_clk_en = lm_set_gate | (lm_cur_state == LM_EXCL) | ifu_lsu_warm_up;
// &Instance("gated_clk_cell", "x_pa_lsu_lm_gated_clk"); @77
gated_clk_cell  x_pa_lsu_lm_gated_clk (
  .clk_in             (forever_cpuclk    ),
  .clk_out            (lm_clk            ),
  .external_en        (1'b0              ),
  .global_en          (1'b1              ),
  .local_en           (lm_clk_en         ),
  .module_en          (cp0_lsu_icg_en    ),
  .pad_yy_icg_scan_en (pad_yy_icg_scan_en)
);

// &Connect(.clk_in      (forever_cpuclk), @78
//          .external_en (1'b0), @79
//          .global_en   (1'b1), @80
//          .module_en     (cp0_lsu_icg_en     ), @81
//          .local_en    (lm_clk_en), @82
//          .clk_out     (lm_clk)); @83

// &ModuleEnd; @85
endmodule
module pa_clic_ff1_onehot(
  data_in,
  ff1_out_onehot
);

parameter WIDTH = 32;

input  [WIDTH-1:0] data_in;
output [WIDTH-1:0] ff1_out_onehot;

wire [WIDTH:0] ff1_tmp;

assign ff1_tmp[WIDTH] = 1'b0;
genvar i;

generate
  for (i = 0; i < WIDTH; i = i+1)
  begin: FF1_ONEHOT
    assign ff1_tmp[i] = data_in[i] || ff1_tmp[i+1];
  end
endgenerate

assign ff1_out_onehot[WIDTH-1:0] = ff1_tmp[WIDTH:1] ^ ff1_tmp[WIDTH-1:0];

endmodule
module pa_clic_expand(
  // input
  data_in_vec,
  // output
  expand_out_vec
);

parameter WIDTH = 6;
parameter NUM   = 32;
localparam EXP_WIDTH = 1 <<< WIDTH;

input  [WIDTH*NUM-1:0]      data_in_vec;
output [EXP_WIDTH*NUM-1:0]  expand_out_vec;

wire   [WIDTH*NUM-1:0]      data_in_vec;
wire   [EXP_WIDTH*NUM-1:0]  expand_out_vec;

genvar i;

generate
  for (i = 0; i < NUM; i = i+1)
  begin: EXPAND
    assign expand_out_vec[EXP_WIDTH*i+:EXP_WIDTH] = {{EXP_WIDTH-1{1'b0}}, 1'b1} << data_in_vec[WIDTH*i+:WIDTH];
  end
endgenerate

endmodule
module pa_clic_sel(
  // input
  data_in,
  sel_in_onehot,
  // output
  data_out
);

parameter DATA_WIDTH   = 32;
parameter SEL_NUM      = 256;

input  [DATA_WIDTH*SEL_NUM-1:0] data_in;
input  [SEL_NUM-1:0]            sel_in_onehot;

output [DATA_WIDTH-1:0]         data_out;

wire   [DATA_WIDTH-1:0]         data_in_2d[SEL_NUM-1:0];
wire   [SEL_NUM-1:0]            data_in_2d_rev[DATA_WIDTH-1:0];
wire   [DATA_WIDTH-1:0]         data_out;

//==========================================================
//                  Generate 2D signal
//==========================================================
genvar i;
genvar j;

generate
  for (i = 0; i < SEL_NUM; i = i+1) begin: EXPAND
    assign data_in_2d[i][DATA_WIDTH-1:0] = data_in[i*DATA_WIDTH+:DATA_WIDTH] & {DATA_WIDTH{sel_in_onehot[i]}};
  end
endgenerate

//==========================================================
//                   Reverse 2D signal
//==========================================================
generate
  for (i = 0; i < SEL_NUM; i = i+1) begin: REVERSEI
    for (j = 0; j < DATA_WIDTH; j = j+1) begin: REVERSEJ
      assign data_in_2d_rev[j][i] = data_in_2d[i][j];
    end
  end
endgenerate

//==========================================================
//                     Do or to sel
//==========================================================
generate
  for (i = 0; i < DATA_WIDTH; i = i+1) begin: OR_SEL
    assign data_out[i] = |data_in_2d_rev[i][SEL_NUM-1:0];
  end
endgenerate


endmodule
module pa_clic_arb_32to1_kernel(
  // input
  prio_in_vec,
  // output
  prio_out_mid,
  sel_out_onehot
);

parameter PRIO_WIDTH   = 6;
parameter INT_NUM     = 32;
localparam PRIO_EXP_NUM = 1 <<< PRIO_WIDTH;

input  [PRIO_EXP_NUM*INT_NUM-1:0] prio_in_vec;
output [PRIO_EXP_NUM-1:0]         prio_out_mid;
output [INT_NUM-1:0]              sel_out_onehot;

wire   [PRIO_EXP_NUM*INT_NUM-1:0] prio_in_vec;
wire   [PRIO_EXP_NUM-1:0]         prio_out_mid;
wire   [INT_NUM-1:0]              sel_out_onehot;

wire   [PRIO_EXP_NUM-1:0]    prio_in_2d[INT_NUM-1:0];
wire   [INT_NUM-1:0]         prio_in_2d_rev[PRIO_EXP_NUM-1:0];

genvar i;
genvar j;
genvar k;

//==========================================================
//                   Generate 2D prio
//==========================================================
generate
  for (k = 0; k < INT_NUM; k = k+1)
  begin: EXPEND_PRIO
    assign prio_in_2d[k][PRIO_EXP_NUM-1:0] = prio_in_vec[PRIO_EXP_NUM*k+:PRIO_EXP_NUM];
  end
endgenerate

//==========================================================
//                   Reverse 2D signal
//==========================================================
generate
  for (i = 0; i < INT_NUM; i = i+1) begin: REVERSEI
    for (j = 0; j < PRIO_EXP_NUM; j = j+1) begin: REVERSEJ
      assign prio_in_2d_rev[j][i] = prio_in_2d[i][j];
    end
  end
endgenerate

wire   [PRIO_EXP_NUM-1:0]         high_prio_onehot;
wire   [PRIO_EXP_NUM-1:0]         prio_out;
//==========================================================
//                     Do or to sel
//==========================================================
generate
  for (i = 0; i < PRIO_EXP_NUM; i = i+1) begin: OR_SEL
    assign prio_out[i] = |prio_in_2d_rev[i][INT_NUM-1:0];
  end
endgenerate

assign prio_out_mid[PRIO_EXP_NUM-1:0] = prio_out[PRIO_EXP_NUM-1:0];

pa_clic_ff1_onehot #(PRIO_EXP_NUM) x_pa_clic_high_prio(
  .data_in        (prio_out),
  .ff1_out_onehot (high_prio_onehot)
);

wire   [PRIO_EXP_NUM-1:0]    prio_after_mask_2d[INT_NUM-1:0];
wire   [INT_NUM-1:0]         int_hit_prio;
generate
  for (k = 0; k < INT_NUM; k = k+1)
  begin: PRIO_MASK
    assign prio_after_mask_2d[k][PRIO_EXP_NUM-1:0] = prio_in_2d[k][PRIO_EXP_NUM-1:0] & high_prio_onehot[PRIO_EXP_NUM-1:0];
    assign int_hit_prio[k] = |prio_after_mask_2d[k][PRIO_EXP_NUM-1:0];
  end
endgenerate

wire   [INT_NUM-1:0]          int_sel_onehot;

pa_clic_ff1_onehot #(INT_NUM) x_pa_clic_num(
  .data_in        (int_hit_prio),
  .ff1_out_onehot (int_sel_onehot)
);

assign sel_out_onehot[INT_NUM-1:0] = int_sel_onehot[INT_NUM-1:0];

endmodule
module pa_fadd_shift_sub_single(
  data_in,
  data_out,
  shift_cnt
);

// &Ports; @24
input   [27:0]  data_in;       
input   [4 :0]  shift_cnt;     
output  [27:0]  data_out;      

// &Regs; @25
reg     [27:0]  data_shift;    

// &Wires; @26
wire    [4 :0]  cnt;           
wire    [27:0]  data_in;       
wire    [27:0]  data_out;      
wire    [27:0]  data_shift_pre; 
wire    [4 :0]  shift_cnt;     


assign data_shift_pre[27:0] = data_in[27:0];
assign data_out[27:0]       = data_shift[27:0];
assign cnt[4:0]             = shift_cnt[4:0];


// &CombBeg; @33
always @( cnt[4:0]
       or data_shift_pre[27:0])
begin
case(cnt[4:0])
  5'd0 : data_shift[27:0]   = data_shift_pre[27:0];
  5'd1 : data_shift[27:0]   = {data_shift_pre[26:0], 1'b0};
  5'd2 : data_shift[27:0]   = {data_shift_pre[25:0], 2'b0};
  5'd3 : data_shift[27:0]   = {data_shift_pre[24:0], 3'b0};
  5'd4 : data_shift[27:0]   = {data_shift_pre[23:0], 4'b0};
  5'd5 : data_shift[27:0]   = {data_shift_pre[22:0], 5'b0};
  5'd6 : data_shift[27:0]   = {data_shift_pre[21:0], 6'b0};
  5'd7 : data_shift[27:0]   = {data_shift_pre[20:0], 7'b0};
  5'd8 : data_shift[27:0]   = {data_shift_pre[19:0], 8'b0};
  5'd9 : data_shift[27:0]   = {data_shift_pre[18:0], 9'b0};
  5'd10 : data_shift[27:0]  = {data_shift_pre[17:0],10'b0};
  5'd11 : data_shift[27:0]  = {data_shift_pre[16:0],11'b0};
  5'd12 : data_shift[27:0]  = {data_shift_pre[15:0],12'b0};
  5'd13 : data_shift[27:0]  = {data_shift_pre[14:0],13'b0};
  5'd14 : data_shift[27:0]  = {data_shift_pre[13:0],14'b0};
  5'd15 : data_shift[27:0]  = {data_shift_pre[12:0],15'b0};
  5'd16 : data_shift[27:0]  = {data_shift_pre[11:0],16'b0};
  5'd17 : data_shift[27:0]  = {data_shift_pre[10:0],17'b0};
  5'd18 : data_shift[27:0]  = {data_shift_pre[9:0],18'b0};
  5'd19 : data_shift[27:0]  = {data_shift_pre[8:0],19'b0};
  5'd20 : data_shift[27:0]  = {data_shift_pre[7:0],20'b0};
  5'd21 : data_shift[27:0]  = {data_shift_pre[6:0],21'b0};
  5'd22 : data_shift[27:0]  = {data_shift_pre[5:0],22'b0};
  5'd23 : data_shift[27:0]  = {data_shift_pre[4:0],23'b0};
  5'd24 : data_shift[27:0]  = {data_shift_pre[3:0],24'b0};
  5'd25 : data_shift[27:0]  = {data_shift_pre[2:0],25'b0};
  5'd26 : data_shift[27:0]  = {data_shift_pre[1:0],26'b0};
  5'd27 : data_shift[27:0]  = {data_shift_pre[0],27'b0};
  default: data_shift[27:0] = 28'b0;
endcase
// &CombEnd; @65
end





// &ModuleEnd; @71
endmodule
module RAM128X1D(WCLK,D,WE,SPO,DPO,A,DPRA);
   input      WCLK; //write clock
   input      D; // write data input
   input      WE; // write enable
   output     SPO; // R/W port addressed by A
   output     DPO; // R port addressed by DPRA
   input [6:0] A; // R/W port address
   input [6:0] DPRA; // R port address
   parameter INIT = 128'd0;

   reg [127:0] ram = INIT;

   assign DPO = ram[DPRA];
   assign SPO=D;

   always @(posedge WCLK) begin
      if(WE) begin
         ram[A] <= D;
      end
   end



endmodule
module TXMOD(
  output TX,
  input CLK,
  input [7:0] data,
  input valid,
  output ready);

reg TXReg = 1;
assign TX = TXReg;

reg [10:0] dataStore = 1536; // MSB=1, LSB=0
reg writing = 0;
assign ready = (writing==0);

reg [13:0] writeClock = 0; // which cycle are we in?
reg [3:0] writeBit = 0; // which bit are we writing? (10 bits total)

always @(posedge CLK) begin
  if(writing==0 && valid==1) begin
    writing <= 1;
    dataStore[8:1] <= data;
    writeClock <= 100;
    writeBit <= 0;
    TXReg <= dataStore[0];
  end else if(writing==1 && writeClock==0 && writeBit==9) begin
    // we're done
    TXReg <= 1;
    writing <= 0;
  end else if(writing==1 && writeClock==0) begin
    // move on to next bit
    TXReg <= dataStore[writeBit];
    writeBit <= writeBit+1;
    writeClock <= 100;
  end else if(writing==1) begin
    TXReg <= dataStore[writeBit];
    writeClock <= writeClock - 1;
  end else begin
    TXReg <= 1;
  end 

end

endmodule
module RXMOD(
  input RX, 
  input CLK,
  output [7:0] data,
  output valid);

reg RX_1;
reg RX_2;
always @(posedge CLK) begin
  RX_1 <= RX;
  RX_2 <= RX_1;
end

wire RXi;
assign RXi = RX_2;

reg [8:0] dataReg;
reg validReg = 0;
assign data = dataReg[7:0];
assign valid = validReg;

reg [12:0] readClock = 0; // which subclock?
reg [3:0] readBit = 0; // which bit? (0-8)
reg reading = 0;


always @ (posedge CLK)
begin
  if(RXi==0 && reading==0) begin
    reading <= 1;
    readClock <= 150; // sample to middle of second byte
    readBit <= 0;
    validReg <= 0;
  end else if(reading==1 && readClock==0 && readBit==8) begin
    // we're done
    reading <= 0;
    dataReg[8] <= RXi;
    validReg <= 1;
  end else if(reading==1 && readClock==0) begin
    // read a byte
    dataReg[readBit] <= RXi;
    readClock <= 100;
    readBit <= readBit + 1;
    validReg <= 0;
  end else if(reading==1 && readClock>0) begin
    readClock <= readClock - 1;
    validReg <= 0;
  end else begin
    validReg <= 0;
  end
end
endmodule
module DRAMReader(
    //AXI port
    input wire ACLK,
    input wire ARESETN,
    output reg [31:0] M_AXI_ARADDR,
    input wire M_AXI_ARREADY,
    output wire  M_AXI_ARVALID,
    input wire [63:0] M_AXI_RDATA,
    output wire M_AXI_RREADY,
    input wire [1:0] M_AXI_RRESP,
    input wire M_AXI_RVALID,
    input wire M_AXI_RLAST,
    output wire [3:0] M_AXI_ARLEN,
    output wire [1:0] M_AXI_ARSIZE,
    output wire [1:0] M_AXI_ARBURST,
    
    //Control config
    input wire CONFIG_VALID,
    output wire CONFIG_READY,
    input wire [31:0] CONFIG_START_ADDR,
    input wire [31:0] CONFIG_NBYTES,
    
    //RAM port
    input wire DATA_READY_DOWNSTREAM,
    output wire DATA_VALID,
    output wire [63:0] DATA
);

assign M_AXI_ARLEN = 4'b1111;
assign M_AXI_ARSIZE = 2'b11;
assign M_AXI_ARBURST = 2'b01;
parameter IDLE = 0, RWAIT = 1;
    
//ADDR logic
reg [31:0] a_count;
reg a_state;  
assign M_AXI_ARVALID = (a_state == RWAIT);
always @(posedge ACLK) begin
    if (ARESETN == 0) begin
        a_state <= IDLE;
        M_AXI_ARADDR <= 0;
        a_count <= 0;
    end else case(a_state)
        IDLE: begin
            if(CONFIG_VALID) begin
                M_AXI_ARADDR <= CONFIG_START_ADDR;
                a_count <= CONFIG_NBYTES[31:7];
                a_state <= RWAIT;
            end
        end
        RWAIT: begin
            if (M_AXI_ARREADY == 1) begin
                if(a_count - 1 == 0)
                    a_state <= IDLE;
                a_count <= a_count - 1;
                M_AXI_ARADDR <= M_AXI_ARADDR + 128; // Bursts are 128 bytes long
            end
        end
    endcase
end
    
//READ logic
reg [31:0] b_count;
reg r_state;
assign M_AXI_RREADY = (r_state == RWAIT) && DATA_READY_DOWNSTREAM;
always @(posedge ACLK) begin
    if (ARESETN == 0) begin
        r_state <= IDLE;
        b_count <= 0;
    end else case(r_state)
        IDLE: begin
            if(CONFIG_VALID) begin
                b_count <= {CONFIG_NBYTES[31:7],7'b0}; // round to nearest 128 bytes
                r_state <= RWAIT;
            end
        end
        RWAIT: begin
            if (M_AXI_RVALID && DATA_READY_DOWNSTREAM) begin
                //use M_AXI_RDATA
                if(b_count - 8 == 0)
                    r_state <= IDLE;
                b_count <= b_count - 8; // each valid cycle the bus provides 8 bytes
            end
        end
    endcase
end

assign DATA = M_AXI_RDATA;
assign DATA_VALID = M_AXI_RVALID && (r_state == RWAIT);
assign CONFIG_READY = (r_state == IDLE) && (a_state == IDLE);

endmodule // DRAMReader
module DRAMWriter(
    //AXI port
    input wire ACLK,
    input wire ARESETN,
    output reg [31:0] M_AXI_AWADDR,
    input wire M_AXI_AWREADY,
    output wire M_AXI_AWVALID,
    
    output wire [63:0] M_AXI_WDATA,
    output wire [7:0] M_AXI_WSTRB,
    input wire M_AXI_WREADY,
    output wire M_AXI_WVALID,
    output wire M_AXI_WLAST,
    
    input wire [1:0] M_AXI_BRESP,
    input wire M_AXI_BVALID,
    output wire M_AXI_BREADY,
    
    output wire [3:0] M_AXI_AWLEN,
    output wire [1:0] M_AXI_AWSIZE,
    output wire [1:0] M_AXI_AWBURST,
    
    //Control config
    input wire CONFIG_VALID,
    output wire CONFIG_READY,
    input wire [31:0] CONFIG_START_ADDR,
    input wire [31:0] CONFIG_NBYTES,
    
    //RAM port
    input wire [63:0] DATA,
    output wire DATA_READY,
    input wire DATA_VALID

);

assign M_AXI_AWLEN = 4'b1111;
assign M_AXI_AWSIZE = 2'b11;
assign M_AXI_AWBURST = 2'b01;
assign M_AXI_WSTRB = 8'b11111111;

parameter IDLE = 0, RWAIT = 1;
    
//ADDR logic
reg [31:0] a_count;
reg a_state;  
assign M_AXI_AWVALID = (a_state == RWAIT);
always @(posedge ACLK) begin
    if (ARESETN == 0) begin
        a_state <= IDLE;
        M_AXI_AWADDR <= 0;
        a_count <= 0;
    end else case(a_state)
        IDLE: begin
            if(CONFIG_VALID) begin
                M_AXI_AWADDR <= CONFIG_START_ADDR;
                a_count <= CONFIG_NBYTES[31:7];
                a_state <= RWAIT;
            end
        end
        RWAIT: begin
            if (M_AXI_AWREADY == 1) begin
                if(a_count - 1 == 0)
                    a_state <= IDLE;
                a_count <= a_count - 1;
                M_AXI_AWADDR <= M_AXI_AWADDR + 128; 
            end
        end
    endcase
end

//WRITE logic
reg [31:0] b_count;
reg w_state;
reg [3:0] last_count;

always @(posedge ACLK) begin
    if (ARESETN == 0) begin
        w_state <= IDLE;
        b_count <= 0;
    end else case(w_state)
        IDLE: begin
            if(CONFIG_VALID) begin
                b_count <= {CONFIG_NBYTES[31:7],7'b0};
                w_state <= RWAIT;
                last_count <= 4'b1111;
            end
        end
        RWAIT: begin
            if (M_AXI_WREADY && M_AXI_WVALID) begin
                //use M_AXI_WDATA
                if(b_count - 8 == 0) begin
                    w_state <= IDLE;
                end
                last_count <= last_count - 4'b1;
                b_count <= b_count - 8;
            end
        end
    endcase
end

assign M_AXI_WLAST = last_count == 4'b0000;

assign M_AXI_WVALID = (w_state == RWAIT) && DATA_VALID;

assign DATA_READY = (w_state == RWAIT) && M_AXI_WREADY;
   
assign CONFIG_READY = (w_state == IDLE) && (a_state == IDLE);

assign M_AXI_BREADY = 1;

assign M_AXI_WDATA = DATA;

endmodule // DRAMWriter
module RGBReader (
    
    input       pclk,           // PCLK
    input       rst_n,            // 0 - Reset.
    input       [7:0] din,        // D0 - D7
    input       vsync,          // VSYNC
    input       href,           // HREF
    output reg  pixel_valid,     // Indicates that a pixel has been received.
    output reg  [15:0] pixel,   // RGB565 pixel.
    output      vstart,           // first pixel of frame
    output      hstart,           // first pixel of line

    input       start, // pulse
    input       stop,    // TODO does not do anythingh
    output reg [31:0] hlen,
    output reg [31:0] vlen
    );

    reg         odd;
    reg         frameValid;
    reg         href_p2;
    reg         vsync_p2;
    reg         saw_vsync;
    
    //hlen should reset every !href
    
    wire href_posedge;
    wire href_negedge;
    wire vsync_posedge;
    assign href_posedge = !href_p2 && href ;
    assign href_negedge = href_p2 && !href ;
    assign vsync_posedge = !vsync_p2 && vsync ;
    
    reg [31:0] pix_cnt;
    `REG(pclk, pix_cnt, 32'h0,
        href ? (pix_cnt+1'b1) : 0 )
    `REG(pclk, hlen, 0, href_negedge ? pix_cnt : hlen)
    
    reg [31:0] ln_cnt;
    `REG(pclk, ln_cnt, 32'h0, 
        vsync ? 32'h0 : (href_posedge ? ln_cnt+1'b1 : ln_cnt))
    `REG(pclk, vlen, 32'h0, vsync_posedge ? ln_cnt : vlen)


    // Only anding with pixel_valid just in case
    assign hstart = !href_p2 && href ;
    assign vstart = hstart && saw_vsync ;
    
    `REG(pclk, saw_vsync, 0, 
        vsync ? 1'b1 : (vstart ? 1'b0 : saw_vsync)
    )
    
    reg running;
    `REG(pclk, running, 0,
        start ? 1'b1 : running
    )
    wire [7:0] din2;
    assign din2 = din;//{din[0],din[1],din[2],din[3],din[4],din[5],din[6],din[7]};
    always @(posedge pclk or negedge rst_n) begin
        if (rst_n == 0) begin
            pixel_valid <= 0;
            odd <= 0;
            frameValid <= 0;
            href_p2 <= 1'b0;
            vsync_p2 <= 1'b0;
        end 
        else begin
            pixel_valid <= 0;
            href_p2 <= href;
            vsync_p2 <= vsync;
            if (frameValid == 1 && vsync == 0 && href == 1) begin
                if (odd==0) begin    
                    pixel[7:0] <= din2;
                end
                else begin
                    pixel[15:8] <= din2;
                    pixel_valid <= 1;
                end
                odd <= ~odd;
                // skip inital frame in case we started receiving in the middle of it
            end 
            else if (running && frameValid == 0 && vsync == 1) begin
                frameValid <= 1;
            end
        end
    end
   
endmodule
module CamReader (
    
    input       pclk,           // PCLK
    input       rst_n,            // 0 - Reset.
    input       [7:0] din,        // D0 - D7
    input       vsync,          // VSYNC
    input       href,           // HREF
    output      pixel_valid,     // Indicates that a pixel has been received.
    output reg  [7:0] pixel,   // Raw pixel

    input       start, // pulse
    input       stop,    // TODO does not do anythingh
    output reg [31:0] hlen,
    output reg [31:0] vlen
    );

    reg         odd;
    reg         frameValid;
    reg         href_p1;
    reg         href_p2;
    reg         href_p3;
    reg         vsync_p1;
    reg         vsync_p2;
    
    wire real_href;
    wire real_vsync;
    reg real_vsync_p1;
    wire vsync_posedge;




    reg running;
    `REG(pclk, running, 0, start ? 1'b1 : running)
    `REG(pclk, frameValid, 0, (running && !frameValid && real_vsync) ? 1'b1 : frameValid)

    reg [7:0] din_p1;
    reg [7:0] din_p2;
    `REG(pclk, din_p1[7:0], 8'hFF, din[7:0])
    `REG(pclk, din_p2[7:0], 8'hFF, din_p1[7:0])
    `REG(pclk, pixel[7:0], 8'hFF, din_p2[7:0])
    localparam IDLE=0, HBLANK=1, HACT=2;
    reg [10:0] pix_cnt_n;
    reg [10:0] pix_cnt;
    
    reg [1:0] pix_ns;
    reg [1:0] pix_cs;

    assign pixel_valid = (pix_cs == HACT);
    always @(*) begin
        case(pix_cs)
            IDLE : begin
                pix_ns = frameValid ? HBLANK : IDLE;
                pix_cnt_n = 0;
            end
            HBLANK : begin
                pix_ns = real_href ? HACT : HBLANK ;
                pix_cnt_n = real_href ? `PIX_PER_LINE : 0;
            end
            HACT : begin
                pix_ns = (pix_cnt == 1) ? HBLANK : HACT ;
                pix_cnt_n = pix_cnt - 1'b1;
            end
            default : begin
                pix_ns = IDLE ;
                pix_cnt_n = 0;
            end
        endcase

    end
    `REG(pclk, pix_cs, IDLE, pix_ns) 
    `REG(pclk, pix_cnt, 0, pix_cnt_n) 


    assign vsync_posedge = !real_vsync_p1 && real_vsync;
    assign real_href = href && href_p1 && href_p2 && !href_p3 && !real_vsync;
    assign real_vsync = vsync && vsync_p1 && vsync_p2;

    `REG(pclk, href_p1, 1'b0, href)
    `REG(pclk, href_p2, 1'b0, href_p1)
    `REG(pclk, href_p3, 1'b0, href_p2)
    `REG(pclk, vsync_p1, 1'b0, vsync)
    `REG(pclk, vsync_p2, 1'b0, vsync_p1)
    `REG(pclk, real_vsync_p1, 1'b0, real_vsync)


    reg pixel_valid_p1;
    `REG(pclk, pixel_valid_p1, 0, pixel_valid)

    reg [10:0] st_pix_cnt;
    `REG(pclk, st_pix_cnt, 32'h0,
        pixel_valid ? (st_pix_cnt+1'b1) : 0 )
    `REG(pclk, hlen, 0, (frameValid && pixel_valid_p1 && !pixel_valid && (st_pix_cnt!= 640)) ? st_pix_cnt : hlen)
    
    reg [10:0] ln_cnt;
    `REG(pclk, ln_cnt, 32'h0, 
        real_vsync ? 32'h0 : (pixel_valid && !pixel_valid_p1 ? ln_cnt+1'b1 : ln_cnt))
    `REG(pclk, vlen, 32'h0, (vsync_posedge && (ln_cnt !=480) ) ? ln_cnt : vlen)



endmodule
module
    addRecFN#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(`floatControlWidth - 1):0] control,
        input subOp,
        input [(expWidth + sigWidth):0] a,
        input [(expWidth + sigWidth):0] b,
        input [2:0] roundingMode,
        output [(expWidth + sigWidth):0] out,
        output [4:0] exceptionFlags
    );

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire invalidExc, out_isNaN, out_isInf, out_isZero, out_sign;
    wire signed [(expWidth + 1):0] out_sExp;
    wire [(sigWidth + 2):0] out_sig;
    addRecFNToRaw#(expWidth, sigWidth)
        addRecFNToRaw(
            control,
            subOp,
            a,
            b,
            roundingMode,
            invalidExc,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig
        );
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    roundRawFNToRecFN#(expWidth, sigWidth, `flRoundOpt_subnormsAlwaysExact)
        roundRawOut(
            control,
            invalidExc,
            1'b0,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig,
            roundingMode,
            out,
            exceptionFlags
        );

endmodule
module
    divSqrtRecFN_small#(
        parameter expWidth = 3, parameter sigWidth = 3, parameter options = 0
    ) (
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        input nReset,
        input clock,
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        input [(`floatControlWidth - 1):0] control,
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        output inReady,
        input inValid,
        input sqrtOp,
        input [(expWidth + sigWidth):0] a,
        input [(expWidth + sigWidth):0] b,
        input [2:0] roundingMode,
        /*--------------------------------------------------------------------
        *--------------------------------------------------------------------*/
        output outValid,
        output sqrtOpOut,
        output [(expWidth + sigWidth):0] out,
        output [4:0] exceptionFlags
    );

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    //wire sqrtOpOut;
    wire [2:0] roundingModeOut;
    wire invalidExc, infiniteExc, out_isNaN, out_isInf, out_isZero, out_sign;
    wire signed [(expWidth + 1):0] out_sExp;
    wire [(sigWidth + 2):0] out_sig;
    divSqrtRecFNToRaw_small#(expWidth, sigWidth, options)
        divSqrtRecFNToRaw(
            nReset,
            clock,
            control,
            inReady,
            inValid,
            sqrtOp,
            a,
            b,
            roundingMode,
            outValid,
            sqrtOpOut,
            roundingModeOut,
            invalidExc,
            infiniteExc,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig
        );
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    roundRawFNToRecFN#(expWidth, sigWidth, 0)
        roundRawOut(
            control,
            invalidExc,
            infiniteExc,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig,
            roundingModeOut,
            out,
            exceptionFlags
        );

endmodule
module
    recFNToRawFN#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(expWidth + sigWidth):0] in,
        output isNaN,
        output isInf,
        output isZero,
        output sign,
        output signed [(expWidth + 1):0] sExp,
        output [sigWidth:0] sig
    );

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire [expWidth:0] exp;
    wire [(sigWidth - 2):0] fract;
    assign {sign, exp, fract} = in;
    wire isSpecial = (exp>>(expWidth - 1) == 'b11);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    assign isNaN = isSpecial &&  exp[expWidth - 2];
    assign isInf = isSpecial && !exp[expWidth - 2];
    assign isZero = (exp>>(expWidth - 2) == 'b000);
    assign sExp = exp;
    assign sig = {1'b0, !isZero, fract};

endmodule
module
    roundRawFNToRecFN#(
        parameter expWidth = 3,
        parameter sigWidth = 3,
        parameter options = 0
    ) (
        input [(`floatControlWidth - 1):0] control,
        input invalidExc,     // overrides 'infiniteExc' and 'in_*' inputs
        input infiniteExc,    // overrides 'in_*' inputs except 'in_sign'
        input in_isNaN,
        input in_isInf,
        input in_isZero,
        input in_sign,
        input signed [(expWidth + 1):0] in_sExp,   // limited range allowed
        input [(sigWidth + 2):0] in_sig,
        input [2:0] roundingMode,
        output [(expWidth + sigWidth):0] out,
        output [4:0] exceptionFlags
    );

    roundAnyRawFNToRecFN#(expWidth, sigWidth + 2, expWidth, sigWidth, options)
        roundAnyRawFNToRecFN(
            control,
            invalidExc,
            infiniteExc,
            in_isNaN,
            in_isInf,
            in_isZero,
            in_sign,
            in_sExp,
            in_sig,
            roundingMode,
            out,
            exceptionFlags
        );

endmodule
module
    mulRecFNToFullRaw#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(`floatControlWidth - 1):0] control,
        input [(expWidth + sigWidth):0] a,
        input [(expWidth + sigWidth):0] b,
        output invalidExc,
        output out_isNaN,
        output out_isInf,
        output out_isZero,
        output out_sign,
        output signed [(expWidth + 1):0] out_sExp,
        output [(sigWidth*2 - 1):0] out_sig
    );

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire isNaNA, isInfA, isZeroA, signA;
    wire signed [(expWidth + 1):0] sExpA;
    wire [sigWidth:0] sigA;
    recFNToRawFN#(expWidth, sigWidth)
        recFNToRawFN_a(a, isNaNA, isInfA, isZeroA, signA, sExpA, sigA);
    wire isSigNaNA;
    isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_a(a, isSigNaNA);
    wire isNaNB, isInfB, isZeroB, signB;
    wire signed [(expWidth + 1):0] sExpB;
    wire [sigWidth:0] sigB;
    recFNToRawFN#(expWidth, sigWidth)
        recFNToRawFN_b(b, isNaNB, isInfB, isZeroB, signB, sExpB, sigB);
    wire isSigNaNB;
    isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_b(b, isSigNaNB);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire notSigNaN_invalidExc = (isInfA && isZeroB) || (isZeroA && isInfB);
    wire notNaN_isInfOut = isInfA || isInfB;
    wire notNaN_isZeroOut = isZeroA || isZeroB;
    wire notNaN_signOut = signA ^ signB;
    wire signed [(expWidth + 1):0] common_sExpOut =
        sExpA + sExpB - (1<<expWidth);
    wire [(sigWidth*2 - 1):0] common_sigOut = sigA * sigB;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    assign invalidExc = isSigNaNA || isSigNaNB || notSigNaN_invalidExc;
    assign out_isInf = notNaN_isInfOut;
    assign out_isZero = notNaN_isZeroOut;
    assign out_sExp = common_sExpOut;
`ifdef HardFloat_propagateNaNPayloads
    assign out_isNaN = isNaNA || isNaNB || notSigNaN_invalidExc;
    wire signNaN;
    wire [(sigWidth - 2):0] fractNaN;
    propagateFloatNaN_mul#(sigWidth)
        propagateNaN(
            control,
            isNaNA,
            signA,
            sigA[(sigWidth - 2):0],
            isNaNB,
            signB,
            sigB[(sigWidth - 2):0],
            signNaN,
            fractNaN
        );
    assign out_sign = out_isNaN ? signNaN : notNaN_signOut;
    assign out_sig =
        out_isNaN ? {1'b1, fractNaN}<<(sigWidth - 1) : common_sigOut;
`else
    assign out_isNaN = isNaNA || isNaNB;
    assign out_sign = notNaN_signOut;
    assign out_sig = common_sigOut;
`endif

endmodule
module
    mulRecFNToRaw#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(`floatControlWidth - 1):0] control,
        input [(expWidth + sigWidth):0] a,
        input [(expWidth + sigWidth):0] b,
        output invalidExc,
        output out_isNaN,
        output out_isInf,
        output out_isZero,
        output out_sign,
        output signed [(expWidth + 1):0] out_sExp,
        output [(sigWidth + 2):0] out_sig
    );

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire isNaNA, isInfA, isZeroA, signA;
    wire signed [(expWidth + 1):0] sExpA;
    wire [sigWidth:0] sigA;
    recFNToRawFN#(expWidth, sigWidth)
        recFNToRawFN_a(a, isNaNA, isInfA, isZeroA, signA, sExpA, sigA);
    wire isSigNaNA;
    isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_a(a, isSigNaNA);
    wire isNaNB, isInfB, isZeroB, signB;
    wire signed [(expWidth + 1):0] sExpB;
    wire [sigWidth:0] sigB;
    recFNToRawFN#(expWidth, sigWidth)
        recFNToRawFN_b(b, isNaNB, isInfB, isZeroB, signB, sExpB, sigB);
    wire isSigNaNB;
    isSigNaNRecFN#(expWidth, sigWidth) isSigNaN_b(b, isSigNaNB);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire notSigNaN_invalidExc = (isInfA && isZeroB) || (isZeroA && isInfB);
    wire notNaN_isInfOut = isInfA || isInfB;
    wire notNaN_isZeroOut = isZeroA || isZeroB;
    wire notNaN_signOut = signA ^ signB;
    wire signed [(expWidth + 1):0] common_sExpOut =
        sExpA + sExpB - (1<<expWidth);
    wire [(sigWidth*2 - 1):0] sigProd = sigA * sigB;
    wire [(sigWidth + 2):0] common_sigOut =
        {sigProd[(sigWidth*2 - 1):(sigWidth - 2)], |sigProd[(sigWidth - 3):0]};
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    assign invalidExc = isSigNaNA || isSigNaNB || notSigNaN_invalidExc;
    assign out_isInf = notNaN_isInfOut;
    assign out_isZero = notNaN_isZeroOut;
    assign out_sExp = common_sExpOut;
`ifdef HardFloat_propagateNaNPayloads
    assign out_isNaN = isNaNA || isNaNB || notSigNaN_invalidExc;
    wire signNaN;
    wire [(sigWidth - 2):0] fractNaN;
    propagateFloatNaN_mul#(sigWidth)
        propagateNaN(
            control,
            isNaNA,
            signA,
            sigA[(sigWidth - 2):0],
            isNaNB,
            signB,
            sigB[(sigWidth - 2):0],
            signNaN,
            fractNaN
        );
    assign out_sign = out_isNaN ? signNaN : notNaN_signOut;
    assign out_sig = out_isNaN ? {1'b1, fractNaN, 2'b00} : common_sigOut;
`else
    assign out_isNaN = isNaNA || isNaNB;
    assign out_sign = notNaN_signOut;
    assign out_sig = common_sigOut;
`endif

endmodule
module
    mulRecFN#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(`floatControlWidth - 1):0] control,
        input [(expWidth + sigWidth):0] a,
        input [(expWidth + sigWidth):0] b,
        input [2:0] roundingMode,
        output [(expWidth + sigWidth):0] out,
        output [4:0] exceptionFlags
    );

    wire invalidExc, out_isNaN, out_isInf, out_isZero, out_sign;
    wire signed [(expWidth + 1):0] out_sExp;
    wire [(sigWidth + 2):0] out_sig;
    mulRecFNToRaw#(expWidth, sigWidth)
        mulRecFNToRaw(
            control,
            a,
            b,
            invalidExc,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig
        );
    roundRawFNToRecFN#(expWidth, sigWidth, 0)
        roundRawOut(
            control,
            invalidExc,
            1'b0,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig,
            roundingMode,
            out,
            exceptionFlags
        );

endmodule
module
    isSigNaNRecFN#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(expWidth + sigWidth):0] in, output isSigNaN
    );

    wire isNaN =
        (in[(expWidth + sigWidth - 1):(expWidth + sigWidth - 3)] == 'b111);
    assign isSigNaN = isNaN && !in[sigWidth - 2];

endmodule
module
    reverse#(parameter width = 1) (
        input [(width - 1):0] in, output [(width - 1):0] out
    );

    genvar ix;
    generate
        for (ix = 0; ix < width; ix = ix + 1) begin :Bit
            assign out[ix] = in[width - 1 - ix];
        end
    endgenerate

endmodule
module
    lowMaskHiLo#(
        parameter inWidth = 1,
        parameter topBound = 1,
        parameter bottomBound = 0
    ) (
        input [(inWidth - 1):0] in,
        output [(topBound - bottomBound - 1):0] out
    );

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    localparam numInVals = 1<<inWidth;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire signed [numInVals:0] c;
    assign c[numInVals] = 1;
    assign c[(numInVals - 1):0] = 0;
    wire [(topBound - bottomBound - 1):0] reverseOut =
        (c>>>in)>>(numInVals - topBound);
    reverse#(topBound - bottomBound) reverse(reverseOut, out);

endmodule
module
    lowMaskLoHi#(
        parameter inWidth = 1,
        parameter topBound = 0,
        parameter bottomBound = 1
    ) (
        input [(inWidth - 1):0] in,
        output [(bottomBound - topBound - 1):0] out
    );

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    localparam numInVals = 1<<inWidth;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire signed [numInVals:0] c;
    assign c[numInVals] = 1;
    assign c[(numInVals - 1):0] = 0;
    wire [(bottomBound - topBound - 1):0] reverseOut =
        (c>>>~in)>>(topBound + 1);
    reverse#(bottomBound - topBound) reverse(reverseOut, out);

endmodule
module
    countLeadingZeros#(parameter inWidth = 1, parameter countWidth = 1) (
        input [(inWidth - 1):0] in, output [(countWidth - 1):0] count
    );

    wire [(inWidth - 1):0] reverseIn;
    reverse#(inWidth) reverse_in(in, reverseIn);
    wire [inWidth:0] oneLeastReverseIn =
        {1'b1, reverseIn} & ({1'b0, ~reverseIn} + 1);
    genvar ix;
    generate
        for (ix = 0; ix <= inWidth; ix = ix + 1) begin :Bit
            wire [(countWidth - 1):0] countSoFar;
            if (ix == 0) begin
                assign countSoFar = 0;
            end else begin
                assign countSoFar =
                    Bit[ix - 1].countSoFar | (oneLeastReverseIn[ix] ? ix : 0);
                if (ix == inWidth) assign count = countSoFar;
            end
        end
    endgenerate

endmodule
module
    compressBy2#(parameter inWidth = 1) (
        input [(inWidth - 1):0] in, output [((inWidth - 1)/2):0] out
    );

    localparam maxBitNumReduced = (inWidth - 1)/2;
    genvar ix;
    generate
        for (ix = 0; ix < maxBitNumReduced; ix = ix + 1) begin :Bit
            assign out[ix] = |in[(ix*2 + 1):ix*2];
        end
    endgenerate
    assign out[maxBitNumReduced] = |in[(inWidth - 1):maxBitNumReduced*2];

endmodule
module
    compressBy4#(parameter inWidth = 1) (
        input [(inWidth - 1):0] in, output [(inWidth - 1)/4:0] out
    );

    localparam maxBitNumReduced = (inWidth - 1)/4;
    genvar ix;
    generate
        for (ix = 0; ix < maxBitNumReduced; ix = ix + 1) begin :Bit
            assign out[ix] = |in[(ix*4 + 3):ix*4];
        end
    endgenerate
    assign out[maxBitNumReduced] = |in[(inWidth - 1):maxBitNumReduced*4];

endmodule
module
    iNToRawFN#(parameter intWidth = 1) (signedIn, in, isZero, sign, sExp, sig);
`include "HardFloat_localFuncs.vi"
    localparam expWidth = clog2(intWidth) + 1;
    input signedIn;
    input [(intWidth - 1):0] in;
    output isZero;
    output sign;
    output signed [(expWidth + 1):0] sExp;
    output [intWidth:0] sig;

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    localparam extIntWidth = 1<<(expWidth - 1);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    assign sign = signedIn && in[intWidth - 1];
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire [(intWidth - 1):0] absIn = sign ? -in : in;
    wire [(extIntWidth - 1):0] extAbsIn = absIn;
    wire [(expWidth - 2):0] adjustedNormDist;
    countLeadingZeros#(extIntWidth, expWidth - 1)
        countLeadingZeros(extAbsIn, adjustedNormDist);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    assign sig = (extAbsIn<<adjustedNormDist)>>(extIntWidth - intWidth);
    assign isZero = !sig[intWidth - 1];
    assign sExp = {2'b10, ~adjustedNormDist};

endmodule
module
    iNToRecFN#(
        parameter intWidth = 1, parameter expWidth = 3, parameter sigWidth = 3
    ) (
        input [(`floatControlWidth - 1):0] control,
        input signedIn,
        input [(intWidth - 1):0] in,
        input [2:0] roundingMode,
        output [(expWidth + sigWidth):0] out,
        output [4:0] exceptionFlags
    );
`include "HardFloat_localFuncs.vi"

    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    localparam intExpWidth = clog2(intWidth) + 1;
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    wire isZero, sign;
    wire signed [(intExpWidth + 1):0] sExp;
    wire [intWidth:0] sig;
    iNToRawFN#(intWidth) iNToRawFN(signedIn, in, isZero, sign, sExp, sig);
    /*------------------------------------------------------------------------
    *------------------------------------------------------------------------*/
    roundAnyRawFNToRecFN#(
        intExpWidth,
        intWidth,
        expWidth,
        sigWidth,
        `flRoundOpt_sigMSBitAlwaysZero | `flRoundOpt_neverUnderflows
    ) roundRawToOut(
            control,
            1'b0,
            1'b0,
            1'b0,
            1'b0,
            isZero,
            sign,
            sExp,
            sig,
            roundingMode,
            out,
            exceptionFlags
        );

endmodule
module
    mulAddRecFNToRaw#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(`floatControlWidth - 1):0] control,
        input [1:0] op,
        input [(expWidth + sigWidth):0] a,
        input [(expWidth + sigWidth):0] b,
        input [(expWidth + sigWidth):0] c,
        input [2:0] roundingMode,
        output invalidExc,
        output out_isNaN,
        output out_isInf,
        output out_isZero,
        output out_sign,
        output signed [(expWidth + 1):0] out_sExp,
        output [(sigWidth + 2):0] out_sig
    );
`include "HardFloat_localFuncs.vi"

    wire [(sigWidth - 1):0] mulAddA, mulAddB;
    wire [(sigWidth*2 - 1):0] mulAddC;
    wire [5:0] intermed_compactState;
    wire signed [(expWidth + 1):0] intermed_sExp;
    wire [(clog2(sigWidth + 1) - 1):0] intermed_CDom_CAlignDist;
    wire [(sigWidth + 1):0] intermed_highAlignedSigC;
    mulAddRecFNToRaw_preMul#(expWidth, sigWidth)
        mulAddToRaw_preMul(
            control,
            op,
            a,
            b,
            c,
            roundingMode,
            mulAddA,
            mulAddB,
            mulAddC,
            intermed_compactState,
            intermed_sExp,
            intermed_CDom_CAlignDist,
            intermed_highAlignedSigC
        );
    wire [sigWidth*2:0] mulAddResult = mulAddA * mulAddB + mulAddC;
    mulAddRecFNToRaw_postMul#(expWidth, sigWidth)
        mulAddToRaw_postMul(
            intermed_compactState,
            intermed_sExp,
            intermed_CDom_CAlignDist,
            intermed_highAlignedSigC,
            mulAddResult,
            roundingMode,
            invalidExc,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig
        );

endmodule
module
    mulAddRecFN#(parameter expWidth = 3, parameter sigWidth = 3) (
        input [(`floatControlWidth - 1):0] control,
        input [1:0] op,
        input [(expWidth + sigWidth):0] a,
        input [(expWidth + sigWidth):0] b,
        input [(expWidth + sigWidth):0] c,
        input [2:0] roundingMode,
        output [(expWidth + sigWidth):0] out,
        output [4:0] exceptionFlags
    );

    wire invalidExc, out_isNaN, out_isInf, out_isZero, out_sign;
    wire signed [(expWidth + 1):0] out_sExp;
    wire [(sigWidth + 2):0] out_sig;
    mulAddRecFNToRaw#(expWidth, sigWidth)
        mulAddRecFNToRaw(
            control,
            op,
            a,
            b,
            c,
            roundingMode,
            invalidExc,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig
        );
    roundRawFNToRecFN#(expWidth, sigWidth, 0)
        roundRawOut(
            control,
            invalidExc,
            1'b0,
            out_isNaN,
            out_isInf,
            out_isZero,
            out_sign,
            out_sExp,
            out_sig,
            roundingMode,
            out,
            exceptionFlags
        );

endmodule