temp update to use new video data (screen skewed/etc)

// 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 Vector::*;
import FIFO::*;
import GetPut::*;
import Gearbox::*;
import Clocks :: *;

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_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#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Action frame_start(Bit#(1) start);
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
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

typedef struct {
    Bit#(1) fsync;
    Bit#(1) vsync;
    Bit#(1) hsync;
    Bit#(1) active_video;
    Bit#(10) video_data;
} XsviData deriving (Bits);

interface ImageonSensorData;
    method Bit#(1) active_video();
    method Action video_data_old(Bit#(10) v);
    method Action framestart(Bit#(1) v);
    method Action video_data(Bit#(40) v);
    method Bit#(32) get_debugind();
    interface Reset reset;
    interface Reset slowReset;
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_oe();
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonTrigger trigger;
    interface ImageonSyncGen syncgen;
    method Bit#(32) get_debugreq();
    method Action set_debugind(Bit#(32) v);
    interface Reset reset;
endinterface

interface ImageonControl;
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Action set_triggen_control(Bit#(32) v);

    method Action set_host_oe(Bit#(1) v);

    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_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_trigger_enable(Bit#(3) 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_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);
    method Action set_debugreq(Bit#(32) v);
    method Bit#(32) get_debugind();
endinterface

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

module mkImageonVitaController#(Clock hdmi_clock)(ImageonVitaController);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset;
    Reg#(Bit#(1)) host_oe_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);

    Reg#(Bit#(1)) serdes_reset_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) serdes_training_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Wire#(Bit#(1)) serdes_clk_ready_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 <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) decoder_enable_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) trigger_enable_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) debugreq_value <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) debugind_value <- mkReg(0);

    interface ImageonVita host;
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	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_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#(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 Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_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
	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
        method Bit#(32) get_debugreq();
            return debugreq_value;
	endmethod
        method Action set_debugind(Bit#(32) v);
            debugind_value <= v;
	endmethod
        interface Reset reset = defaultReset;
    endinterface: host
    interface ImageonControl control;
	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[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    return v;
	endmethod
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	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];
	endmethod

	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	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_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);
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_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_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
        method Action set_debugreq(Bit#(32) v);
            debugreq_value <= v;
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
    endinterface
endmodule

interface ImageonXsviFromSensor;
    interface ImageonSensorData in;
    interface Get#(XsviData) out;
endinterface

typedef enum { Idle, Active, FrontP, Sync, BackP} State deriving (Bits,Eq);

module mkImageonXsviFromSensor#(Clock slow_clock, Reset slow_reset, ImageonVita host)(ImageonXsviFromSensor);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();

    Reg#(Bit#(1)) active_video_reg <- mkReg(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);

    Reg#(State)       hstate <- mkReg(Idle);
    Reg#(State)       vstate <- mkReg(Idle);
    Reg#(Bit#(16))    vsync_count <- mkReg(0);
    Reg#(Bit#(16))    hsync_count <- mkReg(0);
    Reg#(Bit#(32))    debugind_value <- mkReg(0);
    Reg#(Bit#(32))    diff <- mkReg(0);
    Reg#(Bit#(10))    videodata <- mkReg(0);
    Reg#(Bit#(1))     framestart_reg <- mkReg(0, clocked_by slow_clock, reset_by slow_reset);
    Reg#(Bit#(1))     framestart_delay_reg <- mkReg(0, clocked_by slow_clock, reset_by slow_reset);
    Reg#(Bit#(1))     framestart_new <- mkReg(0);
    Gearbox#(4, 1, Bit#(10)) dataGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);
    Gearbox#(4, 1, Bit#(1))  syncGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);

    rule start_fsm if (framestart_new == 1);
        vsync_count <= 0;
        hsync_count <= 0;
        hstate <= Active;
        vstate <= Active;
    endrule

    rule sync_fsm if (framestart_new != 1);
        let hs = hstate;
        let vs = vstate;
        let hc = hsync_count;
        let vc = vsync_count;

        hc = hc + 1;
        if (hstate == FrontP && hsync_count >= host.syncgen.hfporch() - 1)
            begin
            hc = 0;
            hs = Sync;
            vc = vc + 1;
            if (vstate == Active && vsync_count >= host.syncgen.vactive() - 1)
                begin
                vc = 0;
                vs = FrontP;
                end
            if (vstate == FrontP && vsync_count >= host.syncgen.vfporch() - 1)
                begin
                vc = 0;
                vs = Sync;
                end
            if (vstate == Sync && vsync_count >= host.syncgen.vsync() - 1)
                begin
                vc = 0;
                vs = BackP;
                end
            end
        if (hstate == Sync && hsync_count >= host.syncgen.hsync() - 1)
            begin
            hc = 0;
            hs = BackP;
            end
        if (hstate == BackP && hsync_count >= host.syncgen.hbporch() - 1)
            begin
            hc = 0;
            hs = Active;
            end
        if (hstate == Active && hsync_count >= host.syncgen.hactive() - 1)
            begin
            hc = 0;
            hs = FrontP;
            end

        hstate <= hs;
        vstate <= vs;
        hsync_count <= hc;
        vsync_count <= vc;
        active_video_reg <= pack(hstate == Active && vstate == Active);
    endrule

    rule update_framestart;
	syncGearbox.deq;
        framestart_new <= syncGearbox.first[0];
    endrule

    rule update_videodata if (active_video_reg == 1);
	dataGearbox.deq;
        videodata <= dataGearbox.first[0];
    endrule

    rule update_debug;
        let dval = diff;
        //dval = {diff[28:0], framestart_wire, xsvi_framestart_old_wire, framestart_new};
        if (diff[29] == 1)
            begin
            debugind_value <= diff;
            dval = 0;
            end
        diff <= dval;
    endrule

    interface ImageonSensorData in;
        method Bit#(1) active_video();
            return active_video_reg;
        endmethod
	method Action video_data_old(Bit#(10) v);
            xsvi_video_data_wire <= v;
	endmethod
	method Action framestart(Bit#(1) v);
            framestart_reg <= v;
            framestart_delay_reg <= framestart_reg;
	    Vector#(4, Bit#(1)) in = replicate(0);
	    // zero'th element shifted out first
	    in[1] = framestart_delay_reg;
	    syncGearbox.enq(in);
	endmethod
	method Action video_data(Bit#(40) v);// if (active_video_reg == 1);
	    // least signifcant 10 bits shifted out first
	    Vector#(4, Bit#(10)) in = unpack(v);
	    dataGearbox.enq(in);
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
	interface Reset reset = defaultReset;
	interface Reset slowReset = slow_reset;
    endinterface: in
    interface Get out;
	method ActionValue#(XsviData) get();
	    return XsviData {
		fsync: framestart_new,
		vsync: pack(vstate == Sync),
		hsync: pack(hstate == Sync),
		active_video: active_video_reg,
		video_data: videodata
	    };
	endmethod
    endinterface: out
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 Vector::*;
import FIFO::*;
import GetPut::*;
import Gearbox::*;
import Clocks :: *;

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_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#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Action frame_start(Bit#(1) start);
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
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

typedef struct {
    Bit#(1) fsync;
    Bit#(1) vsync;
    Bit#(1) hsync;
    Bit#(1) active_video;
    Bit#(10) video_data;
} XsviData deriving (Bits);

interface ImageonSensorData;
    method Bit#(1) active_video();
    method Action video_data_old(Bit#(10) v);
    method Action framestart(Bit#(1) v);
    method Action video_data(Bit#(40) v);
    method Bit#(32) get_debugind();
    interface Reset reset;
    interface Reset slowReset;
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_oe();
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonTrigger trigger;
    interface ImageonSyncGen syncgen;
    method Bit#(32) get_debugreq();
    method Action set_debugind(Bit#(32) v);
    interface Reset reset;
endinterface

interface ImageonControl;
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Action set_triggen_control(Bit#(32) v);

    method Action set_host_oe(Bit#(1) v);

    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_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_trigger_enable(Bit#(3) 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_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);
    method Action set_debugreq(Bit#(32) v);
    method Bit#(32) get_debugind();
endinterface

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

module mkImageonVitaController#(Clock hdmi_clock)(ImageonVitaController);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset;
    Reg#(Bit#(1)) host_oe_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);

    Reg#(Bit#(1)) serdes_reset_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) serdes_training_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Wire#(Bit#(1)) serdes_clk_ready_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 <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(1)) decoder_enable_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) trigger_enable_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) debugreq_value <- mkSyncReg(0, defaultClock, defaultReset, hdmi_clock);
    Reg#(Bit#(32)) debugind_value <- mkReg(0);

    interface ImageonVita host;
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	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_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#(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 Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_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
	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
        method Bit#(32) get_debugreq();
            return debugreq_value;
	endmethod
        method Action set_debugind(Bit#(32) v);
            debugind_value <= v;
	endmethod
        interface Reset reset = defaultReset;
    endinterface: host
    interface ImageonControl control;
	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[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    return v;
	endmethod
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	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];
	endmethod

	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	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_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);
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_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_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
        method Action set_debugreq(Bit#(32) v);
            debugreq_value <= v;
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
    endinterface
endmodule

interface ImageonXsviFromSensor;
    interface ImageonSensorData in;
    interface Get#(XsviData) out;
endinterface

typedef enum { Idle, Active, FrontP, Sync, BackP} State deriving (Bits,Eq);

module mkImageonXsviFromSensor#(Clock slow_clock, Reset slow_reset, ImageonVita host)(ImageonXsviFromSensor);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    Gearbox#(4, 1, Bit#(10)) dataGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);
    Gearbox#(4, 1, Bit#(1))  syncGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);

    Reg#(Bit#(1)) active_video_reg <- mkReg(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);
    Reg#(Bit#(1))  framestart_wire <- mkSyncReg(0, slow_clock, slow_reset, defaultClock);

    Reg#(State)       hstate <- mkReg(Idle);
    Reg#(State)       vstate <- mkReg(Idle);
    Reg#(Bit#(16))    vsync_count <- mkReg(0);
    Reg#(Bit#(16))    hsync_count <- mkReg(0);
    Reg#(Bit#(32))    debugind_value <- mkReg(0);
    Reg#(Bit#(32))    diff <- mkReg(0);
    Reg#(Bit#(10))    videodata <- mkReg(0);
    Reg#(Bit#(1))     framestart_reg <- mkReg(0, clocked_by slow_clock, reset_by slow_reset);
    Reg#(Bit#(1))     framestart_delay_reg <- mkReg(0, clocked_by slow_clock, reset_by slow_reset);
    Reg#(Bit#(1))     framestart_new <- mkReg(0);

    rule start_fsm if (framestart_new == 1);
        vsync_count <= 0;
        hsync_count <= 0;
        hstate <= Active;
        vstate <= Active;
    endrule

    rule sync_fsm if (framestart_new != 1);
        let hs = hstate;
        let vs = vstate;
        let hc = hsync_count;
        let vc = vsync_count;

        hc = hc + 1;
        if (hstate == FrontP && hsync_count >= host.syncgen.hfporch() - 1)
            begin
            hc = 0;
            hs = Sync;
            vc = vc + 1;
            if (vstate == Active && vsync_count >= host.syncgen.vactive() - 1)
                begin
                vc = 0;
                vs = FrontP;
                end
            if (vstate == FrontP && vsync_count >= host.syncgen.vfporch() - 1)
                begin
                vc = 0;
                vs = Sync;
                end
            if (vstate == Sync && vsync_count >= host.syncgen.vsync() - 1)
                begin
                vc = 0;
                vs = BackP;
                end
            end
        if (hstate == Sync && hsync_count >= host.syncgen.hsync() - 1)
            begin
            hc = 0;
            hs = BackP;
            end
        if (hstate == BackP && hsync_count >= host.syncgen.hbporch() - 1)
            begin
            hc = 0;
            hs = Active;
            end
        if (hstate == Active && hsync_count >= host.syncgen.hactive() - 1)
            begin
            hc = 0;
            hs = FrontP;
            end

        hstate <= hs;
        vstate <= vs;
        hsync_count <= hc;
        vsync_count <= vc;
        active_video_reg <= pack(hstate == Active && vstate == Active);
    endrule

    rule update_framestart;
	syncGearbox.deq;
        framestart_new <= syncGearbox.first[0];
    endrule
    rule update_videodata;
	dataGearbox.deq;
        videodata <= dataGearbox.first[0];
    endrule

    rule update_debug;
        let dval = diff;
        //dval = {diff[28:0], framestart_wire, xsvi_framestart_old_wire, framestart_new};
        if (diff[29] == 1)
            begin
            debugind_value <= diff;
            dval = 0;
            end
        diff <= dval;
    endrule

    interface ImageonSensorData in;
        method Bit#(1) active_video();
            return active_video_reg;
        endmethod
	method Action video_data_old(Bit#(10) v);
            xsvi_video_data_wire <= v;
	endmethod
	method Action framestart(Bit#(1) v);
            framestart_wire <= v;
            framestart_reg <= v;
            framestart_delay_reg <= framestart_reg;
	    Vector#(4, Bit#(1)) in = replicate(0);
	    // zero'th element shifted out first
	    in[1] = framestart_delay_reg;
	    syncGearbox.enq(in);
	endmethod
	method Action video_data(Bit#(40) v);
	    // least signifcant 10 bits shifted out first
	    Vector#(4, Bit#(10)) in = unpack(v);
	    dataGearbox.enq(in);
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
	interface Reset reset = defaultReset;
	interface Reset slowReset = slow_reset;
    endinterface: in
    interface Get out;
	method ActionValue#(XsviData) get();
	    return XsviData {
		fsync: framestart_new,
		vsync: pack(vstate == Sync),
		hsync: pack(hstate == Sync),
		active_video: active_video_reg,
		video_data: xsvi_video_data_wire //videodata
	    };
	endmethod
    endinterface: out
endmodule


conform Top to usage of other examples

conform Top to usage of other examples

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

// portz libraries
import AxiMasterSlave::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import PortalMemory::*;
import PortalRMemory::*;
import AxiRDMA::*;

// generated by tool
import RingIndicationProxy::*;
import RingRequestWrapper::*;
import DMARequestWrapper::*;
import DMAIndicationProxy::*;

// defined by user
import Ring::*;

typedef enum {RingIndication, RingRequest, DMAIndication, DMARequest} IfcNames deriving (Eq,Bits);

module mkPortalTop(StdPortalTop#(addrWidth));

   // instantiate DMA infrastructure
   DMAIndicationProxy dmaIndicationProxy <- mkDMAIndicationProxy(DMAIndication);
   DMAReadBuffer#(64,8) dma_read_chan <- mkDMAReadBuffer();
   DMAWriteBuffer#(64,8) dma_write_chan <- mkDMAWriteBuffer();
   DMAReadBuffer#(64,8) cmd_read_chan <- mkDMAReadBuffer();
   DMAWriteBuffer#(64,8) cmd_write_chan <- mkDMAWriteBuffer();

   Vector#(2, DMAReadClient#(64)) readClients = newVector();
   readClients[0] = dma_read_chan.dmaClient;
   readClients[1] = cmd_read_chan.dmaClient;

   Vector#(2, DMAWriteClient#(64)) writeClients = newVector();
   writeClients[0] = dma_write_chan.dmaClient;
   writeClients[1] = cmd_write_chan.dmaClient;

   Integer numRequests = 8;
   AxiDMA#(Bit#(64))   dma <- mkAxiDMA(dmaIndication.ifc, numRequests, readClients, writeClients);
   DMARequestWrapper dmaRequestWrapper <- mkDMARequestWrapper(DMARequest,dma.request);

   // instantiate user portals
   RingIndicationProxy ringIndicationProxy <- mkRingIndicationProxy(RingIndication);
   RingRequest ringRequest <- mkRingRequestInternal(ringIndicationProxy.ifc, dma_read_chan, dma_write_chan, cmd_read_chan, cmd_write_chan);
   RingRequestWrapper ringRequestWrapper <- mkRingRequestWrapper(RingRequest, ringRequest);

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

   let interrupt_mux <- mkInterruptMux(portals);

   // instantiate system directory
   Directory dir <- mkDirectoryDbg(portals,interrupt_mux);
   Vector#(1,StdPortal) directories;
   directories[0] = dir.portalIfc;

   // when constructing the ctrl mux, directories must be the first argument
   let ctrl_mux <- mkAxiSlaveMux(directories,portals);

   interface interrupt = interrupt_mux;
   interface ctrl = ctrl_mux;
   interface m_axi = replicate(dma.m_axi);
   interface leds = ?;
endmodule : mkPortalTop

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

// portz libraries
import AxiMasterSlave::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import PortalMemory::*;
import PortalRMemory::*;
import AxiRDMA::*;

// generated by tool
import RingIndicationProxy::*;
import RingRequestWrapper::*;
import DMARequestWrapper::*;
import DMAIndicationProxy::*;

// defined by user
import Ring::*;

typedef enum {RingIndication, RingRequest, DmaRequest, DmaIndication} IfcNames deriving (Eq,Bits);

module mkPortalTop(StdPortalTop#(addrWidth));

   // instantiate DMA infrastructure
   DMAIndicationProxy dmaIndicationProxy <- mkDMAIndicationProxy(DMAIndication);
   DMAReadBuffer#(64,8) dma_read_chan <- mkDMAReadBuffer();
   DMAWriteBuffer#(64,8) dma_write_chan <- mkDMAWriteBuffer();
   DMAReadBuffer#(64,8) cmd_read_chan <- mkDMAReadBuffer();
   DMAWriteBuffer#(64,8) cmd_write_chan <- mkDMAWriteBuffer();

   Vector#(2, DMAReadClient#(64)) readClients = newVector();
   readClients[0] = dma_read_chan.dmaClient;
   readClients[1] = cmd_read_chan.dmaClient;

   Vector#(2, DMAWriteClient#(64)) writeClients = newVector();
   writeClients[0] = dma_write_chan.dmaClient;
   writeClients[1] = cmd_write_chan.dmaClient;

   DMAIndicationProxy dmaIndicationProxy <- mkDMAIndicationProxy(DMAIndication);
   Integer numRequests = 8;
   AxiDMA#(Bit#(64))   dma <- mkAxiDMA(dmaIndication.ifc, numRequests, readClients, writeClients);
   DMARequestWrapper dmaRequestWrapper <- mkDMARequestWrapper(DMARequest,dma.request);

   // instantiate user portals
   RingIndicationProxy ringIndicationProxy <- mkRingIndicationProxy(RingIndication);
   RingRequest ringRequest <- mkRingRequestInternal(ringIndicationProxy.ifc, dma_read_chan, dma_write_chan, cmd_read_chan, cmd_write_chan);
   RingRequestWrapper ringRequestWrapper <- mkRingRequestWrapper(RingRequest, ringRequest);

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

   let interrupt_mux <- mkInterruptMux(portals);

   // instantiate system directory
   Directory dir <- mkDirectoryDbg(portals,interrupt_mux);
   Vector#(1,StdPortal) directories;
   directories[0] = dir.portalIfc;

   // when constructing the ctrl mux, directories must be the first argument
   let ctrl_mux <- mkAxiSlaveMux(directories,portals);

   interface interrupt = interrupt_mux;
   interface ctrl = ctrl_mux;
   interface m_axi = replicate(dma.m_axi);
   interface leds = ?;
endmodule : mkPortalTop


write action value to match table ram

write action value to match table ram

import FIFO::*;
import FIFOF::*;
import GetPut::*;
import ClientServer::*;
import StmtFSM::*;
import Vector::*;
import DefaultValue::*;
import BRAM::*;
import FShow::*;
import Pipe::*;
import Bcam::*;
import BcamTypes::*;

interface MatchTable#(numeric type depth, numeric type keySz, numeric type actionSz);
   interface Server#(Bit#(keySz), Maybe#(Bit#(actionSz))) lookupPort;
   interface Put#(Tuple2#(Bit#(keySz), Bit#(actionSz))) add_entry;
   interface Put#(Bit#(TLog#(depth))) delete_entry;
   interface Put#(Tuple2#(Bit#(TLog#(depth)), Bit#(actionSz))) modify_entry;
endinterface

import "BDPI" function ActionValue#(Bit#(10)) matchtable_read_dmac(Bit#(54) dstAddr);
import "BDPI" function Action matchtable_write_dmac(Bit#(54) dstAddr, Bit#(10) data);
import "BDPI" function ActionValue#(Bit#(2)) matchtable_read_acceptor(Bit#(18) msgtype);
import "BDPI" function Action matchtable_write_acceptor(Bit#(18) msgtype, Bit#(2) data);
import "BDPI" function ActionValue#(Bit#(1)) matchtable_read_sequence(Bit#(18) msgtype);
import "BDPI" function Action matchtable_write_sequence(Bit#(18) msgtype, Bit#(1) data);

typeclass MatchTableSim#(numeric type ksz, numeric type vsz);
   function ActionValue#(Bit#(vsz)) matchtable_read(Bit#(ksz) key);
   function Action matchtable_write(Bit#(ksz) key, Bit#(vsz) data);
endtypeclass

instance MatchTableSim#(54, 10);
   function ActionValue#(Bit#(10)) matchtable_read(Bit#(54) key);
   actionvalue
      let v <- matchtable_read_dmac(key);
      return v;
   endactionvalue
   endfunction
   function Action matchtable_write(Bit#(54) key, Bit#(10) data);
   action
      $display("(%0d) matchtable write dmac %h %h", $time, key, data);
      matchtable_write_dmac(key, data);
      $display("(%0d) matchtable write dmac done", $time);
   endaction
   endfunction
endinstance

instance MatchTableSim#(18, 1);
   function ActionValue#(Bit#(1)) matchtable_read(Bit#(18) key);
   actionvalue
      let v <- matchtable_read_sequence(key);
      return v;
   endactionvalue
   endfunction
   function Action matchtable_write(Bit#(18) key, Bit#(1) data);
   action
      matchtable_write_sequence(key, data);
   endaction
   endfunction
endinstance

instance MatchTableSim#(18, 2);
   function ActionValue#(Bit#(2)) matchtable_read(Bit#(18) key);
   actionvalue
      let v <- matchtable_read_acceptor(key);
      return v;
   endactionvalue
   endfunction
   function Action matchtable_write(Bit#(18) key, Bit#(2) data);
   action
      $display("(%0d) matchtable write acceptor %h %h", $time, key, data);
      matchtable_write_acceptor(key, data);
      $display("(%0d) matchtable write acceptor done", $time);
   endaction
   endfunction
endinstance

module mkMatchTable(MatchTable#(depth, keySz, actionSz))
   provisos(Mul#(c__, 256, d__),
            Add#(c__, 7, TLog#(depth)),
            Log#(d__, TLog#(depth)),
            Mul#(e__, 9, keySz),
            Add#(TAdd#(TLog#(c__), 4), 2, TLog#(TDiv#(depth, 4))),
            Log#(TDiv#(depth, 16), TAdd#(TLog#(c__), 4)),
            Add#(9, f__, keySz),
            PriorityEncoder::PEncoder#(d__),
            Add#(2, g__, TLog#(depth)),
            Add#(4, h__, TLog#(depth)),
`ifdef SIMULATION
            MatchTableSim#(keySz, actionSz),
`endif
            Add#(TAdd#(TLog#(c__), 4), i__, TLog#(depth)));

   MatchTable#(depth, keySz, actionSz) ret_ifc;
//`ifdef SIMULATION
//   ret_ifc <- mkMatchTableBluesim();
//`else
   ret_ifc <- mkMatchTableSynth();
//`endif
   return ret_ifc;
endmodule

module mkMatchTableSynth(MatchTable#(depth, keySz, actionSz))
   provisos (NumAlias#(depthSz, TLog#(depth)),
             Mul#(a__, 256, b__),
             Add#(a__, 7, depthSz),
             Log#(b__, depthSz),
             Mul#(c__, 9, keySz),
             Add#(TAdd#(TLog#(a__), 4), 2, TLog#(TDiv#(depth, 4))),
             Log#(TDiv#(depth, 16), TAdd#(TLog#(a__), 4)),
             Add#(9, d__, keySz),
             PriorityEncoder::PEncoder#(b__),
             Add#(2, e__, TLog#(depth)),
             Add#(4, f__, TLog#(depth)),
             Add#(TAdd#(TLog#(a__), 4), g__, TLog#(depth))
            );
   let verbose = True;
   Reg#(Bit#(32)) cycle <- mkReg(0);

   rule every1 (verbose);
      cycle <= cycle + 1;
   endrule

   BinaryCam#(depth, keySz) bcam <- mkBinaryCam();
   FIFO#(Bool) bcamMatchFifo <- mkFIFO();

   BRAM_Configure cfg = defaultValue;
   cfg.latency = 2;
   BRAM2Port#(Bit#(depthSz), Bit#(actionSz)) ram <- mkBRAM2Server(cfg);

   Reg#(Bit#(depthSz)) addrIdx <- mkReg(0);

   rule handle_bcam_response;
      let v <- bcam.readServer.response.get;
      if (verbose) $display("(%0d) matchTable recv bcam response ", $time, fshow(v));
      if (isValid(v)) begin // if match
         let address = fromMaybe(?, v);
         ram.portA.request.put(BRAMRequest{write:False, responseOnWrite: False, address: address, datain:?});
         bcamMatchFifo.enq(True);
      end
      else begin // if miss
         ram.portA.request.put(BRAMRequest{write:False, responseOnWrite: False, address: 0, datain: ?});
         bcamMatchFifo.enq(False);
      end
   endrule

   // Interface for lookup from data-plane modules
   interface Server lookupPort;
      interface Put request;
         method Action put (Bit#(keySz) v);
            BcamReadReq#(Bit#(keySz)) req_bcam = BcamReadReq{data: v};
            bcam.readServer.request.put(pack(req_bcam));
            //if (verbose) $display("matchTable %d: lookup ", cycle, fshow(req_bcam));
         endmethod
      endinterface
      interface Get response;
         method ActionValue#(Maybe#(Bit#(actionSz))) get();
            let m <- toGet(bcamMatchFifo).get;
            let act <- ram.portA.response.get;
            if (verbose) $display("(%0d) matchTable: recv ram response ", $time, fshow(act));
            case (m) matches
               True: return tagged Valid act;
               False: return tagged Invalid;
            endcase
         endmethod
      endinterface
   endinterface

   // Interface for write from control-plane
   interface Put add_entry;
      method Action put (Tuple2#(Bit#(keySz), Bit#(actionSz)) v);
         BcamWriteReq#(Bit#(depthSz), Bit#(keySz)) req_bcam = BcamWriteReq{addr: addrIdx, data: pack(tpl_1(v))};
         BRAMRequest#(Bit#(depthSz), Bit#(actionSz)) req_ram = BRAMRequest{write: True, responseOnWrite: False, address: addrIdx, datain: pack(tpl_2(v))};
         bcam.writeServer.put(req_bcam);
         ram.portA.request.put(req_ram);
         $display("(%0d) match_table: add flow %x %x %x", $time, addrIdx, tpl_1(v), tpl_2(v));
         addrIdx <= addrIdx + 1; //FIXME: currently no reuse of address.
      endmethod
   endinterface
   interface Put delete_entry;
      method Action put (Bit#(depthSz) id);
         BcamWriteReq#(Bit#(depthSz), Bit#(keySz)) req_bcam = BcamWriteReq{addr: id, data: 0};
         BRAMRequest#(Bit#(depthSz), Bit#(actionSz)) req_ram = BRAMRequest{write: True, responseOnWrite: False, address: id, datain: 0};
         bcam.writeServer.put(req_bcam);
         ram.portA.request.put(req_ram);
         $display("(%0d) match_table: delete flow %x", $time, id);
      endmethod
   endinterface
   interface Put modify_entry;
      method Action put (Tuple2#(Bit#(depthSz), Bit#(actionSz)) v);
         match { .flowid, .act} = v;
         BRAMRequest#(Bit#(depthSz), Bit#(actionSz)) req_ram = BRAMRequest{write: True, responseOnWrite: False, address: flowid, datain: pack(act)};
         ram.portA.request.put(req_ram);
      endmethod
   endinterface
endmodule

module mkMatchTableBluesim(MatchTable#(depth, keySz, actionSz))
   provisos (MatchTableSim#(keySz, actionSz),
             Log#(depth, depthSz));
   let verbose = True;

   FIFO#(Tuple2#(Bit#(keySz), Bit#(actionSz))) writeReqFifo <- mkFIFO;
   FIFO#(Bit#(keySz)) readReqFifo <- mkFIFO;
   FIFO#(Maybe#(Bit#(actionSz))) readDataFifo <- mkFIFO;

   Reg#(Bool)      isInitialized   <- mkReg(False);

   rule do_read (isInitialized);
      let v <- toGet(readReqFifo).get;
      $display("(%0d) MatchTable: do_read %h", $time, v);
      let ret <- matchtable_read(pack(v));
      $display("(%0d) MatchTable: read %h", $time, ret);
      if (ret != 0)
         readDataFifo.enq(tagged Valid ret);
      else
         readDataFifo.enq(tagged Invalid);
   endrule

   rule do_init (!isInitialized);
      isInitialized <= True;
   endrule

   interface Server lookupPort;
      interface Put request = toPut(readReqFifo);
      interface Get response = toGet(readDataFifo);
   endinterface
   interface Put add_entry;
      method Action put (Tuple2#(Bit#(keySz), Bit#(actionSz)) v);
         $display("(%0d) MatchTable: insert %h %h", $time, tpl_1(v), tpl_2(v));
         matchtable_write(tpl_1(v), tpl_2(v));
      endmethod
   endinterface
   interface Put delete_entry;
      method Action put (Bit#(depthSz) id);

      endmethod
   endinterface
   interface Put modify_entry;
      method Action put (Tuple2#(Bit#(depthSz), Bit#(actionSz)) v);

      endmethod
   endinterface
endmodule

import FIFO::*;
import FIFOF::*;
import GetPut::*;
import ClientServer::*;
import StmtFSM::*;
import Vector::*;
import DefaultValue::*;
import BRAM::*;
import FShow::*;
import Pipe::*;
import Bcam::*;
import BcamTypes::*;

interface MatchTable#(numeric type depth, numeric type keySz, numeric type actionSz);
   interface Server#(Bit#(keySz), Maybe#(Bit#(actionSz))) lookupPort;
   interface Put#(Tuple2#(Bit#(keySz), Bit#(actionSz))) add_entry;
   interface Put#(Bit#(TLog#(depth))) delete_entry;
   interface Put#(Tuple2#(Bit#(TLog#(depth)), Bit#(actionSz))) modify_entry;
endinterface

import "BDPI" function ActionValue#(Bit#(10)) matchtable_read_dmac(Bit#(54) dstAddr);
import "BDPI" function Action matchtable_write_dmac(Bit#(54) dstAddr, Bit#(10) data);
import "BDPI" function ActionValue#(Bit#(2)) matchtable_read_acceptor(Bit#(18) msgtype);
import "BDPI" function Action matchtable_write_acceptor(Bit#(18) msgtype, Bit#(2) data);
import "BDPI" function ActionValue#(Bit#(1)) matchtable_read_sequence(Bit#(18) msgtype);
import "BDPI" function Action matchtable_write_sequence(Bit#(18) msgtype, Bit#(1) data);

typeclass MatchTableSim#(numeric type ksz, numeric type vsz);
   function ActionValue#(Bit#(vsz)) matchtable_read(Bit#(ksz) key);
   function Action matchtable_write(Bit#(ksz) key, Bit#(vsz) data);
endtypeclass

instance MatchTableSim#(54, 10);
   function ActionValue#(Bit#(10)) matchtable_read(Bit#(54) key);
   actionvalue
      let v <- matchtable_read_dmac(key);
      return v;
   endactionvalue
   endfunction
   function Action matchtable_write(Bit#(54) key, Bit#(10) data);
   action
      $display("(%0d) matchtable write dmac %h %h", $time, key, data);
      matchtable_write_dmac(key, data);
      $display("(%0d) matchtable write dmac done", $time);
   endaction
   endfunction
endinstance

instance MatchTableSim#(18, 1);
   function ActionValue#(Bit#(1)) matchtable_read(Bit#(18) key);
   actionvalue
      let v <- matchtable_read_sequence(key);
      return v;
   endactionvalue
   endfunction
   function Action matchtable_write(Bit#(18) key, Bit#(1) data);
   action
      matchtable_write_sequence(key, data);
   endaction
   endfunction
endinstance

instance MatchTableSim#(18, 2);
   function ActionValue#(Bit#(2)) matchtable_read(Bit#(18) key);
   actionvalue
      let v <- matchtable_read_acceptor(key);
      return v;
   endactionvalue
   endfunction
   function Action matchtable_write(Bit#(18) key, Bit#(2) data);
   action
      $display("(%0d) matchtable write acceptor %h %h", $time, key, data);
      matchtable_write_acceptor(key, data);
      $display("(%0d) matchtable write acceptor done", $time);
   endaction
   endfunction
endinstance

module mkMatchTable(MatchTable#(depth, keySz, actionSz))
   provisos(Mul#(c__, 256, d__),
            Add#(c__, 7, TLog#(depth)),
            Log#(d__, TLog#(depth)),
            Mul#(e__, 9, keySz),
            Add#(TAdd#(TLog#(c__), 4), 2, TLog#(TDiv#(depth, 4))),
            Log#(TDiv#(depth, 16), TAdd#(TLog#(c__), 4)),
            Add#(9, f__, keySz),
            PriorityEncoder::PEncoder#(d__),
            Add#(2, g__, TLog#(depth)),
            Add#(4, h__, TLog#(depth)),
`ifdef SIMULATION
            MatchTableSim#(keySz, actionSz),
`endif
            Add#(TAdd#(TLog#(c__), 4), i__, TLog#(depth)));

   MatchTable#(depth, keySz, actionSz) ret_ifc;
`ifdef SIMULATION
   ret_ifc <- mkMatchTableBluesim();
`else
   ret_ifc <- mkMatchTableSynth();
`endif
   return ret_ifc;
endmodule

module mkMatchTableSynth(MatchTable#(depth, keySz, actionSz))
   provisos (NumAlias#(depthSz, TLog#(depth)),
             Mul#(a__, 256, b__),
             Add#(a__, 7, depthSz),
             Log#(b__, depthSz),
             Mul#(c__, 9, keySz),
             Add#(TAdd#(TLog#(a__), 4), 2, TLog#(TDiv#(depth, 4))),
             Log#(TDiv#(depth, 16), TAdd#(TLog#(a__), 4)),
             Add#(9, d__, keySz),
             PriorityEncoder::PEncoder#(b__),
             Add#(2, e__, TLog#(depth)),
             Add#(4, f__, TLog#(depth)),
             Add#(TAdd#(TLog#(a__), 4), g__, TLog#(depth))
            );
   let verbose = True;
   Reg#(Bit#(32)) cycle <- mkReg(0);

   rule every1 (verbose);
      cycle <= cycle + 1;
   endrule

   BinaryCam#(depth, keySz) bcam <- mkBinaryCam();
   FIFO#(Bool) bcamMatchFifo <- mkFIFO();

   BRAM_Configure cfg = defaultValue;
   cfg.latency = 2;
   BRAM2Port#(Bit#(depthSz), Bit#(actionSz)) ram <- mkBRAM2Server(cfg);

   Reg#(Bit#(depthSz)) addrIdx <- mkReg(0);

   rule handle_bcam_response;
      let v <- bcam.readServer.response.get;
      //if (verbose) $display("matchTable %d: recv bcam response ", cycle, fshow(v));
      if (isValid(v)) begin // if match
         let address = fromMaybe(?, v);
         ram.portA.request.put(BRAMRequest{write:False, responseOnWrite: False, address: address, datain:?});
         bcamMatchFifo.enq(True);
      end
      else begin // if miss
         ram.portA.request.put(BRAMRequest{write:False, responseOnWrite: False, address: 0, datain: ?});
         bcamMatchFifo.enq(False);
      end
   endrule

   // Interface for lookup from data-plane modules
   interface Server lookupPort;
      interface Put request;
         method Action put (Bit#(keySz) v);
            BcamReadReq#(Bit#(keySz)) req_bcam = BcamReadReq{data: v};
            bcam.readServer.request.put(pack(req_bcam));
            //if (verbose) $display("matchTable %d: lookup ", cycle, fshow(req_bcam));
         endmethod
      endinterface
      interface Get response;
         method ActionValue#(Maybe#(Bit#(actionSz))) get();
            let m <- toGet(bcamMatchFifo).get;
            let act <- ram.portA.response.get;
            if (verbose) $display("(%0d) matchTable: recv ram response ", $time, fshow(act));
            case (m) matches
               True: return tagged Valid act;
               False: return tagged Invalid;
            endcase
         endmethod
      endinterface
   endinterface

   // Interface for write from control-plane
   interface Put add_entry;
      method Action put (Tuple2#(Bit#(keySz), Bit#(actionSz)) v);
         BcamWriteReq#(Bit#(depthSz), Bit#(keySz)) req_bcam = BcamWriteReq{addr: addrIdx, data: pack(tpl_1(v))};
         BRAMRequest#(Bit#(depthSz), Bit#(actionSz)) req_ram = BRAMRequest{write: True, responseOnWrite: False, address: addrIdx, datain: 0};
         bcam.writeServer.put(req_bcam);
         ram.portA.request.put(req_ram);
         $display("(%0d) match_table: add flow %x", $time, addrIdx);
         addrIdx <= addrIdx + 1; //FIXME: currently no reuse of address.
      endmethod
   endinterface
   interface Put delete_entry;
      method Action put (Bit#(depthSz) id);
         BcamWriteReq#(Bit#(depthSz), Bit#(keySz)) req_bcam = BcamWriteReq{addr: id, data: 0};
         BRAMRequest#(Bit#(depthSz), Bit#(actionSz)) req_ram = BRAMRequest{write: True, responseOnWrite: False, address: id, datain: 0};
         bcam.writeServer.put(req_bcam);
         ram.portA.request.put(req_ram);
         $display("(%0d) match_table: delete flow %x", $time, id);
      endmethod
   endinterface
   interface Put modify_entry;
      method Action put (Tuple2#(Bit#(depthSz), Bit#(actionSz)) v);
         match { .flowid, .act} = v;
         BRAMRequest#(Bit#(depthSz), Bit#(actionSz)) req_ram = BRAMRequest{write: True, responseOnWrite: False, address: flowid, datain: pack(act)};
         ram.portA.request.put(req_ram);
      endmethod
   endinterface
endmodule

module mkMatchTableBluesim(MatchTable#(depth, keySz, actionSz))
   provisos (MatchTableSim#(keySz, actionSz),
             Log#(depth, depthSz));
   let verbose = True;

   FIFO#(Tuple2#(Bit#(keySz), Bit#(actionSz))) writeReqFifo <- mkFIFO;
   FIFO#(Bit#(keySz)) readReqFifo <- mkFIFO;
   FIFO#(Maybe#(Bit#(actionSz))) readDataFifo <- mkFIFO;

   Reg#(Bool)      isInitialized   <- mkReg(False);

   rule do_read (isInitialized);
      let v <- toGet(readReqFifo).get;
      $display("(%0d) MatchTable: do_read %h", $time, v);
      let ret <- matchtable_read(pack(v));
      $display("(%0d) MatchTable: read %h", $time, ret);
      if (ret != 0)
         readDataFifo.enq(tagged Valid ret);
      else
         readDataFifo.enq(tagged Invalid);
   endrule

   rule do_init (!isInitialized);
      isInitialized <= True;
   endrule

   interface Server lookupPort;
      interface Put request = toPut(readReqFifo);
      interface Get response = toGet(readDataFifo);
   endinterface
   interface Put add_entry;
      method Action put (Tuple2#(Bit#(keySz), Bit#(actionSz)) v);
         $display("(%0d) MatchTable: insert %h %h", $time, tpl_1(v), tpl_2(v));
         matchtable_write(tpl_1(v), tpl_2(v));
      endmethod
   endinterface
   interface Put delete_entry;
      method Action put (Bit#(depthSz) id);

      endmethod
   endinterface
   interface Put modify_entry;
      method Action put (Tuple2#(Bit#(depthSz), Bit#(actionSz)) v);

      endmethod
   endinterface
endmodule