Fixed get_spi_rxfifo

Fixed get_spi_rxfifo

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import SPI::*;
import I2C::*;
import FIFO::*;
import GetPut::*;

interface ImageonSpi;
    method Bit#(1) reset();
    method Bit#(16) timing();
    method Action status_busy(Bit#(1) busy);
    method Action status_error(Bit#(1) error);
    //method Bit#(1) txfifo_clk();
    method Bit#(1) txfifo_wen();
    method Bit#(32) txfifo_din();
    method Action txfifo_full(Bit#(1) full);
    //method Bit#(1) rxfifo_clk();
    method Bit#(1) rxfifo_ren();
    method Action rxfifo_dout(Bit#(32) dout);
    method Action rxfifo_empty(Bit#(1) empty);
endinterface

interface ImageonSerdes;
    method Bit#(1) reset();
    method Bit#(1) auto_align();
    method Bit#(1) align_start();
    method Bit#(1) fifo_enable();
    method Bit#(10) manual_tap();
    method Bit#(10) training();
    method Action iserdes_clk_ready(Bit#(1) ready);
    method Action iserdes_clk_status(Bit#(16) status);
    method Action iserdes_align_busy(Bit#(1) busy);
    method Action iserdes_aligned(Bit#(1) aligned);
endinterface

interface ImageonDecoder;
    method Bit#(1) reset();
    method Bit#(1) enable();
    method Bit#(32) startoddeven();
    method Bit#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Bit#(10) code_fe();
    method Bit#(10) code_bl();
    method Bit#(10) code_img();
    method Bit#(10) code_tr();
    method Bit#(10) code_crc();
    method Action frame_start(Bit#(1) start);
    method Action cnt_black_lines(Bit#(32) lines);
    method Action cnt_image_lines(Bit#(32) lines);
    method Action cnt_black_pixels(Bit#(32) pixels);
    method Action cnt_image_pixels(Bit#(32) pixels);
    method Action cnt_frames(Bit#(32) frames);
    method Action cnt_windows(Bit#(32) windows);
    method Action cnt_clocks(Bit#(32) clocks);
    method Action cnt_start_lines(Bit#(32) lines);
    method Action cnt_end_lines(Bit#(32) lines);
    method Action cnt_monitor0high(Bit#(32) monitor0high);
    method Action cnt_monitor0low(Bit#(32) monitor0low);
    method Action cnt_monitor1high(Bit#(32) monitor1high);
    method Action cnt_monitor1low(Bit#(32) monitor1low);
endinterface

interface ImageonCrc;
    method Bit#(1) reset();
    method Bit#(1) initvalue();
    method Action crc_status(Bit#(32) status);
endinterface

interface ImageonRemapper;
    method Bit#(3) write_cfg();
    method Bit#(3) mode();
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(3) sync2readout();
    method Bit#(1) readouttrigger();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
    method Bit#(32) cnt_trigger1high();
    method Bit#(32) cnt_trigger1low();
    method Bit#(32) cnt_trigger2high();
    method Bit#(32) cnt_trigger2low();
    method Bit#(32) ext_debounce();
    method Bit#(1) ext_polarity();
    method Bit#(3) gen_polarity();
endinterface

interface ImageonFpnPrnu;
    method Bit#(256) prnu_values();
endinterface

interface ImageonSyncGen;
    method Bit#(16) delay();
    method Bit#(16) hactive();
    method Bit#(16) hfporch();
    method Bit#(16) hsync();
    method Bit#(16) hbporch();
    method Bit#(16) vactive();
    method Bit#(16) vfporch();
    method Bit#(16) vsync();
    method Bit#(16) vbporch();
endinterface

interface ImageonXsvi;
    method Action vsync(Bit#(1) v);
    method Action hsync(Bit#(1) v);
    method Action vblank(Bit#(1) v);
    method Action hblank(Bit#(1) v);
    method Action active_video(Bit#(1) v);
    method Action video_data(Bit#(10) v);
endinterface

interface ImageonDebugSpi;
    method Action debug_spi(Bit#(96) o);
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_vita_reset();
    method Bit#(1) host_oe();
    method Bit#(1) host_iic_reset();
    method Bit#(1) host_clock_gen_reset();
    method Bit#(1) host_clock_gen_select();
    method Action host_clock_gen_locked(Bit#(1) locked);
    method Action fsync(Bit#(1) fsync);
    interface ImageonSpi spi;
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonCrc crc;
    interface ImageonRemapper remapper;
    interface ImageonTrigger trigger;
    interface ImageonFpnPrnu fpnPrnu;
    interface ImageonSyncGen syncgen;
    interface ImageonXsvi xsvi;
    interface ImageonDebugSpi debugSpi;
endinterface

interface ImageonControl;
    method Action set_spi_control(Bit#(32) v);
    method Bit#(32) get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Bit#(32) get_decoder_control();
    method Action set_crc_control(Bit#(32) v);
    method Bit#(32) get_crc_control();
    method Bit#(32) get_crc_status();
    method Action set_remapper_control(Bit#(32) v);
    method Bit#(32) get_remapper_control();
    method Action set_triggen_control(Bit#(32) v);
    method Bit#(32) get_triggen_control();

    method Action set_host_vita_reset(Bit#(1) v);
    method Action set_host_oe(Bit#(1) v);
    method Action set_iic_reset(Bit#(1) v);
    method Action set_clock_gen_reset(Bit#(1) v);
    method Action set_clock_gen_select(Bit#(1) v);
    method Bit#(1) get_clock_gen_locked();

    method Action set_spi_reset(Bit#(1) v);
    method Action set_spi_timing(Bit#(16) v);
    method Bit#(96) get_spi_debug();

    interface Put#(Bit#(32)) txfifo;
    interface Put#(Bit#(32)) rxfifo_request;
    interface Get#(Bit#(32)) rxfifo_response;

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_startoddeven(Bit#(32) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_decoder_code_tr(Bit#(10) v);
    method Action set_decoder_code_crc(Bit#(10) v);
    method Action set_crc_reset(Bit#(1) v);
    method Action set_crc_initvalue(Bit#(1) v);
    method Action set_remapper_write_cfg(Bit#(3) v);
    method Action set_remapper_mode(Bit#(3) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_sync2readout(Bit#(3) v);
    method Action set_trigger_readouttrigger(Bit#(1) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_trigger_cnt_trigger1high(Bit#(32) v);
    method Action set_trigger_cnt_trigger1low(Bit#(32) v);
    method Action set_trigger_cnt_trigger2high(Bit#(32) v);
    method Action set_trigger_cnt_trigger2low(Bit#(32) v);
    method Action set_trigger_ext_debounce(Bit#(32) v);
    method Action set_trigger_ext_polarity(Bit#(1) v);
    method Action set_trigger_gen_polarity(Bit#(3) v);
    method Action set_prnu_values(Bit#(256) v);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);
endinterface

interface ImageonVitaController;
    interface ImageonVita host;
    interface ImageonControl control;
endinterface

module mkImageonVitaController(ImageonVitaController);

    Reg#(Bit#(1)) host_vita_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_oe_reg <- mkReg(0);
    Reg#(Bit#(1)) host_iic_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_clock_gen_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_clock_gen_select_reg <- mkReg(0);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);
    Reg#(Bit#(1)) spi_reset_reg <- mkReg(0);
    Reg#(Bit#(16)) spi_timing_reg <- mkReg(0);

    Wire#(Bit#(1)) spi_status_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_status_error_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_full_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_wen_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_txfifo_din_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_ren_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_rxfifo_dout_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_empty_wire <- mkDWire(0);
    Reg#(Bool) spi_rxfifo_requested_reg <- mkReg(False);

    Reg#(Bit#(1)) serdes_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_training_reg <- mkReg(0);
    Wire#(Bit#(1)) serdes_clk_ready_wire <- mkDWire(0);
    Wire#(Bit#(16)) serdes_clk_status_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_align_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_aligned_wire <- mkDWire(0);

    Reg#(Bit#(1)) decoder_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) decoder_enable_reg <- mkReg(0);
    Reg#(Bit#(32)) decoder_startoddeven_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fe_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_bl_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_img_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_tr_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_crc_reg <- mkReg(0);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_black_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_image_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_black_pixels_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_image_pixels_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_frames_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_windows_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_clocks_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_start_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_end_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor0high_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor0low_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor1high_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor1low_wire <- mkDWire(0);

    Reg#(Bit#(1)) crc_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) crc_initvalue_reg <- mkReg(0);
    Wire#(Bit#(32)) crc_status_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) remapper_write_cfg_reg <- mkReg(0);
    Reg#(Bit#(3)) remapper_mode_reg <- mkReg(0);
    Reg#(Bit#(3)) trigger_enable_reg <- mkReg(0);
    Reg#(Bit#(3)) trigger_sync2readout_reg <- mkReg(0);
    Reg#(Bit#(1)) trigger_readouttrigger_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger1high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger1low_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger2high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger2low_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_ext_debounce_reg <- mkReg(0);
    Reg#(Bit#(1)) trigger_ext_polarity_reg <- mkReg(0);
    Reg#(Bit#(3)) trigger_gen_polarity_reg <- mkReg(0);
    Reg#(Bit#(256)) prnu_values_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkReg(0);
    Reg#(Bit#(32)) vsync_reg <- mkReg(0);
    Reg#(Bit#(32)) hsync_reg <- mkReg(0);
    Reg#(Bit#(32)) vblank_reg <- mkReg(0);
    Reg#(Bit#(32)) hblank_reg <- mkReg(0);
    Reg#(Bit#(32)) active_reg <- mkReg(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_vsync_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_hsync_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_vblank_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_hblank_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_active_video_wire <- mkDWire(0);
    Wire#(Bit#(96)) debug_spi_wire <- mkDWire(0);

    interface ImageonVita host;
	method Bit#(1) host_vita_reset();
	    return host_vita_reset_reg;
	endmethod
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	method Bit#(1) host_iic_reset();
	    return host_iic_reset_reg;
	endmethod
	method Bit#(1) host_clock_gen_reset();
	    return host_clock_gen_reset_reg;
	endmethod
	method Bit#(1) host_clock_gen_select();
	    return host_clock_gen_select_reg;
	endmethod
	method Action host_clock_gen_locked(Bit#(1) locked);
	    host_clock_gen_locked_wire <= locked;
	endmethod
	method Action fsync(Bit#(1) sync);
	endmethod
	interface ImageonSpi spi;
	    method Bit#(1) reset();
		return spi_reset_reg;
	    endmethod
	    method Bit#(16) timing();
		return spi_timing_reg;
	    endmethod
	    method Action status_busy(Bit#(1) busy);
	        spi_status_busy_wire <= busy;
	    endmethod
	    method Action status_error(Bit#(1) error);
	        spi_status_error_wire <= error;
	    endmethod
	    method Bit#(1) txfifo_wen();
		return spi_txfifo_wen_wire;
	    endmethod
	    method Bit#(32) txfifo_din();
		return spi_txfifo_din_wire;
	    endmethod
	    method Action txfifo_full(Bit#(1) full);
	        spi_txfifo_full_wire <= full;
	    endmethod
	    method Bit#(1) rxfifo_ren();
		return spi_rxfifo_ren_wire;
	    endmethod
	    method Action rxfifo_dout(Bit#(32) dout);
	        spi_rxfifo_dout_wire <= dout;
	    endmethod
	    method Action rxfifo_empty(Bit#(1) empty);
	        spi_rxfifo_empty_wire <= empty;
	    endmethod
	endinterface
	interface ImageonSerdes serdes;
	    method Bit#(1) reset();
		return serdes_reset_reg;
	    endmethod
	    method Bit#(1) auto_align();
		return serdes_auto_align_reg;
	    endmethod
	    method Bit#(1) align_start();
		return serdes_align_start_reg;
	    endmethod
	    method Bit#(1) fifo_enable();
		return serdes_fifo_enable_reg;
	    endmethod
	    method Bit#(10) manual_tap();
		return serdes_manual_tap_reg;
	    endmethod
	    method Bit#(10) training();
		return serdes_training_reg;
	    endmethod
	    method Action iserdes_clk_ready(Bit#(1) ready);
	        serdes_clk_ready_wire <= ready;
	    endmethod
	    method Action iserdes_clk_status(Bit#(16) status);
	        serdes_clk_status_wire <= status;
	    endmethod
	    method Action iserdes_align_busy(Bit#(1) busy);
	        serdes_align_busy_wire <= busy;
	    endmethod
	    method Action iserdes_aligned(Bit#(1) aligned);
	        serdes_aligned_wire <= aligned;
	    endmethod
	endinterface
	interface ImageonDecoder decoder;
	    method Bit#(1) reset();
		return decoder_reset_reg;
	    endmethod
	    method Bit#(1) enable();
		return decoder_enable_reg;
	    endmethod
	    method Bit#(32) startoddeven();
		return decoder_startoddeven_reg;
	    endmethod
	    method Bit#(10) code_ls();
		return decoder_code_ls_reg;
	    endmethod
	    method Bit#(10) code_le();
		return decoder_code_le_reg;
	    endmethod
	    method Bit#(10) code_fs();
		return decoder_code_fs_reg;
	    endmethod
	    method Bit#(10) code_fe();
		return decoder_code_fe_reg;
	    endmethod
	    method Bit#(10) code_bl();
		return decoder_code_bl_reg;
	    endmethod
	    method Bit#(10) code_img();
		return decoder_code_img_reg;
	    endmethod
	    method Bit#(10) code_tr();
		return decoder_code_tr_reg;
	    endmethod
	    method Bit#(10) code_crc();
		return decoder_code_crc_reg;
	    endmethod
	    method Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	    method Action cnt_black_lines(Bit#(32) lines);
	        decoder_cnt_black_lines_wire <= lines;
	    endmethod
	    method Action cnt_image_lines(Bit#(32) lines);
	        decoder_cnt_image_lines_wire <= lines;
	    endmethod
	    method Action cnt_black_pixels(Bit#(32) pixels);
	        decoder_cnt_black_pixels_wire <= pixels;
	    endmethod
	    method Action cnt_image_pixels(Bit#(32) pixels);
	        decoder_cnt_image_pixels_wire <= pixels;
	    endmethod
	    method Action cnt_frames(Bit#(32) frames);
	        decoder_cnt_frames_wire <= frames;
	    endmethod
	    method Action cnt_windows(Bit#(32) windows);
	        decoder_cnt_windows_wire <= windows;
	    endmethod
	    method Action cnt_clocks(Bit#(32) clocks);
	        decoder_cnt_clocks_wire <= clocks;
	    endmethod
	    method Action cnt_start_lines(Bit#(32) lines);
	        decoder_cnt_start_lines_wire <= lines;
	    endmethod
	    method Action cnt_end_lines(Bit#(32) lines);
	        decoder_cnt_end_lines_wire <= lines;
	    endmethod
	    method Action cnt_monitor0high(Bit#(32) monitor0high);
	        decoder_cnt_monitor0high_wire <= monitor0high;
	    endmethod
	    method Action cnt_monitor0low(Bit#(32) monitor0low);
	        decoder_cnt_monitor0low_wire <= monitor0low;
	    endmethod
	    method Action cnt_monitor1high(Bit#(32) monitor1high);
	        decoder_cnt_monitor1high_wire <= monitor1high;
	    endmethod
	    method Action cnt_monitor1low(Bit#(32) monitor1low);
	        decoder_cnt_monitor1low_wire <= monitor1low;
	    endmethod
	endinterface
	interface ImageonCrc crc;
	    method Bit#(1) reset();
		return crc_reset_reg;
	    endmethod
	    method Bit#(1) initvalue();
		return crc_initvalue_reg;
	    endmethod
	    method Action crc_status(Bit#(32) status);
	        crc_status_wire <= status;
	    endmethod
	endinterface
	interface ImageonRemapper remapper;
	    method Bit#(3) write_cfg();
		return remapper_write_cfg_reg;
	    endmethod
	    method Bit#(3) mode();
		return remapper_mode_reg;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_reg;
	    endmethod
	    method Bit#(3) sync2readout();
		return trigger_sync2readout_reg;
	    endmethod
	    method Bit#(1) readouttrigger();
		return trigger_readouttrigger_reg;
	    endmethod
	    method Bit#(32) default_freq();
		return trigger_default_freq_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0high();
		return trigger_cnt_trigger0high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0low();
		return trigger_cnt_trigger0low_reg;
	    endmethod
	    method Bit#(32) cnt_trigger1high();
		return trigger_cnt_trigger1high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger1low();
		return trigger_cnt_trigger1low_reg;
	    endmethod
	    method Bit#(32) cnt_trigger2high();
		return trigger_cnt_trigger2high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger2low();
		return trigger_cnt_trigger2low_reg;
	    endmethod
	    method Bit#(32) ext_debounce();
		return trigger_ext_debounce_reg;
	    endmethod
	    method Bit#(1) ext_polarity();
		return trigger_ext_polarity_reg;
	    endmethod
	    method Bit#(3) gen_polarity();
		return trigger_gen_polarity_reg;
	    endmethod
	endinterface
	interface ImageonFpnPrnu fpnPrnu;
	    method Bit#(256) prnu_values();
		return prnu_values_reg;
	    endmethod
	endinterface
	interface ImageonSyncGen syncgen;
	    method Bit#(16) delay();
		return syncgen_delay_reg;
	    endmethod
	    method Bit#(16) hactive();
		return syncgen_hactive_reg;
	    endmethod
	    method Bit#(16) hfporch();
		return syncgen_hfporch_reg;
	    endmethod
	    method Bit#(16) hsync();
		return syncgen_hsync_reg;
	    endmethod
	    method Bit#(16) hbporch();
		return syncgen_hbporch_reg;
	    endmethod
	    method Bit#(16) vactive();
		return syncgen_vactive_reg;
	    endmethod
	    method Bit#(16) vfporch();
		return syncgen_vfporch_reg;
	    endmethod
	    method Bit#(16) vsync();
		return syncgen_vsync_reg;
	    endmethod
	    method Bit#(16) vbporch();
		return syncgen_vbporch_reg;
	    endmethod
	endinterface
	interface ImageonXsvi xsvi;
	    method Action vsync(Bit#(1) v);
	        xsvi_vsync_wire <= v;
	        if (v == 1)
	            vsync_reg <= vsync_reg + 1;
	    endmethod
	    method Action hsync(Bit#(1) v);
	        xsvi_hsync_wire <= v;
	        if (v == 1)
	            hsync_reg <= hsync_reg + 1;
	    endmethod
	    method Action vblank(Bit#(1) v);
	        xsvi_vblank_wire <= v;
	        if (v == 1)
	            vblank_reg <= vblank_reg + 1;
	    endmethod
	    method Action hblank(Bit#(1) v);
	        xsvi_hblank_wire <= v;
	        if (v == 1)
	            hblank_reg <= hblank_reg + 1;
	    endmethod
	    method Action active_video(Bit#(1) v);
	        xsvi_active_video_wire <= v;
	        if (v == 1)
	            active_reg <= active_reg + 1;
	    endmethod
	    method Action video_data(Bit#(10) v);
	        xsvi_video_data_wire <= v;
	    endmethod
	endinterface
	interface ImageonDebugSpi debugSpi;
	    method Action debug_spi(Bit#(96) o);
	        debug_spi_wire <= o;
	    endmethod
	endinterface
    endinterface
    interface ImageonControl control;
// SPI_CONTROL
//    [ 0] VITA_RESET
//    [ 1] SPI_RESET
//    [ 8] SPI_STATUS_BUSY
//    [ 9] SPI_STATUS_ERROR
//    [16] SPI_TXFIFO_FULL
//    [24] SPI_RXFIFO_EMPTY
	method Action set_spi_control(Bit#(32) v);
            host_vita_reset_reg <= v[0];
            spi_reset_reg <= v[1];
	endmethod
	method Bit#(32) get_spi_control();
	    let v = 0;
            v[0] = host_vita_reset_reg;
	    v[1] = spi_reset_reg;
	    v[8] = spi_status_busy_wire;
	    v[9] = spi_status_error_wire;
	    v[16] = spi_txfifo_full_wire;
	    v[24] = spi_rxfifo_empty_wire;
	    return v;
	endmethod

// ISERDES_CONTROL
//    [ 0] ISERDES_RESET
//    [ 1] ISERDES_AUTO_ALIGN
//    [ 2] ISERDES_ALIGN_START
//    [ 3] ISERDES_FIFO_ENABLE
//    [ 8] ISERDES_CLK_READY
//    [ 9] ISERDES_ALIGN_BUSY
//    [10] ISERDES_ALIGNED
// [23:16] ISERDES_TXCLK_STATUS
// [31:24] ISERDES_RXCLK_STATUS
	method Action set_iserdes_control(Bit#(32) v);
	    serdes_reset_reg <= v[0];
	    serdes_auto_align_reg <= v[1];
	    serdes_align_start_reg <= v[2];
	    serdes_fifo_enable_reg <= v[3];
	endmethod
	method Bit#(32) get_iserdes_control();
	    let v = 0;
	    v[0] = serdes_reset_reg;
	    v[1] = serdes_auto_align_reg;
	    v[2] = serdes_align_start_reg;
	    v[3] = serdes_fifo_enable_reg;
	    v[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    v[31:16] = serdes_clk_status_wire;
	    return v;
	endmethod
// DECODER_CONTROL[7:0]
//    [0] DECODER_RESET
//    [1] DECODER_ENABLE
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	endmethod
	method Bit#(32) get_decoder_control();
	    let v = 0;
	    v[0] = decoder_reset_reg;
	    v[1] = decoder_enable_reg;
	    return v;
	endmethod
// CRC_CONTROL[7:0]
//    [0] CRC_RESET
//    [1] CRC_INITVALUE
	method Action set_crc_control(Bit#(32) v);
	    crc_reset_reg <= v[0];
	    crc_initvalue_reg <= v[1];
	endmethod
	method Bit#(32) get_crc_control();
	    let v = 0;
	    v[0] = crc_reset_reg;
	    v[1] = crc_initvalue_reg;
	    return v;
	endmethod
	method Bit#(32) get_crc_status();
	    return crc_status_wire;
	endmethod
// REMAPPER_CONTROL[7:0]
//    [2:0] REMAPPER_WRITE_CFG
//    [6:4] REMAPPER_MODE
	method Action set_remapper_control(Bit#(32) v);
	    remapper_write_cfg_reg <= v[2:0];
	    remapper_mode_reg <= v[6:4];
	endmethod
	method Bit#(32) get_remapper_control();
	    let v = 0;
	    v[2:0] = remapper_write_cfg_reg;
	    v[6:4] = remapper_mode_reg;
	    return v;
	endmethod
// TRIGGEN_CONTROL
// [ 2: 0] TRIGGEN_ENABLE
// [ 6: 4] TRIGGEN_SYNC2READOUT
// [    8] TRIGGEN_READOUTTRIGGER
// [   16] TRIGGEN_EXT_POLARITY
// [   24] TRIGGEN_CNT_UPDATE
// [30:28] TRIGGEN_GEN_POLARITY
	method Action set_triggen_control(Bit#(32) v);
	    trigger_enable_reg <= v[2:0];
	    trigger_sync2readout_reg <= v[6:4];
	    trigger_readouttrigger_reg <= v[8];
	    trigger_ext_polarity_reg <= v[16];
	    //FIXME
	    //trigger_cnt_update_reg <= v[24];
	    trigger_gen_polarity_reg <= v[30:28];
	endmethod
	method Bit#(32) get_triggen_control();
	    let v = 0;
	    v[2:0] = trigger_enable_reg;
	    v[6:4] = trigger_sync2readout_reg;
	    v[8] = trigger_readouttrigger_reg;
	    v[16] = trigger_ext_polarity_reg;
	    //FIXME
	    //v[24] = trigger_cnt_update_reg;
	    v[30:28] = trigger_gen_polarity_reg;
	    return v;
	endmethod

	method Action set_host_vita_reset(Bit#(1) v);
	    host_vita_reset_reg <= v;
	endmethod
	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	endmethod
	method Action set_iic_reset(Bit#(1) v);
	    host_iic_reset_reg <= v[0];
	endmethod
	method Action set_clock_gen_reset(Bit#(1) v);
	    host_clock_gen_reset_reg <= v[0];
	endmethod
	method Action set_clock_gen_select(Bit#(1) v);
	    host_clock_gen_select_reg <= v[0];
	endmethod
	method Bit#(1) get_clock_gen_locked();
	    return host_clock_gen_locked_wire;
	endmethod

	method Action set_spi_reset(Bit#(1) v);
	    spi_reset_reg <= v;
	endmethod
	method Action set_spi_timing(Bit#(16) v);
	    spi_timing_reg <= v;
	endmethod
	interface Put txfifo;
	    method Action put(Bit#(32) v) if (spi_txfifo_full_wire == 0);
	        spi_txfifo_wen_wire <= 1;
		spi_txfifo_din_wire <= v;
	    endmethod
	endinterface
        interface Put rxfifo_request;
	    method Action put(Bit#(32) v) if (!spi_rxfifo_requested_reg && (spi_rxfifo_empty_wire == 0));
	        spi_rxfifo_requested_reg <= True;
		spi_rxfifo_ren_wire <= 1;
	    endmethod
	endinterface
	interface Get rxfifo_response;
	    method ActionValue#(Bit#(32)) get() if (spi_rxfifo_requested_reg);
	        spi_rxfifo_requested_reg <= False;
		return spi_rxfifo_dout_wire;
	    endmethod
	endinterface
	method Bit#(96) get_spi_debug();
	    return debug_spi_wire;
	endmethod
	method Action set_serdes_reset(Bit#(1) v);
	    serdes_reset_reg <= v;
	endmethod
	method Action set_serdes_auto_align(Bit#(1) v);
	    serdes_auto_align_reg <= v;
	endmethod
	method Action set_serdes_align_start(Bit#(1) v);
	    serdes_align_start_reg <= v;
	endmethod
	method Action set_serdes_fifo_enable(Bit#(1) v);
	    serdes_fifo_enable_reg <= v;
	endmethod
	method Action set_serdes_manual_tap(Bit#(10) v);
	    serdes_manual_tap_reg <= v;
	endmethod
	method Action set_serdes_training(Bit#(10) v);
	    serdes_training_reg <= v;
	endmethod
	method Action set_decoder_reset(Bit#(1) v);
	    decoder_reset_reg <= v;
	endmethod
	method Action set_decoder_enable(Bit#(1) v);
	    decoder_enable_reg <= v;
	endmethod
	method Action set_decoder_startoddeven(Bit#(32) v);
	    decoder_startoddeven_reg <= v;
	endmethod
	method Action set_decoder_code_ls(Bit#(10) v);
	    decoder_code_ls_reg <= v;
	endmethod
	method Action set_decoder_code_le(Bit#(10) v);
	    decoder_code_le_reg <= v;
	endmethod
	method Action set_decoder_code_fs(Bit#(10) v);
	    decoder_code_fs_reg <= v;
	endmethod
	method Action set_decoder_code_fe(Bit#(10) v);
	    decoder_code_fe_reg <= v;
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	    decoder_code_bl_reg <= v;
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	    decoder_code_img_reg <= v;
	endmethod
	method Action set_decoder_code_tr(Bit#(10) v);
	    decoder_code_tr_reg <= v;
	endmethod
	method Action set_decoder_code_crc(Bit#(10) v);
	    decoder_code_crc_reg <= v;
	endmethod
	method Action set_crc_reset(Bit#(1) v);
	    crc_reset_reg <= v;
	endmethod
	method Action set_crc_initvalue(Bit#(1) v);
	    crc_initvalue_reg <= v;
	endmethod
	method Action set_remapper_write_cfg(Bit#(3) v);
	    remapper_write_cfg_reg <= v;
	endmethod
	method Action set_remapper_mode(Bit#(3) v);
	    remapper_mode_reg <= v;
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_reg <= v;
	endmethod
	method Action set_trigger_sync2readout(Bit#(3) v);
	    trigger_sync2readout_reg <= v;
	endmethod
	method Action set_trigger_readouttrigger(Bit#(1) v);
	    trigger_readouttrigger_reg <= v;
	endmethod
	method Action set_trigger_default_freq(Bit#(32) v);
	    trigger_default_freq_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0high(Bit#(32) v);
	    trigger_cnt_trigger0high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0low(Bit#(32) v);
	    trigger_cnt_trigger0low_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger1high(Bit#(32) v);
	    trigger_cnt_trigger1high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger1low(Bit#(32) v);
	    trigger_cnt_trigger1low_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger2high(Bit#(32) v);
	    trigger_cnt_trigger2high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger2low(Bit#(32) v);
	    trigger_cnt_trigger2low_reg <= v;
	endmethod
	method Action set_trigger_ext_debounce(Bit#(32) v);
	    trigger_ext_debounce_reg <= v;
	endmethod
	method Action set_trigger_ext_polarity(Bit#(1) v);
	    trigger_ext_polarity_reg <= v;
	endmethod
	method Action set_trigger_gen_polarity(Bit#(3) v);
	    trigger_gen_polarity_reg <= v;
	endmethod
	method Action set_prnu_values(Bit#(256) v);
	    prnu_values_reg <= v;
	endmethod
	method Action set_syncgen_delay(Bit#(16) v);
	    syncgen_delay_reg <= v;
	endmethod
	method Action set_syncgen_hactive(Bit#(16) v);
	    syncgen_hactive_reg <= v;
	endmethod
	method Action set_syncgen_hfporch(Bit#(16) v);
	    syncgen_hfporch_reg <= v;
	endmethod
	method Action set_syncgen_hsync(Bit#(16) v);
	    syncgen_hsync_reg <= v;
	endmethod
	method Action set_syncgen_hbporch(Bit#(16) v);
	    syncgen_hbporch_reg <= v;
	endmethod
	method Action set_syncgen_vactive(Bit#(16) v);
	    syncgen_vactive_reg <= v;
	endmethod
	method Action set_syncgen_vfporch(Bit#(16) v);
	    syncgen_vfporch_reg <= v;
	endmethod
	method Action set_syncgen_vsync(Bit#(16) v);
	    syncgen_vsync_reg <= v;
	endmethod
	method Action set_syncgen_vbporch(Bit#(16) v);
	    syncgen_vbporch_reg <= v;
	endmethod
    endinterface
endmodule

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import SPI::*;
import I2C::*;
import FIFO::*;
import GetPut::*;

interface ImageonSpi;
    method Bit#(1) reset();
    method Bit#(16) timing();
    method Action status_busy(Bit#(1) busy);
    method Action status_error(Bit#(1) error);
    //method Bit#(1) txfifo_clk();
    method Bit#(1) txfifo_wen();
    method Bit#(32) txfifo_din();
    method Action txfifo_full(Bit#(1) full);
    //method Bit#(1) rxfifo_clk();
    method Bit#(1) rxfifo_ren();
    method Action rxfifo_dout(Bit#(32) dout);
    method Action rxfifo_empty(Bit#(1) empty);
endinterface

interface ImageonSerdes;
    method Bit#(1) reset();
    method Bit#(1) auto_align();
    method Bit#(1) align_start();
    method Bit#(1) fifo_enable();
    method Bit#(10) manual_tap();
    method Bit#(10) training();
    method Action iserdes_clk_ready(Bit#(1) ready);
    method Action iserdes_clk_status(Bit#(16) status);
    method Action iserdes_align_busy(Bit#(1) busy);
    method Action iserdes_aligned(Bit#(1) aligned);
endinterface

interface ImageonDecoder;
    method Bit#(1) reset();
    method Bit#(1) enable();
    method Bit#(32) startoddeven();
    method Bit#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Bit#(10) code_fe();
    method Bit#(10) code_bl();
    method Bit#(10) code_img();
    method Bit#(10) code_tr();
    method Bit#(10) code_crc();
    method Action frame_start(Bit#(1) start);
    method Action cnt_black_lines(Bit#(32) lines);
    method Action cnt_image_lines(Bit#(32) lines);
    method Action cnt_black_pixels(Bit#(32) pixels);
    method Action cnt_image_pixels(Bit#(32) pixels);
    method Action cnt_frames(Bit#(32) frames);
    method Action cnt_windows(Bit#(32) windows);
    method Action cnt_clocks(Bit#(32) clocks);
    method Action cnt_start_lines(Bit#(32) lines);
    method Action cnt_end_lines(Bit#(32) lines);
    method Action cnt_monitor0high(Bit#(32) monitor0high);
    method Action cnt_monitor0low(Bit#(32) monitor0low);
    method Action cnt_monitor1high(Bit#(32) monitor1high);
    method Action cnt_monitor1low(Bit#(32) monitor1low);
endinterface

interface ImageonCrc;
    method Bit#(1) reset();
    method Bit#(1) initvalue();
    method Action crc_status(Bit#(32) status);
endinterface

interface ImageonRemapper;
    method Bit#(3) write_cfg();
    method Bit#(3) mode();
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(3) sync2readout();
    method Bit#(1) readouttrigger();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
    method Bit#(32) cnt_trigger1high();
    method Bit#(32) cnt_trigger1low();
    method Bit#(32) cnt_trigger2high();
    method Bit#(32) cnt_trigger2low();
    method Bit#(32) ext_debounce();
    method Bit#(1) ext_polarity();
    method Bit#(3) gen_polarity();
endinterface

interface ImageonFpnPrnu;
    method Bit#(256) prnu_values();
endinterface

interface ImageonSyncGen;
    method Bit#(16) delay();
    method Bit#(16) hactive();
    method Bit#(16) hfporch();
    method Bit#(16) hsync();
    method Bit#(16) hbporch();
    method Bit#(16) vactive();
    method Bit#(16) vfporch();
    method Bit#(16) vsync();
    method Bit#(16) vbporch();
endinterface

interface ImageonXsvi;
    method Action vsync(Bit#(1) v);
    method Action hsync(Bit#(1) v);
    method Action vblank(Bit#(1) v);
    method Action hblank(Bit#(1) v);
    method Action active_video(Bit#(1) v);
    method Action video_data(Bit#(10) v);
endinterface

interface ImageonDebugSpi;
    method Action debug_spi(Bit#(96) o);
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_vita_reset();
    method Bit#(1) host_oe();
    method Bit#(1) host_iic_reset();
    method Bit#(1) host_clock_gen_reset();
    method Bit#(1) host_clock_gen_select();
    method Action host_clock_gen_locked(Bit#(1) locked);
    method Action fsync(Bit#(1) fsync);
    interface ImageonSpi spi;
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonCrc crc;
    interface ImageonRemapper remapper;
    interface ImageonTrigger trigger;
    interface ImageonFpnPrnu fpnPrnu;
    interface ImageonSyncGen syncgen;
    interface ImageonXsvi xsvi;
    interface ImageonDebugSpi debugSpi;
endinterface

interface ImageonControl;
    method Action set_spi_control(Bit#(32) v);
    method Bit#(32) get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Bit#(32) get_decoder_control();
    method Action set_crc_control(Bit#(32) v);
    method Bit#(32) get_crc_control();
    method Bit#(32) get_crc_status();
    method Action set_remapper_control(Bit#(32) v);
    method Bit#(32) get_remapper_control();
    method Action set_triggen_control(Bit#(32) v);
    method Bit#(32) get_triggen_control();

    method Action set_host_vita_reset(Bit#(1) v);
    method Action set_host_oe(Bit#(1) v);
    method Action set_iic_reset(Bit#(1) v);
    method Action set_clock_gen_reset(Bit#(1) v);
    method Action set_clock_gen_select(Bit#(1) v);
    method Bit#(1) get_clock_gen_locked();

    method Action set_spi_reset(Bit#(1) v);
    method Action set_spi_timing(Bit#(16) v);

    interface Put#(Bit#(32)) txfifo;
    interface Get#(Bit#(32)) rxfifo;

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_startoddeven(Bit#(32) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_decoder_code_tr(Bit#(10) v);
    method Action set_decoder_code_crc(Bit#(10) v);
    method Action set_crc_reset(Bit#(1) v);
    method Action set_crc_initvalue(Bit#(1) v);
    method Action set_remapper_write_cfg(Bit#(3) v);
    method Action set_remapper_mode(Bit#(3) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_sync2readout(Bit#(3) v);
    method Action set_trigger_readouttrigger(Bit#(1) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_trigger_cnt_trigger1high(Bit#(32) v);
    method Action set_trigger_cnt_trigger1low(Bit#(32) v);
    method Action set_trigger_cnt_trigger2high(Bit#(32) v);
    method Action set_trigger_cnt_trigger2low(Bit#(32) v);
    method Action set_trigger_ext_debounce(Bit#(32) v);
    method Action set_trigger_ext_polarity(Bit#(1) v);
    method Action set_trigger_gen_polarity(Bit#(3) v);
    method Action set_prnu_values(Bit#(256) v);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);
endinterface

interface ImageonVitaController;
    interface ImageonVita host;
    interface ImageonControl control;
endinterface

module mkImageonVitaController(ImageonVitaController);

    Reg#(Bit#(1)) host_vita_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_oe_reg <- mkReg(0);
    Reg#(Bit#(1)) host_iic_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_clock_gen_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_clock_gen_select_reg <- mkReg(0);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);
    Reg#(Bit#(1)) spi_reset_reg <- mkReg(0);
    Reg#(Bit#(16)) spi_timing_reg <- mkReg(0);

    Wire#(Bit#(1)) spi_status_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_status_error_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_full_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_wen_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_txfifo_din_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_ren_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_rxfifo_dout_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_empty_wire <- mkDWire(0);

    Reg#(Bit#(1)) serdes_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_training_reg <- mkReg(0);
    Wire#(Bit#(1)) serdes_clk_ready_wire <- mkDWire(0);
    Wire#(Bit#(16)) serdes_clk_status_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_align_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_aligned_wire <- mkDWire(0);

    Reg#(Bit#(1)) decoder_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) decoder_enable_reg <- mkReg(0);
    Reg#(Bit#(32)) decoder_startoddeven_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fe_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_bl_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_img_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_tr_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_crc_reg <- mkReg(0);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_black_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_image_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_black_pixels_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_image_pixels_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_frames_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_windows_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_clocks_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_start_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_end_lines_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor0high_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor0low_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor1high_wire <- mkDWire(0);
    Wire#(Bit#(32)) decoder_cnt_monitor1low_wire <- mkDWire(0);

    Reg#(Bit#(1)) crc_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) crc_initvalue_reg <- mkReg(0);
    Wire#(Bit#(32)) crc_status_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) remapper_write_cfg_reg <- mkReg(0);
    Reg#(Bit#(3)) remapper_mode_reg <- mkReg(0);
    Reg#(Bit#(3)) trigger_enable_reg <- mkReg(0);
    Reg#(Bit#(3)) trigger_sync2readout_reg <- mkReg(0);
    Reg#(Bit#(1)) trigger_readouttrigger_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger1high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger1low_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger2high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger2low_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_ext_debounce_reg <- mkReg(0);
    Reg#(Bit#(1)) trigger_ext_polarity_reg <- mkReg(0);
    Reg#(Bit#(3)) trigger_gen_polarity_reg <- mkReg(0);
    Reg#(Bit#(256)) prnu_values_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkReg(0);
    Reg#(Bit#(32)) vsync_reg <- mkReg(0);
    Reg#(Bit#(32)) hsync_reg <- mkReg(0);
    Reg#(Bit#(32)) vblank_reg <- mkReg(0);
    Reg#(Bit#(32)) hblank_reg <- mkReg(0);
    Reg#(Bit#(32)) active_reg <- mkReg(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_vsync_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_hsync_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_vblank_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_hblank_wire <- mkDWire(0);
    Wire#(Bit#(1)) xsvi_active_video_wire <- mkDWire(0);
    Wire#(Bit#(96)) debug_spi_wire <- mkDWire(0);

    interface ImageonVita host;
	method Bit#(1) host_vita_reset();
	    return host_vita_reset_reg;
	endmethod
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	method Bit#(1) host_iic_reset();
	    return host_iic_reset_reg;
	endmethod
	method Bit#(1) host_clock_gen_reset();
	    return host_clock_gen_reset_reg;
	endmethod
	method Bit#(1) host_clock_gen_select();
	    return host_clock_gen_select_reg;
	endmethod
	method Action host_clock_gen_locked(Bit#(1) locked);
	    host_clock_gen_locked_wire <= locked;
	endmethod
	method Action fsync(Bit#(1) sync);
	endmethod
	interface ImageonSpi spi;
	    method Bit#(1) reset();
		return spi_reset_reg;
	    endmethod
	    method Bit#(16) timing();
		return spi_timing_reg;
	    endmethod
	    method Action status_busy(Bit#(1) busy);
	        spi_status_busy_wire <= busy;
	    endmethod
	    method Action status_error(Bit#(1) error);
	        spi_status_error_wire <= error;
	    endmethod
	    method Bit#(1) txfifo_wen();
		return spi_txfifo_wen_wire;
	    endmethod
	    method Bit#(32) txfifo_din();
		return spi_txfifo_din_wire;
	    endmethod
	    method Action txfifo_full(Bit#(1) full);
	        spi_txfifo_full_wire <= full;
	    endmethod
	    method Bit#(1) rxfifo_ren();
		return spi_rxfifo_ren_wire;
	    endmethod
	    method Action rxfifo_dout(Bit#(32) dout);
	        spi_rxfifo_dout_wire <= dout;
	    endmethod
	    method Action rxfifo_empty(Bit#(1) empty);
	        spi_rxfifo_empty_wire <= empty;
	    endmethod
	endinterface
	interface ImageonSerdes serdes;
	    method Bit#(1) reset();
		return serdes_reset_reg;
	    endmethod
	    method Bit#(1) auto_align();
		return serdes_auto_align_reg;
	    endmethod
	    method Bit#(1) align_start();
		return serdes_align_start_reg;
	    endmethod
	    method Bit#(1) fifo_enable();
		return serdes_fifo_enable_reg;
	    endmethod
	    method Bit#(10) manual_tap();
		return serdes_manual_tap_reg;
	    endmethod
	    method Bit#(10) training();
		return serdes_training_reg;
	    endmethod
	    method Action iserdes_clk_ready(Bit#(1) ready);
	        serdes_clk_ready_wire <= ready;
	    endmethod
	    method Action iserdes_clk_status(Bit#(16) status);
	        serdes_clk_status_wire <= status;
	    endmethod
	    method Action iserdes_align_busy(Bit#(1) busy);
	        serdes_align_busy_wire <= busy;
	    endmethod
	    method Action iserdes_aligned(Bit#(1) aligned);
	        serdes_aligned_wire <= aligned;
	    endmethod
	endinterface
	interface ImageonDecoder decoder;
	    method Bit#(1) reset();
		return decoder_reset_reg;
	    endmethod
	    method Bit#(1) enable();
		return decoder_enable_reg;
	    endmethod
	    method Bit#(32) startoddeven();
		return decoder_startoddeven_reg;
	    endmethod
	    method Bit#(10) code_ls();
		return decoder_code_ls_reg;
	    endmethod
	    method Bit#(10) code_le();
		return decoder_code_le_reg;
	    endmethod
	    method Bit#(10) code_fs();
		return decoder_code_fs_reg;
	    endmethod
	    method Bit#(10) code_fe();
		return decoder_code_fe_reg;
	    endmethod
	    method Bit#(10) code_bl();
		return decoder_code_bl_reg;
	    endmethod
	    method Bit#(10) code_img();
		return decoder_code_img_reg;
	    endmethod
	    method Bit#(10) code_tr();
		return decoder_code_tr_reg;
	    endmethod
	    method Bit#(10) code_crc();
		return decoder_code_crc_reg;
	    endmethod
	    method Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	    method Action cnt_black_lines(Bit#(32) lines);
	        decoder_cnt_black_lines_wire <= lines;
	    endmethod
	    method Action cnt_image_lines(Bit#(32) lines);
	        decoder_cnt_image_lines_wire <= lines;
	    endmethod
	    method Action cnt_black_pixels(Bit#(32) pixels);
	        decoder_cnt_black_pixels_wire <= pixels;
	    endmethod
	    method Action cnt_image_pixels(Bit#(32) pixels);
	        decoder_cnt_image_pixels_wire <= pixels;
	    endmethod
	    method Action cnt_frames(Bit#(32) frames);
	        decoder_cnt_frames_wire <= frames;
	    endmethod
	    method Action cnt_windows(Bit#(32) windows);
	        decoder_cnt_windows_wire <= windows;
	    endmethod
	    method Action cnt_clocks(Bit#(32) clocks);
	        decoder_cnt_clocks_wire <= clocks;
	    endmethod
	    method Action cnt_start_lines(Bit#(32) lines);
	        decoder_cnt_start_lines_wire <= lines;
	    endmethod
	    method Action cnt_end_lines(Bit#(32) lines);
	        decoder_cnt_end_lines_wire <= lines;
	    endmethod
	    method Action cnt_monitor0high(Bit#(32) monitor0high);
	        decoder_cnt_monitor0high_wire <= monitor0high;
	    endmethod
	    method Action cnt_monitor0low(Bit#(32) monitor0low);
	        decoder_cnt_monitor0low_wire <= monitor0low;
	    endmethod
	    method Action cnt_monitor1high(Bit#(32) monitor1high);
	        decoder_cnt_monitor1high_wire <= monitor1high;
	    endmethod
	    method Action cnt_monitor1low(Bit#(32) monitor1low);
	        decoder_cnt_monitor1low_wire <= monitor1low;
	    endmethod
	endinterface
	interface ImageonCrc crc;
	    method Bit#(1) reset();
		return crc_reset_reg;
	    endmethod
	    method Bit#(1) initvalue();
		return crc_initvalue_reg;
	    endmethod
	    method Action crc_status(Bit#(32) status);
	        crc_status_wire <= status;
	    endmethod
	endinterface
	interface ImageonRemapper remapper;
	    method Bit#(3) write_cfg();
		return remapper_write_cfg_reg;
	    endmethod
	    method Bit#(3) mode();
		return remapper_mode_reg;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_reg;
	    endmethod
	    method Bit#(3) sync2readout();
		return trigger_sync2readout_reg;
	    endmethod
	    method Bit#(1) readouttrigger();
		return trigger_readouttrigger_reg;
	    endmethod
	    method Bit#(32) default_freq();
		return trigger_default_freq_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0high();
		return trigger_cnt_trigger0high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0low();
		return trigger_cnt_trigger0low_reg;
	    endmethod
	    method Bit#(32) cnt_trigger1high();
		return trigger_cnt_trigger1high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger1low();
		return trigger_cnt_trigger1low_reg;
	    endmethod
	    method Bit#(32) cnt_trigger2high();
		return trigger_cnt_trigger2high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger2low();
		return trigger_cnt_trigger2low_reg;
	    endmethod
	    method Bit#(32) ext_debounce();
		return trigger_ext_debounce_reg;
	    endmethod
	    method Bit#(1) ext_polarity();
		return trigger_ext_polarity_reg;
	    endmethod
	    method Bit#(3) gen_polarity();
		return trigger_gen_polarity_reg;
	    endmethod
	endinterface
	interface ImageonFpnPrnu fpnPrnu;
	    method Bit#(256) prnu_values();
		return prnu_values_reg;
	    endmethod
	endinterface
	interface ImageonSyncGen syncgen;
	    method Bit#(16) delay();
		return syncgen_delay_reg;
	    endmethod
	    method Bit#(16) hactive();
		return syncgen_hactive_reg;
	    endmethod
	    method Bit#(16) hfporch();
		return syncgen_hfporch_reg;
	    endmethod
	    method Bit#(16) hsync();
		return syncgen_hsync_reg;
	    endmethod
	    method Bit#(16) hbporch();
		return syncgen_hbporch_reg;
	    endmethod
	    method Bit#(16) vactive();
		return syncgen_vactive_reg;
	    endmethod
	    method Bit#(16) vfporch();
		return syncgen_vfporch_reg;
	    endmethod
	    method Bit#(16) vsync();
		return syncgen_vsync_reg;
	    endmethod
	    method Bit#(16) vbporch();
		return syncgen_vbporch_reg;
	    endmethod
	endinterface
	interface ImageonXsvi xsvi;
	    method Action vsync(Bit#(1) v);
	        xsvi_vsync_wire <= v;
	        if (v == 1)
	            vsync_reg <= vsync_reg + 1;
	    endmethod
	    method Action hsync(Bit#(1) v);
	        xsvi_hsync_wire <= v;
	        if (v == 1)
	            hsync_reg <= hsync_reg + 1;
	    endmethod
	    method Action vblank(Bit#(1) v);
	        xsvi_vblank_wire <= v;
	        if (v == 1)
	            vblank_reg <= vblank_reg + 1;
	    endmethod
	    method Action hblank(Bit#(1) v);
	        xsvi_hblank_wire <= v;
	        if (v == 1)
	            hblank_reg <= hblank_reg + 1;
	    endmethod
	    method Action active_video(Bit#(1) v);
	        xsvi_active_video_wire <= v;
	        if (v == 1)
	            active_reg <= active_reg + 1;
	    endmethod
	    method Action video_data(Bit#(10) v);
	        xsvi_video_data_wire <= v;
	    endmethod
	endinterface
	interface ImageonDebugSpi debugSpi;
	    method Action debug_spi(Bit#(96) o);
	        debug_spi_wire <= o;
	    endmethod
	endinterface
    endinterface
    interface ImageonControl control;
// SPI_CONTROL
//    [ 0] VITA_RESET
//    [ 1] SPI_RESET
//    [ 8] SPI_STATUS_BUSY
//    [ 9] SPI_STATUS_ERROR
//    [16] SPI_TXFIFO_FULL
//    [24] SPI_RXFIFO_EMPTY
	method Action set_spi_control(Bit#(32) v);
            host_vita_reset_reg <= v[0];
            spi_reset_reg <= v[1];
	endmethod
	method Bit#(32) get_spi_control();
	    let v = 0;
            v[0] = host_vita_reset_reg;
	    v[1] = spi_reset_reg;
	    v[8] = spi_status_busy_wire;
	    v[9] = spi_status_error_wire;
	    v[16] = spi_txfifo_full_wire;
	    v[24] = spi_rxfifo_empty_wire;
	    return v;
	endmethod

// ISERDES_CONTROL
//    [ 0] ISERDES_RESET
//    [ 1] ISERDES_AUTO_ALIGN
//    [ 2] ISERDES_ALIGN_START
//    [ 3] ISERDES_FIFO_ENABLE
//    [ 8] ISERDES_CLK_READY
//    [ 9] ISERDES_ALIGN_BUSY
//    [10] ISERDES_ALIGNED
// [23:16] ISERDES_TXCLK_STATUS
// [31:24] ISERDES_RXCLK_STATUS
	method Action set_iserdes_control(Bit#(32) v);
	    serdes_reset_reg <= v[0];
	    serdes_auto_align_reg <= v[1];
	    serdes_align_start_reg <= v[2];
	    serdes_fifo_enable_reg <= v[3];
	endmethod
	method Bit#(32) get_iserdes_control();
	    let v = 0;
	    v[0] = serdes_reset_reg;
	    v[1] = serdes_auto_align_reg;
	    v[2] = serdes_align_start_reg;
	    v[3] = serdes_fifo_enable_reg;
	    v[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    v[31:16] = serdes_clk_status_wire;
	    return v;
	endmethod
// DECODER_CONTROL[7:0]
//    [0] DECODER_RESET
//    [1] DECODER_ENABLE
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	endmethod
	method Bit#(32) get_decoder_control();
	    let v = 0;
	    v[0] = decoder_reset_reg;
	    v[1] = decoder_enable_reg;
	    return v;
	endmethod
// CRC_CONTROL[7:0]
//    [0] CRC_RESET
//    [1] CRC_INITVALUE
	method Action set_crc_control(Bit#(32) v);
	    crc_reset_reg <= v[0];
	    crc_initvalue_reg <= v[1];
	endmethod
	method Bit#(32) get_crc_control();
	    let v = 0;
	    v[0] = crc_reset_reg;
	    v[1] = crc_initvalue_reg;
	    return v;
	endmethod
	method Bit#(32) get_crc_status();
	    return crc_status_wire;
	endmethod
// REMAPPER_CONTROL[7:0]
//    [2:0] REMAPPER_WRITE_CFG
//    [6:4] REMAPPER_MODE
	method Action set_remapper_control(Bit#(32) v);
	    remapper_write_cfg_reg <= v[2:0];
	    remapper_mode_reg <= v[6:4];
	endmethod
	method Bit#(32) get_remapper_control();
	    let v = 0;
	    v[2:0] = remapper_write_cfg_reg;
	    v[6:4] = remapper_mode_reg;
	    return v;
	endmethod
// TRIGGEN_CONTROL
// [ 2: 0] TRIGGEN_ENABLE
// [ 6: 4] TRIGGEN_SYNC2READOUT
// [    8] TRIGGEN_READOUTTRIGGER
// [   16] TRIGGEN_EXT_POLARITY
// [   24] TRIGGEN_CNT_UPDATE
// [30:28] TRIGGEN_GEN_POLARITY
	method Action set_triggen_control(Bit#(32) v);
	    trigger_enable_reg <= v[2:0];
	    trigger_sync2readout_reg <= v[6:4];
	    trigger_readouttrigger_reg <= v[8];
	    trigger_ext_polarity_reg <= v[16];
	    //FIXME
	    //trigger_cnt_update_reg <= v[24];
	    trigger_gen_polarity_reg <= v[30:28];
	endmethod
	method Bit#(32) get_triggen_control();
	    let v = 0;
	    v[2:0] = trigger_enable_reg;
	    v[6:4] = trigger_sync2readout_reg;
	    v[8] = trigger_readouttrigger_reg;
	    v[16] = trigger_ext_polarity_reg;
	    //FIXME
	    //v[24] = trigger_cnt_update_reg;
	    v[30:28] = trigger_gen_polarity_reg;
	    return v;
	endmethod

	method Action set_host_vita_reset(Bit#(1) v);
	    host_vita_reset_reg <= v;
	endmethod
	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	endmethod
	method Action set_iic_reset(Bit#(1) v);
	    host_iic_reset_reg <= v[0];
	endmethod
	method Action set_clock_gen_reset(Bit#(1) v);
	    host_clock_gen_reset_reg <= v[0];
	endmethod
	method Action set_clock_gen_select(Bit#(1) v);
	    host_clock_gen_select_reg <= v[0];
	endmethod
	method Bit#(1) get_clock_gen_locked();
	    return host_clock_gen_locked_wire;
	endmethod

	method Action set_spi_reset(Bit#(1) v);
	    spi_reset_reg <= v;
	endmethod
	method Action set_spi_timing(Bit#(16) v);
	    spi_timing_reg <= v;
	endmethod
	interface Put txfifo;
	    method Action put(Bit#(32) v) if (spi_txfifo_full_wire == 0);
	        spi_txfifo_wen_wire <= 1;
		spi_txfifo_din_wire <= v;
	    endmethod
	endinterface
	interface Get rxfifo;
	    method ActionValue#(Bit#(32)) get() if (spi_rxfifo_empty_wire == 0);
		spi_rxfifo_ren_wire <= 1;
		return spi_rxfifo_dout_wire;
	    endmethod
	endinterface
	method Action set_serdes_reset(Bit#(1) v);
	    serdes_reset_reg <= v;
	endmethod
	method Action set_serdes_auto_align(Bit#(1) v);
	    serdes_auto_align_reg <= v;
	endmethod
	method Action set_serdes_align_start(Bit#(1) v);
	    serdes_align_start_reg <= v;
	endmethod
	method Action set_serdes_fifo_enable(Bit#(1) v);
	    serdes_fifo_enable_reg <= v;
	endmethod
	method Action set_serdes_manual_tap(Bit#(10) v);
	    serdes_manual_tap_reg <= v;
	endmethod
	method Action set_serdes_training(Bit#(10) v);
	    serdes_training_reg <= v;
	endmethod
	method Action set_decoder_reset(Bit#(1) v);
	    decoder_reset_reg <= v;
	endmethod
	method Action set_decoder_enable(Bit#(1) v);
	    decoder_enable_reg <= v;
	endmethod
	method Action set_decoder_startoddeven(Bit#(32) v);
	    decoder_startoddeven_reg <= v;
	endmethod
	method Action set_decoder_code_ls(Bit#(10) v);
	    decoder_code_ls_reg <= v;
	endmethod
	method Action set_decoder_code_le(Bit#(10) v);
	    decoder_code_le_reg <= v;
	endmethod
	method Action set_decoder_code_fs(Bit#(10) v);
	    decoder_code_fs_reg <= v;
	endmethod
	method Action set_decoder_code_fe(Bit#(10) v);
	    decoder_code_fe_reg <= v;
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	    decoder_code_bl_reg <= v;
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	    decoder_code_img_reg <= v;
	endmethod
	method Action set_decoder_code_tr(Bit#(10) v);
	    decoder_code_tr_reg <= v;
	endmethod
	method Action set_decoder_code_crc(Bit#(10) v);
	    decoder_code_crc_reg <= v;
	endmethod
	method Action set_crc_reset(Bit#(1) v);
	    crc_reset_reg <= v;
	endmethod
	method Action set_crc_initvalue(Bit#(1) v);
	    crc_initvalue_reg <= v;
	endmethod
	method Action set_remapper_write_cfg(Bit#(3) v);
	    remapper_write_cfg_reg <= v;
	endmethod
	method Action set_remapper_mode(Bit#(3) v);
	    remapper_mode_reg <= v;
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_reg <= v;
	endmethod
	method Action set_trigger_sync2readout(Bit#(3) v);
	    trigger_sync2readout_reg <= v;
	endmethod
	method Action set_trigger_readouttrigger(Bit#(1) v);
	    trigger_readouttrigger_reg <= v;
	endmethod
	method Action set_trigger_default_freq(Bit#(32) v);
	    trigger_default_freq_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0high(Bit#(32) v);
	    trigger_cnt_trigger0high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0low(Bit#(32) v);
	    trigger_cnt_trigger0low_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger1high(Bit#(32) v);
	    trigger_cnt_trigger1high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger1low(Bit#(32) v);
	    trigger_cnt_trigger1low_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger2high(Bit#(32) v);
	    trigger_cnt_trigger2high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger2low(Bit#(32) v);
	    trigger_cnt_trigger2low_reg <= v;
	endmethod
	method Action set_trigger_ext_debounce(Bit#(32) v);
	    trigger_ext_debounce_reg <= v;
	endmethod
	method Action set_trigger_ext_polarity(Bit#(1) v);
	    trigger_ext_polarity_reg <= v;
	endmethod
	method Action set_trigger_gen_polarity(Bit#(3) v);
	    trigger_gen_polarity_reg <= v;
	endmethod
	method Action set_prnu_values(Bit#(256) v);
	    prnu_values_reg <= v;
	endmethod
	method Action set_syncgen_delay(Bit#(16) v);
	    syncgen_delay_reg <= v;
	endmethod
	method Action set_syncgen_hactive(Bit#(16) v);
	    syncgen_hactive_reg <= v;
	endmethod
	method Action set_syncgen_hfporch(Bit#(16) v);
	    syncgen_hfporch_reg <= v;
	endmethod
	method Action set_syncgen_hsync(Bit#(16) v);
	    syncgen_hsync_reg <= v;
	endmethod
	method Action set_syncgen_hbporch(Bit#(16) v);
	    syncgen_hbporch_reg <= v;
	endmethod
	method Action set_syncgen_vactive(Bit#(16) v);
	    syncgen_vactive_reg <= v;
	endmethod
	method Action set_syncgen_vfporch(Bit#(16) v);
	    syncgen_vfporch_reg <= v;
	endmethod
	method Action set_syncgen_vsync(Bit#(16) v);
	    syncgen_vsync_reg <= v;
	endmethod
	method Action set_syncgen_vbporch(Bit#(16) v);
	    syncgen_vbporch_reg <= v;
	endmethod
    endinterface
endmodule


define interface pins

define interface pins

Change-Id: I2d22c6ddadacba683914f2d83db5b7296b57097d

// bsv libraries
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;

// portz libraries
import Directory::*;
import CtrlMux::*;
import Portal::*;
import Leds::*;
import PortalMemory::*;
import MemTypes::*;
import MemServer::*;

// generated by tool
import MemlatencyRequestWrapper::*;
import DmaConfigWrapper::*;
import MemlatencyIndicationProxy::*;
import DmaIndicationProxy::*;

// defined by user
import Memlatency::*;

typedef enum {MemlatencyIndication, MemlatencyRequest, DmaIndication, DmaConfig} IfcNames deriving (Eq,Bits);

module mkPortalTop(StdPortalDmaTop#(addrWidth))

   provisos(Add#(addrWidth, a__, 52),
	    Add#(b__, addrWidth, 64),
	    Add#(c__, 12, addrWidth),
	    Add#(addrWidth, d__, 44),
	    Add#(e__, c__, 40),
	    Add#(f__, addrWidth, 40));

   MemlatencyIndicationProxy memlatencyIndicationProxy <- mkMemlatencyIndicationProxy(MemlatencyIndication);
   Memlatency memlatency <- mkMemlatency(memlatencyIndicationProxy.ifc);
   MemlatencyRequestWrapper memlatencyRequestWrapper <- mkMemlatencyRequestWrapper(MemlatencyRequest,memlatency.request);

   DmaIndicationProxy dmaIndicationProxy <- mkDmaIndicationProxy(DmaIndication);
   Vector#(1,  ObjectReadClient#(64))   readClients = cons(memlatency.dmaReadClient, nil);
   Vector#(1, ObjectWriteClient#(64)) writeClients = cons(memlatency.dmaWriteClient, nil);
   MemServer#(addrWidth, 64, 1)   dma <- mkMemServer(dmaIndicationProxy.ifc, readClients, writeClients);
   DmaConfigWrapper dmaRequestWrapper <- mkDmaConfigWrapper(DmaConfig,dma.request);

   Vector#(4,StdPortal) portals;
   portals[0] = memlatencyRequestWrapper.portalIfc;
   portals[1] = memlatencyIndicationProxy.portalIfc;
   portals[2] = dmaRequestWrapper.portalIfc;
   portals[3] = dmaIndicationProxy.portalIfc;

   StdDirectory dir <- mkStdDirectory(portals);
   let ctrl_mux <- mkSlaveMux(dir,portals);

   interface Empty pins; endinterface
   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface leds = default_leds;
endmodule

// bsv libraries
import SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;

// portz libraries
import Directory::*;
import CtrlMux::*;
import Portal::*;
import Leds::*;
import PortalMemory::*;
import MemTypes::*;
import MemServer::*;

// generated by tool
import MemlatencyRequestWrapper::*;
import DmaConfigWrapper::*;
import MemlatencyIndicationProxy::*;
import DmaIndicationProxy::*;

// defined by user
import Memlatency::*;

typedef enum {MemlatencyIndication, MemlatencyRequest, DmaIndication, DmaConfig} IfcNames deriving (Eq,Bits);

module mkPortalTop(StdPortalDmaTop#(addrWidth))

   provisos(Add#(addrWidth, a__, 52),
	    Add#(b__, addrWidth, 64),
	    Add#(c__, 12, addrWidth),
	    Add#(addrWidth, d__, 44),
	    Add#(e__, c__, 40),
	    Add#(f__, addrWidth, 40));

   MemlatencyIndicationProxy memlatencyIndicationProxy <- mkMemlatencyIndicationProxy(MemlatencyIndication);
   Memlatency memlatency <- mkMemlatency(memlatencyIndicationProxy.ifc);
   MemlatencyRequestWrapper memlatencyRequestWrapper <- mkMemlatencyRequestWrapper(MemlatencyRequest,memlatency.request);

   DmaIndicationProxy dmaIndicationProxy <- mkDmaIndicationProxy(DmaIndication);
   Vector#(1,  ObjectReadClient#(64))   readClients = cons(memlatency.dmaReadClient, nil);
   Vector#(1, ObjectWriteClient#(64)) writeClients = cons(memlatency.dmaWriteClient, nil);
   MemServer#(addrWidth, 64, 1)   dma <- mkMemServer(dmaIndicationProxy.ifc, readClients, writeClients);
   DmaConfigWrapper dmaRequestWrapper <- mkDmaConfigWrapper(DmaConfig,dma.request);

   Vector#(4,StdPortal) portals;
   portals[0] = memlatencyRequestWrapper.portalIfc;
   portals[1] = memlatencyIndicationProxy.portalIfc;
   portals[2] = dmaRequestWrapper.portalIfc;
   portals[3] = dmaIndicationProxy.portalIfc;

   StdDirectory dir <- mkStdDirectory(portals);
   let ctrl_mux <- mkSlaveMux(dir,portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface leds = default_leds;
endmodule


missed ifdef TOP_SOURCES_PORTAL_CLOCK

missed ifdef TOP_SOURCES_PORTAL_CLOCK

// Copyright (c) 2016 Connectal Project

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Arbitrate::*;
import BRAM::*;
import BuildVector::*;
import Clocks::*;
import Connectable::*;
import FIFOF::*;
import Gearbox::*;
import GetPut::*;
import Probe::*;
import StmtFSM::*;
import Vector::*;

import AddressGenerator::*;
import AxiBits::*;
import AxiStream::*;
import ConnectalClocks::*;
import ConnectalConfig::*;
import DefaultValue::*;
import GearboxGetPut::*;
import HostInterface::*;
import MemReadEngine::*;
import MemTypes::*;
import PhysMemSlaveFromBram::*;
import Pipe::*;
import TraceMemClient::*;
import XilinxCells::*;
import MPEngine::*;

import Nvme::*;
import NvmeIfc::*;
import NvmePins::*;
import StringSearchIfc::*;

interface NvmeSearch;
   interface NvmeRequest request;
   interface NvmeDriverRequest driverRequest;
   interface MemServerPortalRequest bramRequest;
   interface StringSearchRequest searchRequest;
   interface NvmeTrace trace;
   interface NvmePins pins;
   interface Vector#(2, MemReadClient#(DataBusWidth)) dmaReadClient;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaWriteClient;
`ifdef TOP_SOURCES_PORTAL_CLOCK
   interface Clock portalClockSource;
`endif
endinterface

typedef enum {
   Loopback,
   Needle,
   MpNext,
   Clear,
   Opcode,
   StartBlock,
   NumBlocks,
   Start
   } MsgFromSoftwareTag deriving (Bits,Eq);

typedef struct {
   MsgFromSoftwareTag tag;
   Bit#(24)  data;
   } MsgFromSoftware deriving (Bits);

typedef enum {
   Loopback=1,
   LocDone=2,
   TransferDone=3
   } MsgToSoftwareTag deriving (Bits,Eq);

typedef struct {
   MsgToSoftwareTag tag;
   Bit#(24)  data;
   } MsgToSoftware deriving (Bits);

(* synthesize *)
module mkSearchAcceleratorClient(NvmeAcceleratorClient);
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   Reg#(Bit#(24))                      needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();

   FIFOF#(MemData#(32)) msgFromSoftwareFifo <- mkFIFOF();
   FIFOF#(MemData#(32)) msgToSoftwareFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataFromNvmeFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataToNvmeFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoCommand))) requestFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoResponse))) responseFifo <- mkFIFOF();

   mkConnection(toPipeOut(dataFromNvmeFifo), mpEngine.haystack);

   Reg#(Bit#(8)) opcode <- mkReg(extend(pack(NvmeRead)));
   Reg#(Bit#(32)) startBlock <- mkReg(0);
   Reg#(Bit#(32))  numBlocks <- mkReg(0);
   Reg#(Bit#(16)) requestId <- mkReg(0);

   let inmsgTagProbe <- mkProbe();
   let inmsgDataProbe <- mkProbe();
   let outmsgTagProbe <- mkProbe();
   let outmsgDataProbe <- mkProbe();
   let responseProbe <- mkProbe();
   rule rl_msg_from_software;
      let md <- toGet(msgFromSoftwareFifo).get();
      MsgFromSoftware msg = unpack(truncate(md.data));
      inmsgTagProbe <= msg.tag;
      inmsgDataProbe <= msg.data;
      case (msg.tag) matches
	 Loopback: begin
		      MsgToSoftware outmsg = MsgToSoftware { tag: Loopback, data: msg.data };
		      outmsgTagProbe <= outmsg.tag;
		      outmsgDataProbe <= outmsg.data;
		      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: md.last });
		   end
	 Needle: mpEngine.needle.enq(MemDataF { data: extend(msg.data), first: False, last: md.last, tag: 0 });
	 MpNext: mpEngine.mpNext.enq(MemDataF { data: extend(msg.data), first: False, last: md.last, tag: 0 });
	 Clear:  mpEngine.clear();
	 Opcode:         opcode <= truncate(msg.data);
	 StartBlock: startBlock <= extend(msg.data);
	 NumBlocks:   numBlocks <= extend(msg.data);
	 Start: begin
		   mpEngine.start(extend(msg.data));
		   needleLenReg <= msg.data;
		   requestFifo.enq(pack(NvmeIoCommand {
		      opcode: opcode,
		      flags: 0,
		      requestId: requestId,
		      startBlock: extend(startBlock),
		      numBlocks: numBlocks,
		      dsm: 'h71 // FIXME copied value from nvme.cpp, but where did this come from?
		      }));
		   requestId <= requestId + 1;
		end
      endcase
   endrule
   rule rl_response;
      let r <- toGet(responseFifo).get();
      NvmeIoResponse response = unpack(r);
      Bit#(8) sct = truncate(response.statusCodeType);
      responseProbe <= response.statusCode;

      MsgToSoftware outmsg = MsgToSoftware { tag: TransferDone, data: { sct, response.statusCode }};
      outmsgTagProbe <= outmsg.tag;
      outmsgDataProbe <= outmsg.data;
      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: True });
   endrule
   rule rl_match;
      let loc <- toGet(mpEngine.locdone).get();
      MsgToSoftware outmsg = MsgToSoftware { tag: LocDone, data: truncate(pack(loc)) };
      outmsgTagProbe <= outmsg.tag;
      outmsgDataProbe <= outmsg.data;
      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: (loc == -1) });
   endrule

   AxiStreamSlave#(32) msgFromSoftwareStream <- mkAxiStream(msgFromSoftwareFifo);
   AxiStreamMaster#(32) msgToSoftwareStream <- mkAxiStream(msgToSoftwareFifo);
   AxiStreamSlave#(PcieDataBusWidth) dataFromNvmeStream <- mkAxiStream(dataFromNvmeFifo);
   AxiStreamMaster#(PcieDataBusWidth) dataToNvmeStream <- mkAxiStream(dataToNvmeFifo);
   AxiStreamMaster#(SizeOf#(NvmeIoCommand)) requestStream <- mkAxiStream(requestFifo);
   AxiStreamSlave#(SizeOf#(NvmeIoResponse)) responseStream <- mkAxiStream(responseFifo);

   interface AxiStreamSlave msgFromSoftware = msgFromSoftwareStream;
   interface AxiStreamMaster msgToSoftware = msgToSoftwareStream;
   interface AxiStreamSlave dataFromNvme = dataFromNvmeStream;
   interface AxiStreamMaster dataToNvme = dataToNvmeStream;
   interface AxiStreamMaster request = requestStream;
   interface AxiStreamSlave response = responseStream;

endmodule

module mkNvmeSearch#(NvmeIndication ind, NvmeDriverIndication driverInd, NvmeTrace trace, MemServerPortalIndication bramIndication,
	       StringSearchResponse searchIndication)(NvmeSearch);

   let nvme <- mkNvme(ind, driverInd, trace, bramIndication);

   MemReadEngine#(DataBusWidth,DataBusWidth,2,3) re <- mkMemReadEngine();

`ifndef NVME_ACCELERATOR_INTERFACE
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth))     fifoToMp <- mkFIFOF();
   let                                 needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();
   mkConnection(re.readServers[0].data, mpEngine.needle);
   mkConnection(re.readServers[1].data, mpEngine.mpNext);
   mkConnection(toPipeOut(fifoToMp), mpEngine.haystack);

   Reg#(Bool) firstReg <- mkReg(True);
   rule rl_count_data_to_mp;
      let data <- toGet(nvme.dataFromNvme).get();
      if (dataLengthFifo.notEmpty()) begin
	 data.last = (dataCounter+fromInteger(valueOf(PcieDataBusWidth)/8)) >= dataLengthFifo.first;
	 let md = MemDataF {data: data.data, last: data.last, first: firstReg, tag: 0};
	 firstReg <= data.last;
	 fifoToMp.enq(md);
      end
      dataCounter <= dataCounter + 1;
   endrule

   rule rl_locdone;
      let loc <- toGet(mpEngine.locdone).get();
      searchIndication.strstrLoc(pack(loc));
   endrule
`endif

   interface NvmeRequest                request = nvme.request;
   interface NvmeDriverRequest    driverRequest = nvme.driverRequest;
   interface MemServerPortalRequest bramRequest = nvme.bramRequest;
   interface NvmeTrace                    trace = nvme.trace;
   interface NvmePins                      pins = nvme.pins;
   interface StringSearchRequest searchRequest;
      method Action setSearchString(Bit#(32) needleSglId, Bit#(32) mpNextSglId, Bit#(32) needleLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.clear();
	 needleLenReg <= needleLen;

	 let burstLen = fromInteger(valueOf(DataBusWidth)/8);
	 let mask = burstLen - 1;
	 needleLen = (needleLen + mask) & ~mask;
	 re.readServers[0].request.put(MemengineCmd {sglId: needleSglId, base: 0, burstLen: burstLen, len: needleLen, tag: 0});
	 re.readServers[1].request.put(MemengineCmd {sglId: mpNextSglId, base: 0, burstLen: burstLen, len: needleLen*4, tag: 0});
`endif
      endmethod
      method Action startSearch(Bit#(32) haystackLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.start(needleLenReg);
	 dataLengthFifo.enq(haystackLen);
`endif
      endmethod
   endinterface
`ifdef TOP_SOURCES_PORTAL_CLOCK
   interface Clock portalClockSource = nvme.portalClockSource;
`endif
   interface Vector dmaReadClient = append(nvme.dmaReadClient, vec(re.dmaClient));
   interface Vector dmaWriteClient = nvme.dmaWriteClient;
endmodule

// Copyright (c) 2016 Connectal Project

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Arbitrate::*;
import BRAM::*;
import BuildVector::*;
import Clocks::*;
import Connectable::*;
import FIFOF::*;
import Gearbox::*;
import GetPut::*;
import Probe::*;
import StmtFSM::*;
import Vector::*;

import AddressGenerator::*;
import AxiBits::*;
import AxiStream::*;
import ConnectalClocks::*;
import ConnectalConfig::*;
import DefaultValue::*;
import GearboxGetPut::*;
import HostInterface::*;
import MemReadEngine::*;
import MemTypes::*;
import PhysMemSlaveFromBram::*;
import Pipe::*;
import TraceMemClient::*;
import XilinxCells::*;
import MPEngine::*;

import Nvme::*;
import NvmeIfc::*;
import NvmePins::*;
import StringSearchIfc::*;

interface NvmeSearch;
   interface NvmeRequest request;
   interface NvmeDriverRequest driverRequest;
   interface MemServerPortalRequest bramRequest;
   interface StringSearchRequest searchRequest;
   interface NvmeTrace trace;
   interface NvmePins pins;
   interface Vector#(2, MemReadClient#(DataBusWidth)) dmaReadClient;
   interface Vector#(1, MemWriteClient#(DataBusWidth)) dmaWriteClient;
`ifdef TOP_SOURCES_PORTAL_CLOCK
   interface Clock portalClockSource;
`endif
endinterface

typedef enum {
   Loopback,
   Needle,
   MpNext,
   Clear,
   Opcode,
   StartBlock,
   NumBlocks,
   Start
   } MsgFromSoftwareTag deriving (Bits,Eq);

typedef struct {
   MsgFromSoftwareTag tag;
   Bit#(24)  data;
   } MsgFromSoftware deriving (Bits);

typedef enum {
   Loopback=1,
   LocDone=2,
   TransferDone=3
   } MsgToSoftwareTag deriving (Bits,Eq);

typedef struct {
   MsgToSoftwareTag tag;
   Bit#(24)  data;
   } MsgToSoftware deriving (Bits);

(* synthesize *)
module mkSearchAcceleratorClient(NvmeAcceleratorClient);
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   Reg#(Bit#(24))                      needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();

   FIFOF#(MemData#(32)) msgFromSoftwareFifo <- mkFIFOF();
   FIFOF#(MemData#(32)) msgToSoftwareFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataFromNvmeFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth)) dataToNvmeFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoCommand))) requestFifo <- mkFIFOF();
   FIFOF#(Bit#(SizeOf#(NvmeIoResponse))) responseFifo <- mkFIFOF();

   mkConnection(toPipeOut(dataFromNvmeFifo), mpEngine.haystack);

   Reg#(Bit#(8)) opcode <- mkReg(extend(pack(NvmeRead)));
   Reg#(Bit#(32)) startBlock <- mkReg(0);
   Reg#(Bit#(32))  numBlocks <- mkReg(0);
   Reg#(Bit#(16)) requestId <- mkReg(0);

   let inmsgTagProbe <- mkProbe();
   let inmsgDataProbe <- mkProbe();
   let outmsgTagProbe <- mkProbe();
   let outmsgDataProbe <- mkProbe();
   let responseProbe <- mkProbe();
   rule rl_msg_from_software;
      let md <- toGet(msgFromSoftwareFifo).get();
      MsgFromSoftware msg = unpack(truncate(md.data));
      inmsgTagProbe <= msg.tag;
      inmsgDataProbe <= msg.data;
      case (msg.tag) matches
	 Loopback: begin
		      MsgToSoftware outmsg = MsgToSoftware { tag: Loopback, data: msg.data };
		      outmsgTagProbe <= outmsg.tag;
		      outmsgDataProbe <= outmsg.data;
		      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: md.last });
		   end
	 Needle: mpEngine.needle.enq(MemDataF { data: extend(msg.data), first: False, last: md.last, tag: 0 });
	 MpNext: mpEngine.mpNext.enq(MemDataF { data: extend(msg.data), first: False, last: md.last, tag: 0 });
	 Clear:  mpEngine.clear();
	 Opcode:         opcode <= truncate(msg.data);
	 StartBlock: startBlock <= extend(msg.data);
	 NumBlocks:   numBlocks <= extend(msg.data);
	 Start: begin
		   mpEngine.start(extend(msg.data));
		   needleLenReg <= msg.data;
		   requestFifo.enq(pack(NvmeIoCommand {
		      opcode: opcode,
		      flags: 0,
		      requestId: requestId,
		      startBlock: extend(startBlock),
		      numBlocks: numBlocks,
		      dsm: 'h71 // FIXME copied value from nvme.cpp, but where did this come from?
		      }));
		   requestId <= requestId + 1;
		end
      endcase
   endrule
   rule rl_response;
      let r <- toGet(responseFifo).get();
      NvmeIoResponse response = unpack(r);
      Bit#(8) sct = truncate(response.statusCodeType);
      responseProbe <= response.statusCode;

      MsgToSoftware outmsg = MsgToSoftware { tag: TransferDone, data: { sct, response.statusCode }};
      outmsgTagProbe <= outmsg.tag;
      outmsgDataProbe <= outmsg.data;
      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: True });
   endrule
   rule rl_match;
      let loc <- toGet(mpEngine.locdone).get();
      MsgToSoftware outmsg = MsgToSoftware { tag: LocDone, data: truncate(pack(loc)) };
      outmsgTagProbe <= outmsg.tag;
      outmsgDataProbe <= outmsg.data;
      msgToSoftwareFifo.enq(MemData { data: extend(pack(outmsg)), last: (loc == -1) });
   endrule

   AxiStreamSlave#(32) msgFromSoftwareStream <- mkAxiStream(msgFromSoftwareFifo);
   AxiStreamMaster#(32) msgToSoftwareStream <- mkAxiStream(msgToSoftwareFifo);
   AxiStreamSlave#(PcieDataBusWidth) dataFromNvmeStream <- mkAxiStream(dataFromNvmeFifo);
   AxiStreamMaster#(PcieDataBusWidth) dataToNvmeStream <- mkAxiStream(dataToNvmeFifo);
   AxiStreamMaster#(SizeOf#(NvmeIoCommand)) requestStream <- mkAxiStream(requestFifo);
   AxiStreamSlave#(SizeOf#(NvmeIoResponse)) responseStream <- mkAxiStream(responseFifo);

   interface AxiStreamSlave msgFromSoftware = msgFromSoftwareStream;
   interface AxiStreamMaster msgToSoftware = msgToSoftwareStream;
   interface AxiStreamSlave dataFromNvme = dataFromNvmeStream;
   interface AxiStreamMaster dataToNvme = dataToNvmeStream;
   interface AxiStreamMaster request = requestStream;
   interface AxiStreamSlave response = responseStream;

endmodule

module mkNvmeSearch#(NvmeIndication ind, NvmeDriverIndication driverInd, NvmeTrace trace, MemServerPortalIndication bramIndication,
	       StringSearchResponse searchIndication)(NvmeSearch);

   let nvme <- mkNvme(ind, driverInd, trace, bramIndication);

   MemReadEngine#(DataBusWidth,DataBusWidth,2,3) re <- mkMemReadEngine();

`ifndef NVME_ACCELERATOR_INTERFACE
   Reg#(Bit#(32))                       dataCounter <- mkReg(0);
   FIFOF#(Bit#(32))                  dataLengthFifo <- mkFIFOF();
   FIFOF#(MemDataF#(PcieDataBusWidth))     fifoToMp <- mkFIFOF();
   let                                 needleLenReg <- mkReg(0);
   MPStreamEngine#(PcieDataBusWidth,DataBusWidth)    mpEngine <- mkMPStreamEngine();
   mkConnection(re.readServers[0].data, mpEngine.needle);
   mkConnection(re.readServers[1].data, mpEngine.mpNext);
   mkConnection(toPipeOut(fifoToMp), mpEngine.haystack);

   Reg#(Bool) firstReg <- mkReg(True);
   rule rl_count_data_to_mp;
      let data <- toGet(nvme.dataFromNvme).get();
      if (dataLengthFifo.notEmpty()) begin
	 data.last = (dataCounter+fromInteger(valueOf(PcieDataBusWidth)/8)) >= dataLengthFifo.first;
	 let md = MemDataF {data: data.data, last: data.last, first: firstReg, tag: 0};
	 firstReg <= data.last;
	 fifoToMp.enq(md);
      end
      dataCounter <= dataCounter + 1;
   endrule

   rule rl_locdone;
      let loc <- toGet(mpEngine.locdone).get();
      searchIndication.strstrLoc(pack(loc));
   endrule
`endif

   interface NvmeRequest                request = nvme.request;
   interface NvmeDriverRequest    driverRequest = nvme.driverRequest;
   interface MemServerPortalRequest bramRequest = nvme.bramRequest;
   interface NvmeTrace                    trace = nvme.trace;
   interface NvmePins                      pins = nvme.pins;
   interface StringSearchRequest searchRequest;
      method Action setSearchString(Bit#(32) needleSglId, Bit#(32) mpNextSglId, Bit#(32) needleLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.clear();
	 needleLenReg <= needleLen;

	 let burstLen = fromInteger(valueOf(DataBusWidth)/8);
	 let mask = burstLen - 1;
	 needleLen = (needleLen + mask) & ~mask;
	 re.readServers[0].request.put(MemengineCmd {sglId: needleSglId, base: 0, burstLen: burstLen, len: needleLen, tag: 0});
	 re.readServers[1].request.put(MemengineCmd {sglId: mpNextSglId, base: 0, burstLen: burstLen, len: needleLen*4, tag: 0});
`endif
      endmethod
      method Action startSearch(Bit#(32) haystackLen);
`ifndef NVME_ACCELERATOR_INTERFACE
	 mpEngine.start(needleLenReg);
	 dataLengthFifo.enq(haystackLen);
`endif
      endmethod
   endinterface
   interface Clock portalClockSource = nvme.portalClockSource;
   interface Vector dmaReadClient = append(nvme.dmaReadClient, vec(re.dmaClient));
   interface Vector dmaWriteClient = nvme.dmaWriteClient;
endmodule