default clock sys_clk

default clock sys_clk

/*
   ../scripts/importbvi.py
   -I
   AxiDdr3
   -o
   AxiDdr3Wrapper.bsv
   -P
   AxiDdr3
   -f
   ddr3
   -c ui_clk
   -r ui_clk_sync_rst
   -c sys_clk_i
   -r sys_rst
   /home/jamey/connectal/out/vc707/axiddr3/axiddr3_stub.v
*/

import Clocks::*;
import DefaultValue::*;
import XilinxCells::*;
import GetPut::*;
import AxiBits::*;

(* always_ready, always_enabled *)
interface AxiDdr3App;
    method Bit#(1)     ref_ack();
    method Action      ref_req(Bit#(1) v);
    method Bit#(1)     sr_active();
    method Action      sr_req(Bit#(1) v);
    method Bit#(1)     zq_ack();
    method Action      zq_req(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3Ddr3;
    method Bit#(14)     addr();
    method Bit#(3)     ba();
    method Bit#(1)     cas_n();
    method Bit#(1)     ck_n();
    method Bit#(1)     ck_p();
    method Bit#(1)     cke();
    method Bit#(1)     cs_n();
    method Bit#(8)     dm();
    interface Inout#(Bit#(64))     dq;
    interface Inout#(Bit#(8))     dqs_n;
    interface Inout#(Bit#(8))     dqs_p;
    method Bit#(1)     odt();
    method Bit#(1)     ras_n();
    method Bit#(1)     reset_n();
    method Bit#(1)     we_n();
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3Init;
    method Bit#(1)     calib_complete();
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3Mmcm;
    method Bit#(1)     locked();
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3S_axi;
    method Action      araddr(Bit#(30) v);
    method Action      arburst(Bit#(2) v);
    method Action      arcache(Bit#(4) v);
    method Action      arid(Bit#(6) v);
    method Action      arlen(Bit#(8) v);
    method Action      arlock(Bit#(1) v);
    method Action      arprot(Bit#(3) v);
    method Action      arqos(Bit#(4) v);
    method Bit#(1)     arready();
    method Action      arsize(Bit#(3) v);
    method Action      arvalid(Bit#(1) v);
    method Action      awaddr(Bit#(30) v);
    method Action      awburst(Bit#(2) v);
    method Action      awcache(Bit#(4) v);
    method Action      awid(Bit#(6) v);
    method Action      awlen(Bit#(8) v);
    method Action      awlock(Bit#(1) v);
    method Action      awprot(Bit#(3) v);
    method Action      awqos(Bit#(4) v);
    method Bit#(1)     awready();
    method Action      awsize(Bit#(3) v);
    method Action      awvalid(Bit#(1) v);
    method Bit#(6)     bid();
    method Action      bready(Bit#(1) v);
    method Bit#(2)     bresp();
    method Bit#(1)     bvalid();
    method Bit#(512)     rdata();
    method Bit#(6)     rid();
    method Bit#(1)     rlast();
    method Action      rready(Bit#(1) v);
    method Bit#(2)     rresp();
    method Bit#(1)     rvalid();
    method Action      wdata(Bit#(512) v);
    method Action      wlast(Bit#(1) v);
    method Bit#(1)     wready();
    method Action      wstrb(Bit#(64) v);
    method Action      wvalid(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3;
    interface AxiDdr3App     app;
    interface AxiDdr3Ddr3     ddr3;
    interface AxiDdr3Init     init;
    interface AxiDdr3Mmcm     mmcm;
    interface AxiDdr3S_axi   s_axi;
    method Action aresetn(Bit#(1) r);
    interface Clock ui_clk;
    interface Reset ui_clk_sync_rst;
endinterface
import "BVI" axiddr3 =
module mkAxiDdr3#(Clock sys_clk, Reset sys_rst, Clock clk_ref_i)(AxiDdr3);
   default_clock  sys_clk_i(sys_clk_i) = sys_clk;
   input_clock  clk_ref_i(clk_ref_i) = clk_ref_i;
   default_reset  sys_rst(sys_rst) = sys_rst;
   output_clock  ui_clk(ui_clk);
   output_reset  ui_clk_sync_rst(ui_clk_sync_rst);
    method aresetn(aresetn) enable((*inhigh*) EN_aresetn) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    interface AxiDdr3App     app;
        method app_ref_ack ref_ack() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method ref_req(app_ref_req) enable((*inhigh*) EN_app_ref_req) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method app_sr_active sr_active() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method sr_req(app_sr_req) enable((*inhigh*) EN_app_sr_req) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method app_zq_ack zq_ack() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method zq_req(app_zq_req) enable((*inhigh*) EN_app_zq_req) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    interface AxiDdr3Ddr3     ddr3;
        method ddr3_addr addr();
        method ddr3_ba ba();
        method ddr3_cas_n cas_n();
        method ddr3_ck_n ck_n();
        method ddr3_ck_p ck_p();
        method ddr3_cke cke();
        method ddr3_cs_n cs_n();
        method ddr3_dm dm();
        ifc_inout dq(ddr3_dq);
        ifc_inout dqs_n(ddr3_dqs_n);
        ifc_inout dqs_p(ddr3_dqs_p);
        method ddr3_odt odt();
        method ddr3_ras_n ras_n();
        method ddr3_reset_n reset_n();
        method ddr3_we_n we_n();
    endinterface
    interface AxiDdr3Init     init;
        method init_calib_complete calib_complete() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    interface AxiDdr3Mmcm     mmcm;
        method mmcm_locked locked() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    interface AxiDdr3S_axi     s_axi;
        method araddr(s_axi_araddr) enable((*inhigh*) EN_s_axi_araddr) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arburst(s_axi_arburst) enable((*inhigh*) EN_s_axi_arburst) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arcache(s_axi_arcache) enable((*inhigh*) EN_s_axi_arcache) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arid(s_axi_arid) enable((*inhigh*) EN_s_axi_arid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arlen(s_axi_arlen) enable((*inhigh*) EN_s_axi_arlen) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arlock(s_axi_arlock) enable((*inhigh*) EN_s_axi_arlock) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arprot(s_axi_arprot) enable((*inhigh*) EN_s_axi_arprot) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arqos(s_axi_arqos) enable((*inhigh*) EN_s_axi_arqos) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_arready arready() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arsize(s_axi_arsize) enable((*inhigh*) EN_s_axi_arsize) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arvalid(s_axi_arvalid) enable((*inhigh*) EN_s_axi_arvalid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awaddr(s_axi_awaddr) enable((*inhigh*) EN_s_axi_awaddr) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awburst(s_axi_awburst) enable((*inhigh*) EN_s_axi_awburst) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awcache(s_axi_awcache) enable((*inhigh*) EN_s_axi_awcache) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awid(s_axi_awid) enable((*inhigh*) EN_s_axi_awid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awlen(s_axi_awlen) enable((*inhigh*) EN_s_axi_awlen) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awlock(s_axi_awlock) enable((*inhigh*) EN_s_axi_awlock) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awprot(s_axi_awprot) enable((*inhigh*) EN_s_axi_awprot) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awqos(s_axi_awqos) enable((*inhigh*) EN_s_axi_awqos) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_awready awready() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awsize(s_axi_awsize) enable((*inhigh*) EN_s_axi_awsize) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awvalid(s_axi_awvalid) enable((*inhigh*) EN_s_axi_awvalid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_bid bid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method bready(s_axi_bready) enable((*inhigh*) EN_s_axi_bready) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_bresp bresp() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_bvalid bvalid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rdata rdata() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rid rid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rlast rlast() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method rready(s_axi_rready) enable((*inhigh*) EN_s_axi_rready) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rresp rresp() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rvalid rvalid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wdata(s_axi_wdata) enable((*inhigh*) EN_s_axi_wdata) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wlast(s_axi_wlast) enable((*inhigh*) EN_s_axi_wlast) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_wready wready() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wstrb(s_axi_wstrb) enable((*inhigh*) EN_s_axi_wstrb) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wvalid(s_axi_wvalid) enable((*inhigh*) EN_s_axi_wvalid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    schedule (app.ref_ack, app.ref_req, app.sr_active, app.sr_req, app.zq_ack, app.zq_req, aresetn, ddr3.addr, ddr3.ba, ddr3.cas_n, ddr3.ck_n, ddr3.ck_p, ddr3.cke, ddr3.cs_n, ddr3.dm, ddr3.odt, ddr3.ras_n, ddr3.reset_n, ddr3.we_n, init.calib_complete, mmcm.locked, s_axi.araddr, s_axi.arburst, s_axi.arcache, s_axi.arid, s_axi.arlen, s_axi.arlock, s_axi.arprot, s_axi.arqos, s_axi.arready, s_axi.arsize, s_axi.arvalid, s_axi.awaddr, s_axi.awburst, s_axi.awcache, s_axi.awid, s_axi.awlen, s_axi.awlock, s_axi.awprot, s_axi.awqos, s_axi.awready, s_axi.awsize, s_axi.awvalid, s_axi.bid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rid, s_axi.rlast, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wlast, s_axi.wready, s_axi.wstrb, s_axi.wvalid) CF (app.ref_ack, app.ref_req, app.sr_active, app.sr_req, app.zq_ack, app.zq_req, aresetn, ddr3.addr, ddr3.ba, ddr3.cas_n, ddr3.ck_n, ddr3.ck_p, ddr3.cke, ddr3.cs_n, ddr3.dm, ddr3.odt, ddr3.ras_n, ddr3.reset_n, ddr3.we_n, init.calib_complete, mmcm.locked, s_axi.araddr, s_axi.arburst, s_axi.arcache, s_axi.arid, s_axi.arlen, s_axi.arlock, s_axi.arprot, s_axi.arqos, s_axi.arready, s_axi.arsize, s_axi.arvalid, s_axi.awaddr, s_axi.awburst, s_axi.awcache, s_axi.awid, s_axi.awlen, s_axi.awlock, s_axi.awprot, s_axi.awqos, s_axi.awready, s_axi.awsize, s_axi.awvalid, s_axi.bid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rid, s_axi.rlast, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wlast, s_axi.wready, s_axi.wstrb, s_axi.wvalid);
endmodule

/*
   ../scripts/importbvi.py
   -I
   AxiDdr3
   -o
   AxiDdr3Wrapper.bsv
   -P
   AxiDdr3
   -f
   ddr3
   -c ui_clk
   -r ui_clk_sync_rst
   -c sys_clk_i
   -r sys_rst
   /home/jamey/connectal/out/vc707/axiddr3/axiddr3_stub.v
*/

import Clocks::*;
import DefaultValue::*;
import XilinxCells::*;
import GetPut::*;
import AxiBits::*;

(* always_ready, always_enabled *)
interface AxiDdr3App;
    method Bit#(1)     ref_ack();
    method Action      ref_req(Bit#(1) v);
    method Bit#(1)     sr_active();
    method Action      sr_req(Bit#(1) v);
    method Bit#(1)     zq_ack();
    method Action      zq_req(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3Ddr3;
    method Bit#(14)     addr();
    method Bit#(3)     ba();
    method Bit#(1)     cas_n();
    method Bit#(1)     ck_n();
    method Bit#(1)     ck_p();
    method Bit#(1)     cke();
    method Bit#(1)     cs_n();
    method Bit#(8)     dm();
    interface Inout#(Bit#(64))     dq;
    interface Inout#(Bit#(8))     dqs_n;
    interface Inout#(Bit#(8))     dqs_p;
    method Bit#(1)     odt();
    method Bit#(1)     ras_n();
    method Bit#(1)     reset_n();
    method Bit#(1)     we_n();
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3Init;
    method Bit#(1)     calib_complete();
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3Mmcm;
    method Bit#(1)     locked();
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3S_axi;
    method Action      araddr(Bit#(30) v);
    method Action      arburst(Bit#(2) v);
    method Action      arcache(Bit#(4) v);
    method Action      arid(Bit#(6) v);
    method Action      arlen(Bit#(8) v);
    method Action      arlock(Bit#(1) v);
    method Action      arprot(Bit#(3) v);
    method Action      arqos(Bit#(4) v);
    method Bit#(1)     arready();
    method Action      arsize(Bit#(3) v);
    method Action      arvalid(Bit#(1) v);
    method Action      awaddr(Bit#(30) v);
    method Action      awburst(Bit#(2) v);
    method Action      awcache(Bit#(4) v);
    method Action      awid(Bit#(6) v);
    method Action      awlen(Bit#(8) v);
    method Action      awlock(Bit#(1) v);
    method Action      awprot(Bit#(3) v);
    method Action      awqos(Bit#(4) v);
    method Bit#(1)     awready();
    method Action      awsize(Bit#(3) v);
    method Action      awvalid(Bit#(1) v);
    method Bit#(6)     bid();
    method Action      bready(Bit#(1) v);
    method Bit#(2)     bresp();
    method Bit#(1)     bvalid();
    method Bit#(512)     rdata();
    method Bit#(6)     rid();
    method Bit#(1)     rlast();
    method Action      rready(Bit#(1) v);
    method Bit#(2)     rresp();
    method Bit#(1)     rvalid();
    method Action      wdata(Bit#(512) v);
    method Action      wlast(Bit#(1) v);
    method Bit#(1)     wready();
    method Action      wstrb(Bit#(64) v);
    method Action      wvalid(Bit#(1) v);
endinterface
(* always_ready, always_enabled *)
interface AxiDdr3;
    interface AxiDdr3App     app;
    interface AxiDdr3Ddr3     ddr3;
    interface AxiDdr3Init     init;
    interface AxiDdr3Mmcm     mmcm;
    interface AxiDdr3S_axi   s_axi;
    method Action aresetn(Bit#(1) r);
    interface Clock ui_clk;
    interface Reset ui_clk_sync_rst;
endinterface
import "BVI" axiddr3 =
module mkAxiDdr3#(Clock sys_clk, Reset sys_rst, Clock clk_ref_i)(AxiDdr3);
   input_clock  sys_clk_i(sys_clk_i) = sys_clk;
   input_clock  clk_ref_i(clk_ref_i) = clk_ref_i;
   input_reset  sys_rst(sys_rst) = sys_rst;
   output_clock  ui_clk(ui_clk);
   output_reset  ui_clk_sync_rst(ui_clk_sync_rst);
    method aresetn(aresetn) enable((*inhigh*) EN_aresetn) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    interface AxiDdr3App     app;
        method app_ref_ack ref_ack() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method ref_req(app_ref_req) enable((*inhigh*) EN_app_ref_req) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method app_sr_active sr_active() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method sr_req(app_sr_req) enable((*inhigh*) EN_app_sr_req) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method app_zq_ack zq_ack() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method zq_req(app_zq_req) enable((*inhigh*) EN_app_zq_req) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    interface AxiDdr3Ddr3     ddr3;
        method ddr3_addr addr();
        method ddr3_ba ba();
        method ddr3_cas_n cas_n();
        method ddr3_ck_n ck_n();
        method ddr3_ck_p ck_p();
        method ddr3_cke cke();
        method ddr3_cs_n cs_n();
        method ddr3_dm dm();
        ifc_inout dq(ddr3_dq);
        ifc_inout dqs_n(ddr3_dqs_n);
        ifc_inout dqs_p(ddr3_dqs_p);
        method ddr3_odt odt();
        method ddr3_ras_n ras_n();
        method ddr3_reset_n reset_n();
        method ddr3_we_n we_n();
    endinterface
    interface AxiDdr3Init     init;
        method init_calib_complete calib_complete() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    interface AxiDdr3Mmcm     mmcm;
        method mmcm_locked locked() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    interface AxiDdr3S_axi     s_axi;
        method araddr(s_axi_araddr) enable((*inhigh*) EN_s_axi_araddr) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arburst(s_axi_arburst) enable((*inhigh*) EN_s_axi_arburst) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arcache(s_axi_arcache) enable((*inhigh*) EN_s_axi_arcache) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arid(s_axi_arid) enable((*inhigh*) EN_s_axi_arid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arlen(s_axi_arlen) enable((*inhigh*) EN_s_axi_arlen) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arlock(s_axi_arlock) enable((*inhigh*) EN_s_axi_arlock) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arprot(s_axi_arprot) enable((*inhigh*) EN_s_axi_arprot) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arqos(s_axi_arqos) enable((*inhigh*) EN_s_axi_arqos) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_arready arready() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arsize(s_axi_arsize) enable((*inhigh*) EN_s_axi_arsize) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method arvalid(s_axi_arvalid) enable((*inhigh*) EN_s_axi_arvalid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awaddr(s_axi_awaddr) enable((*inhigh*) EN_s_axi_awaddr) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awburst(s_axi_awburst) enable((*inhigh*) EN_s_axi_awburst) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awcache(s_axi_awcache) enable((*inhigh*) EN_s_axi_awcache) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awid(s_axi_awid) enable((*inhigh*) EN_s_axi_awid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awlen(s_axi_awlen) enable((*inhigh*) EN_s_axi_awlen) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awlock(s_axi_awlock) enable((*inhigh*) EN_s_axi_awlock) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awprot(s_axi_awprot) enable((*inhigh*) EN_s_axi_awprot) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awqos(s_axi_awqos) enable((*inhigh*) EN_s_axi_awqos) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_awready awready() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awsize(s_axi_awsize) enable((*inhigh*) EN_s_axi_awsize) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method awvalid(s_axi_awvalid) enable((*inhigh*) EN_s_axi_awvalid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_bid bid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method bready(s_axi_bready) enable((*inhigh*) EN_s_axi_bready) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_bresp bresp() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_bvalid bvalid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rdata rdata() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rid rid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rlast rlast() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method rready(s_axi_rready) enable((*inhigh*) EN_s_axi_rready) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rresp rresp() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_rvalid rvalid() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wdata(s_axi_wdata) enable((*inhigh*) EN_s_axi_wdata) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wlast(s_axi_wlast) enable((*inhigh*) EN_s_axi_wlast) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method s_axi_wready wready() clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wstrb(s_axi_wstrb) enable((*inhigh*) EN_s_axi_wstrb) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
        method wvalid(s_axi_wvalid) enable((*inhigh*) EN_s_axi_wvalid) clocked_by (ui_clk) reset_by (ui_clk_sync_rst);
    endinterface
    schedule (app.ref_ack, app.ref_req, app.sr_active, app.sr_req, app.zq_ack, app.zq_req, aresetn, ddr3.addr, ddr3.ba, ddr3.cas_n, ddr3.ck_n, ddr3.ck_p, ddr3.cke, ddr3.cs_n, ddr3.dm, ddr3.odt, ddr3.ras_n, ddr3.reset_n, ddr3.we_n, init.calib_complete, mmcm.locked, s_axi.araddr, s_axi.arburst, s_axi.arcache, s_axi.arid, s_axi.arlen, s_axi.arlock, s_axi.arprot, s_axi.arqos, s_axi.arready, s_axi.arsize, s_axi.arvalid, s_axi.awaddr, s_axi.awburst, s_axi.awcache, s_axi.awid, s_axi.awlen, s_axi.awlock, s_axi.awprot, s_axi.awqos, s_axi.awready, s_axi.awsize, s_axi.awvalid, s_axi.bid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rid, s_axi.rlast, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wlast, s_axi.wready, s_axi.wstrb, s_axi.wvalid) CF (app.ref_ack, app.ref_req, app.sr_active, app.sr_req, app.zq_ack, app.zq_req, aresetn, ddr3.addr, ddr3.ba, ddr3.cas_n, ddr3.ck_n, ddr3.ck_p, ddr3.cke, ddr3.cs_n, ddr3.dm, ddr3.odt, ddr3.ras_n, ddr3.reset_n, ddr3.we_n, init.calib_complete, mmcm.locked, s_axi.araddr, s_axi.arburst, s_axi.arcache, s_axi.arid, s_axi.arlen, s_axi.arlock, s_axi.arprot, s_axi.arqos, s_axi.arready, s_axi.arsize, s_axi.arvalid, s_axi.awaddr, s_axi.awburst, s_axi.awcache, s_axi.awid, s_axi.awlen, s_axi.awlock, s_axi.awprot, s_axi.awqos, s_axi.awready, s_axi.awsize, s_axi.awvalid, s_axi.bid, s_axi.bready, s_axi.bresp, s_axi.bvalid, s_axi.rdata, s_axi.rid, s_axi.rlast, s_axi.rready, s_axi.rresp, s_axi.rvalid, s_axi.wdata, s_axi.wlast, s_axi.wready, s_axi.wstrb, s_axi.wvalid);
endmodule


include mdw0 and mdw1 in error message

include mdw0 and mdw1 in error message

Change-Id: I2cf791fe1ff0dd2129756a4aaf89a98074dde535

// 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 FIFOF::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import BRAM::*;
import BRAMFIFO::*;
import Connectable::*;

import ConfigCounter::*;
import ConnectalMemory::*;
import MemTypes::*;
import Pipe::*;
import MemUtils::*;

module mkMemwriteEngine(MemwriteEngineV#(dataWidth, cmdQDepth, numServers))
   provisos( Mul#(TDiv#(dataWidth, 8), 8, dataWidth)
	    ,Add#(1, a__, numServers)
	    ,Add#(b__, TLog#(numServers), TAdd#(1, TLog#(TMul#(cmdQDepth,numServers))))
	    ,Pipe::FunnelPipesPipelined#(1, numServers,Tuple2#(Bit#(TLog#(numServers)), MemTypes::MemengineCmd), TMin#(2,TLog#(numServers)))
	    ,Pipe::FunnelPipesPipelined#(1, numServers,Tuple2#(Bit#(dataWidth),Bool),TMin#(2, TLog#(numServers)))
	    ,Add#(c__, TLog#(numServers), TLog#(TMul#(cmdQDepth, numServers)))
	    ,Add#(1, d__, dataWidth)
	    ,FunnelPipesPipelined#(1, numServers, Tuple3#(Bit#(2),Bit#(dataWidth),Bool), TMin#(2, TLog#(numServers)))
	    ,FunnelPipesPipelined#(1, numServers,Tuple3#(Bit#(TLog#(numServers)), Bit#(dataWidth), Bool), TMin#(2,TLog#(numServers)))
	    ,Add#(e__, TLog#(numServers), 6)
	    );
   let rv <- mkMemwriteEngineBuff(256);
   return rv;
endmodule

interface BurstFunnel#(numeric type k, numeric type w);
   method Action loadIdx(Bit#(TLog#(k)) i);
   interface Vector#(k, PipeIn#(Bit#(w))) dataIn;
   interface Vector#(k, Reg#(Bit#(BurstLenSize))) burstLen;
   interface PipeOut#(Tuple2#(Bit#(TLog#(k)),Bit#(w))) dataOut;
endinterface

module mkBurstFunnel#(Integer maxBurstLen)(BurstFunnel#(k,w))
   provisos( Log#(k,logk)
	    ,Min#(2,logk,bpc)
	    ,FunnelPipesPipelined#(1, k, Tuple3#(Bit#(2),Bit#(w),Bool), bpc)
	    );

   Reg#(Bit#(2)) nameGen <- mkReg(0);
   UGBramFifos#(4,16,Tuple2#(Bit#(w),Bool)) complBuff <- mkUGBramFifos;
   Vector#(4, ConfigCounter#(16)) compCnts <- replicateM(mkConfigCounter(0));
   Vector#(k,FIFOF#(Tuple3#(Bit#(2), Bit#(w), Bool))) data_in <- replicateM(mkFIFOF);
   Vector#(k,Reg#(Bit#(BurstLenSize))) burst_len <- replicateM(mkReg(0));
   Vector#(k,Reg#(Bit#(BurstLenSize))) drain_cnt <- replicateM(mkReg(0));
   Reg#(Bit#(BurstLenSize)) inj_ctrl <- mkReg(0);
   FIFO#(Tuple2#(Bit#(TAdd#(1,logk)),Bit#(2))) loadIdxs <- mkSizedFIFO(32);
   FIFO#(Tuple2#(Bit#(TAdd#(1,logk)),Bit#(2))) inFlight <- mkSizedFIFO(4);
   FunnelPipe#(1, k, Tuple3#(Bit#(2),Bit#(w),Bool),bpc) data_in_funnel <- mkFunnelPipesPipelined(map(toPipeOut,data_in));
   Reg#(Bit#(BurstLenSize)) drainCnt <- mkReg(0);
   FIFOF#(Tuple2#(Bit#(TLog#(k)),Bit#(w))) exit_data <- mkFIFOF;
   FIFO#(Bit#(logk)) drainRename <- mkFIFO;

   Reg#(Bit#(32)) cycle <- mkReg(0);
   Reg#(Bit#(32)) last_entry <- mkReg(0);

   rule cyc;
      cycle <= cycle+1;
   endrule

   function PipeIn#(Bit#(w)) enter_data(FIFOF#(Tuple3#(Bit#(2), Bit#(w), Bool)) f, Integer i) =
      (interface PipeIn;
   	  method Bool notFull = f.notFull;
   	  method Action enq(Bit#(w) v) if (tpl_1(loadIdxs.first) == fromInteger(i));
	     last_entry <= cycle;
	     match {.old_name, .new_name} = loadIdxs.first;
	     let first = inj_ctrl == 0;
	     let cnt = first ? burst_len[i] : inj_ctrl;
	     let new_cnt = cnt-1;
	     let last = new_cnt == 0;
	     inj_ctrl <= new_cnt;
	     if (first)
		inFlight.enq(loadIdxs.first);
	     if (last)
		loadIdxs.deq;
	     f.enq(tuple3(new_name, v, last));
	     //$display("%d enq %d", cycle-last_entry, i);
	  endmethod
       endinterface);
   Vector#(k, PipeIn#(Bit#(w))) data_in_pipes = zipWith(enter_data, data_in, genVector);

   function Reg#(Bit#(BurstLenSize)) check(Reg#(Bit#(BurstLenSize)) r) =
      (interface Reg;
	  method Action _write(Bit#(BurstLenSize) v);
	     if(v > 16) begin
		$display("ERROR mkBurstFunnel: burstLen too large");
		$finish;
	     end
	     r <= v;
	  endmethod
	  method Bit#(BurstLenSize) _read = r._read;
       endinterface);

   rule drain_funnel;
      match{.new_name,.data,.last} = data_in_funnel[0].first;
      data_in_funnel[0].deq;
      complBuff.enq(new_name,tuple2(data,last));
      compCnts[new_name].increment(1);
   endrule

   rule drain_req (compCnts[tpl_2(inFlight.first)].read > 0);
      match {.old_name, .new_name} = inFlight.first;
      let new_drainCnt = drainCnt-1;
      if (drainCnt == 0) begin
	 new_drainCnt = burst_len[old_name]-1;
	 drainRename.enq(truncate(old_name));
      end
      if (new_drainCnt == 0) begin
	 inFlight.deq;
      end
      complBuff.first_req(new_name);
      drainCnt <= new_drainCnt;
      compCnts[new_name].decrement(1);
      complBuff.deq(new_name);
   endrule

   rule drain_resp;
      match {.data,.last} <- complBuff.first_resp;
      if (last)
	 drainRename.deq;
      exit_data.enq(tuple2(drainRename.first,data));
   endrule

   method Action loadIdx(Bit#(logk) idx);
      loadIdxs.enq(tuple2(extend(idx),nameGen));
      nameGen <= nameGen+1;
   endmethod
   interface burstLen = map(check,burst_len);
   interface dataIn = data_in_pipes;
   interface PipeOut dataOut = toPipeOut(exit_data);
endmodule

module mkMemwriteEngineBuff#(Integer bufferSizeBytes)(MemwriteEngineV#(dataWidth, cmdQDepth, numServers))
   provisos ( Div#(dataWidth,8,dataWidthBytes)
	     ,Mul#(dataWidthBytes,8,dataWidth)
	     ,Log#(dataWidthBytes,beatShift)
	     ,Log#(cmdQDepth,logCmdQDepth)
	     ,Mul#(cmdQDepth,numServers,cmdBuffSz)
	     ,Log#(cmdBuffSz, cmdBuffAddrSz)
	     ,Log#(numServers, serverIdxSz)
	     ,Add#(1,logCmdQDepth, outCntSz)
	     ,Add#(1, c__, numServers)
	     ,Add#(b__, TLog#(numServers), cmdBuffAddrSz)
	     ,Add#(e__, TLog#(numServers), TAdd#(1, cmdBuffAddrSz))
	     ,Add#(a__, serverIdxSz, cmdBuffAddrSz)
	     ,Min#(2,TLog#(numServers),bpc)
	     ,FunnelPipesPipelined#(1,numServers,Tuple2#(Bit#(serverIdxSz),MemengineCmd),bpc)
	     ,FunnelPipesPipelined#(1,numServers,Tuple2#(Bit#(dataWidth),Bool),bpc)
	     ,FunnelPipesPipelined#(1, numServers, Tuple3#(Bit#(2),Bit#(dataWidth),Bool), TMin#(2, serverIdxSz))
	     ,Add#(1, d__, dataWidth)
	     ,FunnelPipesPipelined#(1, numServers, Tuple3#(Bit#(serverIdxSz),Bit#(dataWidth), Bool), TMin#(2, serverIdxSz))
	     ,Add#(f__, TLog#(numServers), TAdd#(1, serverIdxSz))
	     ,Add#(g__, serverIdxSz, 6)
	     );

   Integer bufferSizeBeats = bufferSizeBytes/valueOf(dataWidthBytes);
   Vector#(numServers, Reg#(Bit#(outCntSz)))     outs1 <- replicateM(mkReg(0));
   Vector#(numServers, Reg#(Bit#(outCntSz)))     outs0 <- replicateM(mkReg(0));
   Vector#(numServers, ConfigCounter#(16))           buffCap <- replicateM(mkConfigCounter(0));
   UGBramFifos#(numServers,cmdQDepth,MemengineCmd) cmdBuf <- mkUGBramFifos;

   Reg#(Bool) load_in_progress <- mkReg(False);
   FIFO#(Tuple3#(MemengineCmd,Bool,Bool))         loadf_b <- mkSizedFIFO(1);
   FIFO#(Tuple2#(Bit#(serverIdxSz),MemengineCmd)) loadf_c <- mkSizedFIFO(1);
   FIFO#(Tuple3#(Bit#(8),Bit#(MemTagSize),Bool))    workf <- mkSizedFIFO(32); // is this the right size?
   FIFO#(Tuple2#(Bit#(serverIdxSz),Bool))           donef <- mkSizedFIFO(32); // is this the right size?

   Vector#(numServers, FIFO#(Bool))              outfs <- replicateM(mkSizedFIFO(1));
   Vector#(numServers, FIFOF#(Tuple2#(Bit#(serverIdxSz), MemengineCmd))) cmds_in <- replicateM(mkSizedFIFOF(1));
   FunnelPipe#(1, numServers, Tuple2#(Bit#(serverIdxSz), MemengineCmd),bpc) cmds_in_funnel <- mkFunnelPipesPipelined(map(toPipeOut,cmds_in));
   Vector#(numServers, FIFOF#(Bit#(dataWidth)))  write_data_buffs <- replicateM(mkSizedBRAMFIFOF(bufferSizeBeats));
   Vector#(numServers, PipeOut#(Bit#(dataWidth))) foo = map(toPipeOut, write_data_buffs);
   BurstFunnel#(numServers,dataWidth) write_data_funnel <- mkBurstFunnel(bufferSizeBeats);
   zipWithM(mkConnection, foo, write_data_funnel.dataIn);

   Reg#(Bit#(8))                    respCnt <- mkReg(0);
   Reg#(Bit#(TAdd#(1,serverIdxSz))) loadIdx <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));
   let cmd_q_depth = fromInteger(valueOf(cmdQDepth));

   function Action incr_loadIdx =
      (action
       if(loadIdx+1 >= fromInteger(valueOf(numServers)))
	  loadIdx <= 0;
       else
	  loadIdx <= loadIdx+1;
       endaction);

   rule store_cmd;
      match {.idx, .cmd} <- toGet(cmds_in_funnel[0]).get;
      outs1[idx] <= outs1[idx]+1;
      cmdBuf.enq(idx,cmd);
      //$display("store_cmd %d", idx);
   endrule

   rule load_ctxt_a (!load_in_progress);
      if (outs1[loadIdx] > 0) begin
	 load_in_progress <= True;
	 cmdBuf.first_req(truncate(loadIdx));
      end
      else begin
	 incr_loadIdx;
      end
   endrule

   rule load_ctxt_b;
      let cmd <- cmdBuf.first_resp;
      let cond0 = buffCap[loadIdx].read() >= unpack(extend(cmd.burstLen>>beat_shift));
      let cond1 = cmd.len <= extend(cmd.burstLen);
      loadf_b.enq(tuple3(cmd,cond0,cond1));
   endrule

   rule load_ctxt_c;
      load_in_progress <= False;
      incr_loadIdx;
      match {.cmd,.cond0,.cond1} <- toGet(loadf_b).get;
      if  (cond0) begin
	 //$display("load_ctxt_b %h %d", cmd.base, idx);
	 let x = cmd.burstLen;
	 if (cmd.len < extend(cmd.burstLen))
	    x = truncate(cmd.len);
	 buffCap[loadIdx].decrement(unpack(extend(x>>beat_shift)));
	 loadf_c.enq(tuple2(truncate(loadIdx),cmd));
	 write_data_funnel.loadIdx(truncate(loadIdx));
	 if (cond1) begin
	    outs1[loadIdx] <= outs1[loadIdx]-1;
	    cmdBuf.deq(truncate(loadIdx));
	 end
	 else begin
	    let new_cmd = MemengineCmd{sglId:cmd.sglId, base:cmd.base+extend(cmd.burstLen), burstLen:cmd.burstLen, len:cmd.len-extend(cmd.burstLen)};
	    cmdBuf.upd_head(truncate(loadIdx),new_cmd);
	 end
      end
   endrule

   function PipeIn#(Bit#(w)) check_in(FIFOF#(Bit#(w)) f, Integer i) =
      (interface PipeIn;
   	  method Bool notFull = f.notFull;
   	  method Action enq(Bit#(w) v);
	     f.enq(v);
	     buffCap[i].increment(1);
	     //$display("check_in %d", i);
	     // if(i==2)
	     // 	for(Integer j = 0; j < valueOf(w); j=j+32) begin
	     // 	   Bit#(32) xx = v[j+31:j];
	     // 	   $display("%h", xx);
	     // 	end
	  endmethod
       endinterface);

   function MemwriteServer#(dataWidth) toMemwriteServer(Server#(MemengineCmd,Bool) cs, PipeIn#(Bit#(dataWidth)) p) =
      (interface MemwriteServer;
	  interface cmdServer = cs;
	  interface dataPipe  = p;
       endinterface);

   Vector#(numServers, Server#(MemengineCmd,Bool)) rs;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      rs[i] = (interface Server#(MemengineCmd,Bool);
		  interface Put request;
		     method Action put(MemengineCmd c) if (outs0[i] < cmd_q_depth);
			Bit#(32) bsb = fromInteger(bufferSizeBytes);
`ifdef BSIM
			Bit#(32) dw = fromInteger(valueOf(dataWidthBytes));
			Bit#(32) bl = extend(c.burstLen);
			// this is because bsc lifts the divide operation (below)
			// and on startup the simulator gets a floating-point exception
	  		if (bl ==0)
			   bl = 1;
			let mdw0 = ((c.len)/bl)*bl != c.len;
			let mdw1 = ((c.len)/dw)*dw != c.len;
			let bbl = extend(c.burstLen) > bsb;
			if(bbl || mdw0 || mdw1 || c.len == 0) begin
			   if (bbl)
			      $display("XXXXXXXXXX mkMemwriteEngineBuff::unsupported burstLen %d %d", bsb, c.burstLen);
			   if (mdw0 || mdw1 || c.len == 0)
			      $display("XXXXXXXXXX mkMemwriteEngineBuff::unsupported len %h mdw0=%d mdw1=%d", c.len, mdw0, mdw1);
			end
			else begin
`endif
			   outs0[i] <= outs0[i]+1;
			   cmds_in[i].enq(tuple2(fromInteger(i),c));
			   write_data_funnel.burstLen[i] <= c.burstLen >> beat_shift;
			   //$display("(%d) %h %h %h", i, c.base, c.len, c.burstLen);
`ifdef BSIM
			end
`endif
 		     endmethod
		  endinterface
		  interface Get response;
		     method ActionValue#(Bool) get;
			let rv <- toGet(outfs[i]).get;
	 		outs0[i] <= outs0[i]-1;
			return rv;
		     endmethod
		  endinterface
	       endinterface);
   interface writeServers = rs;
   interface MemWriteClient dmaClient;
      interface Get writeReq;
	 method ActionValue#(MemRequest) get();
	    match {.idx, .cmd} <- toGet(loadf_c).get;
	    Bit#(BurstLenSize) bl = cmd.burstLen;
	    Bool last = False;
	    if (cmd.len <= extend(bl)) begin
	       last = True;
	       bl = truncate(cmd.len);
	    end
	    let new_tag = (cmd.tag << valueOf(serverIdxSz)) | extend(idx);
	    workf.enq(tuple3(truncate(bl>>beat_shift), new_tag, last));
	    //$display("writeReq %d, %h %h %h", idx, cmd.base, bl, last);
	    return MemRequest { sglId: cmd.sglId, offset: cmd.base, burstLen:bl, tag: new_tag};
	 endmethod
      endinterface
      interface Get writeData;
	 method ActionValue#(MemData#(dataWidth)) get;
	    match {.rc, .new_tag, .last} = workf.first;
	    Bit#(serverIdxSz) idx = truncate(new_tag);
	    let new_respCnt = respCnt+1;
	    if (new_respCnt == rc) begin
	       respCnt <= 0;
	       workf.deq;
	       donef.enq(tuple2(idx,last));
	    end
	    else begin
	       respCnt <= new_respCnt;
	    end
	    match {._idx, .wd} <- toGet(write_data_funnel.dataOut).get;
	    if(_idx != idx) begin
	       $display("ERROR mkMemwriteEngineBuf: bursts oo %d %d", idx, _idx);
	       $finish;
	    end
	    // TODO: this last field should be set correctly to mark the end of bursts
	    return MemData{data:wd, tag:new_tag, last:False};
	 endmethod
      endinterface
      interface Put writeDone;
	 method Action put(Bit#(MemTagSize) tag);
	    match {.idx, .last} <- toGet(donef).get;
	    if (last)
	       outfs[idx].enq(True);
	    //$display("writeDone %d %d", idx, last);
	 endmethod
      endinterface
   endinterface
   interface dataPipes = zipWith(check_in, write_data_buffs, genVector);
   interface write_servers = zipWith(toMemwriteServer, rs, zipWith(check_in, write_data_buffs, genVector));
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 FIFOF::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import BRAM::*;
import BRAMFIFO::*;
import Connectable::*;

import ConfigCounter::*;
import ConnectalMemory::*;
import MemTypes::*;
import Pipe::*;
import MemUtils::*;

module mkMemwriteEngine(MemwriteEngineV#(dataWidth, cmdQDepth, numServers))
   provisos( Mul#(TDiv#(dataWidth, 8), 8, dataWidth)
	    ,Add#(1, a__, numServers)
	    ,Add#(b__, TLog#(numServers), TAdd#(1, TLog#(TMul#(cmdQDepth,numServers))))
	    ,Pipe::FunnelPipesPipelined#(1, numServers,Tuple2#(Bit#(TLog#(numServers)), MemTypes::MemengineCmd), TMin#(2,TLog#(numServers)))
	    ,Pipe::FunnelPipesPipelined#(1, numServers,Tuple2#(Bit#(dataWidth),Bool),TMin#(2, TLog#(numServers)))
	    ,Add#(c__, TLog#(numServers), TLog#(TMul#(cmdQDepth, numServers)))
	    ,Add#(1, d__, dataWidth)
	    ,FunnelPipesPipelined#(1, numServers, Tuple3#(Bit#(2),Bit#(dataWidth),Bool), TMin#(2, TLog#(numServers)))
	    ,FunnelPipesPipelined#(1, numServers,Tuple3#(Bit#(TLog#(numServers)), Bit#(dataWidth), Bool), TMin#(2,TLog#(numServers)))
	    ,Add#(e__, TLog#(numServers), 6)
	    );
   let rv <- mkMemwriteEngineBuff(256);
   return rv;
endmodule

interface BurstFunnel#(numeric type k, numeric type w);
   method Action loadIdx(Bit#(TLog#(k)) i);
   interface Vector#(k, PipeIn#(Bit#(w))) dataIn;
   interface Vector#(k, Reg#(Bit#(BurstLenSize))) burstLen;
   interface PipeOut#(Tuple2#(Bit#(TLog#(k)),Bit#(w))) dataOut;
endinterface

module mkBurstFunnel#(Integer maxBurstLen)(BurstFunnel#(k,w))
   provisos( Log#(k,logk)
	    ,Min#(2,logk,bpc)
	    ,FunnelPipesPipelined#(1, k, Tuple3#(Bit#(2),Bit#(w),Bool), bpc)
	    );

   Reg#(Bit#(2)) nameGen <- mkReg(0);
   UGBramFifos#(4,16,Tuple2#(Bit#(w),Bool)) complBuff <- mkUGBramFifos;
   Vector#(4, ConfigCounter#(16)) compCnts <- replicateM(mkConfigCounter(0));
   Vector#(k,FIFOF#(Tuple3#(Bit#(2), Bit#(w), Bool))) data_in <- replicateM(mkFIFOF);
   Vector#(k,Reg#(Bit#(BurstLenSize))) burst_len <- replicateM(mkReg(0));
   Vector#(k,Reg#(Bit#(BurstLenSize))) drain_cnt <- replicateM(mkReg(0));
   Reg#(Bit#(BurstLenSize)) inj_ctrl <- mkReg(0);
   FIFO#(Tuple2#(Bit#(TAdd#(1,logk)),Bit#(2))) loadIdxs <- mkSizedFIFO(32);
   FIFO#(Tuple2#(Bit#(TAdd#(1,logk)),Bit#(2))) inFlight <- mkSizedFIFO(4);
   FunnelPipe#(1, k, Tuple3#(Bit#(2),Bit#(w),Bool),bpc) data_in_funnel <- mkFunnelPipesPipelined(map(toPipeOut,data_in));
   Reg#(Bit#(BurstLenSize)) drainCnt <- mkReg(0);
   FIFOF#(Tuple2#(Bit#(TLog#(k)),Bit#(w))) exit_data <- mkFIFOF;
   FIFO#(Bit#(logk)) drainRename <- mkFIFO;

   Reg#(Bit#(32)) cycle <- mkReg(0);
   Reg#(Bit#(32)) last_entry <- mkReg(0);

   rule cyc;
      cycle <= cycle+1;
   endrule

   function PipeIn#(Bit#(w)) enter_data(FIFOF#(Tuple3#(Bit#(2), Bit#(w), Bool)) f, Integer i) =
      (interface PipeIn;
   	  method Bool notFull = f.notFull;
   	  method Action enq(Bit#(w) v) if (tpl_1(loadIdxs.first) == fromInteger(i));
	     last_entry <= cycle;
	     match {.old_name, .new_name} = loadIdxs.first;
	     let first = inj_ctrl == 0;
	     let cnt = first ? burst_len[i] : inj_ctrl;
	     let new_cnt = cnt-1;
	     let last = new_cnt == 0;
	     inj_ctrl <= new_cnt;
	     if (first)
		inFlight.enq(loadIdxs.first);
	     if (last)
		loadIdxs.deq;
	     f.enq(tuple3(new_name, v, last));
	     //$display("%d enq %d", cycle-last_entry, i);
	  endmethod
       endinterface);
   Vector#(k, PipeIn#(Bit#(w))) data_in_pipes = zipWith(enter_data, data_in, genVector);

   function Reg#(Bit#(BurstLenSize)) check(Reg#(Bit#(BurstLenSize)) r) =
      (interface Reg;
	  method Action _write(Bit#(BurstLenSize) v);
	     if(v > 16) begin
		$display("ERROR mkBurstFunnel: burstLen too large");
		$finish;
	     end
	     r <= v;
	  endmethod
	  method Bit#(BurstLenSize) _read = r._read;
       endinterface);

   rule drain_funnel;
      match{.new_name,.data,.last} = data_in_funnel[0].first;
      data_in_funnel[0].deq;
      complBuff.enq(new_name,tuple2(data,last));
      compCnts[new_name].increment(1);
   endrule

   rule drain_req (compCnts[tpl_2(inFlight.first)].read > 0);
      match {.old_name, .new_name} = inFlight.first;
      let new_drainCnt = drainCnt-1;
      if (drainCnt == 0) begin
	 new_drainCnt = burst_len[old_name]-1;
	 drainRename.enq(truncate(old_name));
      end
      if (new_drainCnt == 0) begin
	 inFlight.deq;
      end
      complBuff.first_req(new_name);
      drainCnt <= new_drainCnt;
      compCnts[new_name].decrement(1);
      complBuff.deq(new_name);
   endrule

   rule drain_resp;
      match {.data,.last} <- complBuff.first_resp;
      if (last)
	 drainRename.deq;
      exit_data.enq(tuple2(drainRename.first,data));
   endrule

   method Action loadIdx(Bit#(logk) idx);
      loadIdxs.enq(tuple2(extend(idx),nameGen));
      nameGen <= nameGen+1;
   endmethod
   interface burstLen = map(check,burst_len);
   interface dataIn = data_in_pipes;
   interface PipeOut dataOut = toPipeOut(exit_data);
endmodule

module mkMemwriteEngineBuff#(Integer bufferSizeBytes)(MemwriteEngineV#(dataWidth, cmdQDepth, numServers))
   provisos ( Div#(dataWidth,8,dataWidthBytes)
	     ,Mul#(dataWidthBytes,8,dataWidth)
	     ,Log#(dataWidthBytes,beatShift)
	     ,Log#(cmdQDepth,logCmdQDepth)
	     ,Mul#(cmdQDepth,numServers,cmdBuffSz)
	     ,Log#(cmdBuffSz, cmdBuffAddrSz)
	     ,Log#(numServers, serverIdxSz)
	     ,Add#(1,logCmdQDepth, outCntSz)
	     ,Add#(1, c__, numServers)
	     ,Add#(b__, TLog#(numServers), cmdBuffAddrSz)
	     ,Add#(e__, TLog#(numServers), TAdd#(1, cmdBuffAddrSz))
	     ,Add#(a__, serverIdxSz, cmdBuffAddrSz)
	     ,Min#(2,TLog#(numServers),bpc)
	     ,FunnelPipesPipelined#(1,numServers,Tuple2#(Bit#(serverIdxSz),MemengineCmd),bpc)
	     ,FunnelPipesPipelined#(1,numServers,Tuple2#(Bit#(dataWidth),Bool),bpc)
	     ,FunnelPipesPipelined#(1, numServers, Tuple3#(Bit#(2),Bit#(dataWidth),Bool), TMin#(2, serverIdxSz))
	     ,Add#(1, d__, dataWidth)
	     ,FunnelPipesPipelined#(1, numServers, Tuple3#(Bit#(serverIdxSz),Bit#(dataWidth), Bool), TMin#(2, serverIdxSz))
	     ,Add#(f__, TLog#(numServers), TAdd#(1, serverIdxSz))
	     ,Add#(g__, serverIdxSz, 6)
	     );

   Integer bufferSizeBeats = bufferSizeBytes/valueOf(dataWidthBytes);
   Vector#(numServers, Reg#(Bit#(outCntSz)))     outs1 <- replicateM(mkReg(0));
   Vector#(numServers, Reg#(Bit#(outCntSz)))     outs0 <- replicateM(mkReg(0));
   Vector#(numServers, ConfigCounter#(16))           buffCap <- replicateM(mkConfigCounter(0));
   UGBramFifos#(numServers,cmdQDepth,MemengineCmd) cmdBuf <- mkUGBramFifos;

   Reg#(Bool) load_in_progress <- mkReg(False);
   FIFO#(Tuple3#(MemengineCmd,Bool,Bool))         loadf_b <- mkSizedFIFO(1);
   FIFO#(Tuple2#(Bit#(serverIdxSz),MemengineCmd)) loadf_c <- mkSizedFIFO(1);
   FIFO#(Tuple3#(Bit#(8),Bit#(MemTagSize),Bool))    workf <- mkSizedFIFO(32); // is this the right size?
   FIFO#(Tuple2#(Bit#(serverIdxSz),Bool))           donef <- mkSizedFIFO(32); // is this the right size?

   Vector#(numServers, FIFO#(Bool))              outfs <- replicateM(mkSizedFIFO(1));
   Vector#(numServers, FIFOF#(Tuple2#(Bit#(serverIdxSz), MemengineCmd))) cmds_in <- replicateM(mkSizedFIFOF(1));
   FunnelPipe#(1, numServers, Tuple2#(Bit#(serverIdxSz), MemengineCmd),bpc) cmds_in_funnel <- mkFunnelPipesPipelined(map(toPipeOut,cmds_in));
   Vector#(numServers, FIFOF#(Bit#(dataWidth)))  write_data_buffs <- replicateM(mkSizedBRAMFIFOF(bufferSizeBeats));
   Vector#(numServers, PipeOut#(Bit#(dataWidth))) foo = map(toPipeOut, write_data_buffs);
   BurstFunnel#(numServers,dataWidth) write_data_funnel <- mkBurstFunnel(bufferSizeBeats);
   zipWithM(mkConnection, foo, write_data_funnel.dataIn);

   Reg#(Bit#(8))                    respCnt <- mkReg(0);
   Reg#(Bit#(TAdd#(1,serverIdxSz))) loadIdx <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));
   let cmd_q_depth = fromInteger(valueOf(cmdQDepth));

   function Action incr_loadIdx =
      (action
       if(loadIdx+1 >= fromInteger(valueOf(numServers)))
	  loadIdx <= 0;
       else
	  loadIdx <= loadIdx+1;
       endaction);

   rule store_cmd;
      match {.idx, .cmd} <- toGet(cmds_in_funnel[0]).get;
      outs1[idx] <= outs1[idx]+1;
      cmdBuf.enq(idx,cmd);
      //$display("store_cmd %d", idx);
   endrule

   rule load_ctxt_a (!load_in_progress);
      if (outs1[loadIdx] > 0) begin
	 load_in_progress <= True;
	 cmdBuf.first_req(truncate(loadIdx));
      end
      else begin
	 incr_loadIdx;
      end
   endrule

   rule load_ctxt_b;
      let cmd <- cmdBuf.first_resp;
      let cond0 = buffCap[loadIdx].read() >= unpack(extend(cmd.burstLen>>beat_shift));
      let cond1 = cmd.len <= extend(cmd.burstLen);
      loadf_b.enq(tuple3(cmd,cond0,cond1));
   endrule

   rule load_ctxt_c;
      load_in_progress <= False;
      incr_loadIdx;
      match {.cmd,.cond0,.cond1} <- toGet(loadf_b).get;
      if  (cond0) begin
	 //$display("load_ctxt_b %h %d", cmd.base, idx);
	 let x = cmd.burstLen;
	 if (cmd.len < extend(cmd.burstLen))
	    x = truncate(cmd.len);
	 buffCap[loadIdx].decrement(unpack(extend(x>>beat_shift)));
	 loadf_c.enq(tuple2(truncate(loadIdx),cmd));
	 write_data_funnel.loadIdx(truncate(loadIdx));
	 if (cond1) begin
	    outs1[loadIdx] <= outs1[loadIdx]-1;
	    cmdBuf.deq(truncate(loadIdx));
	 end
	 else begin
	    let new_cmd = MemengineCmd{sglId:cmd.sglId, base:cmd.base+extend(cmd.burstLen), burstLen:cmd.burstLen, len:cmd.len-extend(cmd.burstLen)};
	    cmdBuf.upd_head(truncate(loadIdx),new_cmd);
	 end
      end
   endrule

   function PipeIn#(Bit#(w)) check_in(FIFOF#(Bit#(w)) f, Integer i) =
      (interface PipeIn;
   	  method Bool notFull = f.notFull;
   	  method Action enq(Bit#(w) v);
	     f.enq(v);
	     buffCap[i].increment(1);
	     //$display("check_in %d", i);
	     // if(i==2)
	     // 	for(Integer j = 0; j < valueOf(w); j=j+32) begin
	     // 	   Bit#(32) xx = v[j+31:j];
	     // 	   $display("%h", xx);
	     // 	end
	  endmethod
       endinterface);

   function MemwriteServer#(dataWidth) toMemwriteServer(Server#(MemengineCmd,Bool) cs, PipeIn#(Bit#(dataWidth)) p) =
      (interface MemwriteServer;
	  interface cmdServer = cs;
	  interface dataPipe  = p;
       endinterface);

   Vector#(numServers, Server#(MemengineCmd,Bool)) rs;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      rs[i] = (interface Server#(MemengineCmd,Bool);
		  interface Put request;
		     method Action put(MemengineCmd c) if (outs0[i] < cmd_q_depth);
			Bit#(32) bsb = fromInteger(bufferSizeBytes);
`ifdef BSIM
			Bit#(32) dw = fromInteger(valueOf(dataWidthBytes));
			Bit#(32) bl = extend(c.burstLen);
			// this is because bsc lifts the divide operation (below)
			// and on startup the simulator gets a floating-point exception
	  		if (bl ==0)
			   bl = 1;
			let mdw0 = ((c.len)/bl)*bl != c.len;
			let mdw1 = ((c.len)/dw)*dw != c.len;
			let bbl = extend(c.burstLen) > bsb;
			if(bbl || mdw0 || mdw1 || c.len == 0) begin
			   if (bbl)
			      $display("XXXXXXXXXX mkMemwriteEngineBuff::unsupported burstLen %d %d", bsb, c.burstLen);
			   if (mdw0 || mdw1 || c.len == 0)
			      $display("XXXXXXXXXX mkMemwriteEngineBuff::unsupported len %h", c.len);
			end
			else begin
`endif
			   outs0[i] <= outs0[i]+1;
			   cmds_in[i].enq(tuple2(fromInteger(i),c));
			   write_data_funnel.burstLen[i] <= c.burstLen >> beat_shift;
			   //$display("(%d) %h %h %h", i, c.base, c.len, c.burstLen);
`ifdef BSIM
			end
`endif
 		     endmethod
		  endinterface
		  interface Get response;
		     method ActionValue#(Bool) get;
			let rv <- toGet(outfs[i]).get;
	 		outs0[i] <= outs0[i]-1;
			return rv;
		     endmethod
		  endinterface
	       endinterface);
   interface writeServers = rs;
   interface MemWriteClient dmaClient;
      interface Get writeReq;
	 method ActionValue#(MemRequest) get();
	    match {.idx, .cmd} <- toGet(loadf_c).get;
	    Bit#(BurstLenSize) bl = cmd.burstLen;
	    Bool last = False;
	    if (cmd.len <= extend(bl)) begin
	       last = True;
	       bl = truncate(cmd.len);
	    end
	    let new_tag = (cmd.tag << valueOf(serverIdxSz)) | extend(idx);
	    workf.enq(tuple3(truncate(bl>>beat_shift), new_tag, last));
	    //$display("writeReq %d, %h %h %h", idx, cmd.base, bl, last);
	    return MemRequest { sglId: cmd.sglId, offset: cmd.base, burstLen:bl, tag: new_tag};
	 endmethod
      endinterface
      interface Get writeData;
	 method ActionValue#(MemData#(dataWidth)) get;
	    match {.rc, .new_tag, .last} = workf.first;
	    Bit#(serverIdxSz) idx = truncate(new_tag);
	    let new_respCnt = respCnt+1;
	    if (new_respCnt == rc) begin
	       respCnt <= 0;
	       workf.deq;
	       donef.enq(tuple2(idx,last));
	    end
	    else begin
	       respCnt <= new_respCnt;
	    end
	    match {._idx, .wd} <- toGet(write_data_funnel.dataOut).get;
	    if(_idx != idx) begin
	       $display("ERROR mkMemwriteEngineBuf: bursts oo %d %d", idx, _idx);
	       $finish;
	    end
	    // TODO: this last field should be set correctly to mark the end of bursts
	    return MemData{data:wd, tag:new_tag, last:False};
	 endmethod
      endinterface
      interface Put writeDone;
	 method Action put(Bit#(MemTagSize) tag);
	    match {.idx, .last} <- toGet(donef).get;
	    if (last)
	       outfs[idx].enq(True);
	    //$display("writeDone %d %d", idx, last);
	 endmethod
      endinterface
   endinterface
   interface dataPipes = zipWith(check_in, write_data_buffs, genVector);
   interface write_servers = zipWith(toMemwriteServer, rs, zipWith(check_in, write_data_buffs, genVector));
endmodule


updated isActiveLine guard

updated isActiveLine guard

// Copyright (c) 2013 Nokia, Inc.
// 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 Clocks::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import SyncBits::*;
import YUV::*;

`ifdef ZC706
typedef 24 HdmiBits;
`else
typedef 16 HdmiBits;
`endif

interface HDMI#(type pixelType);
    method Bit#(1) hdmi_vsync;
    method Bit#(1) hdmi_hsync;
    method Bit#(1) hdmi_de;
    method pixelType hdmi_data;
    interface Clock hdmi_clock_if;
    interface Reset deleteme_unused_reset;
endinterface

interface HdmiInternalRequest;
    method Action setTestPattern(Bit#(1) v);
    method Action setPatternColor(Bit#(32) v);
    method Action setHsyncWidth(Bit#(12) hsyncWidth);
    method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max, Bit#(12) mid);
    method Action setVsyncWidth(Bit#(11) vsyncWidth);
    method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max, Bit#(11) mid);
    method Action setNumberOfLines(Bit#(11) lines);
    method Action setNumberOfPixels(Bit#(12) pixels);
    method Action waitForVsync(Bit#(32) unused);
endinterface
interface HdmiInternalIndication;
    method Action vsync(Bit#(64) v, Bit#(32) vs);
endinterface
interface HdmiInternalStatus;
    method Bit#(11) getNumberOfLines();
    method Bit#(12) getNumberOfPixels();
    method Bool dataEnable();
endinterface

interface HdmiGenerator#(type pixelType);
    interface HdmiInternalRequest control;
    interface HdmiInternalStatus  status;
    interface Get#(VideoData#(pixelType)) rgb888;
    interface Put#(Bit#(32)) request;
endinterface

module mkHdmiGenerator#(Clock axi_clock, Reset axi_reset,
   SyncPulseIfc vsyncPulse, HdmiInternalIndication indication)(HdmiGenerator#(Rgb888));
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    // 1920 * 1080
    Reg#(Bit#(12)) hsyncWidth <- mkSyncReg(44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMinimum <- mkSyncReg(192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMaximum <- mkSyncReg(1920 + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) pixelMidpoint <- mkSyncReg((1920/2) + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) vsyncWidth <- mkSyncReg(5, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMinimum <- mkSyncReg(41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMaximum <- mkSyncReg(1080+41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineMidpoint <- mkSyncReg((1080/2) + 41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) numberOfLines <- mkSyncReg(1080 + 45, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) numberOfPixels <- mkSyncReg(1920 + 192 + 44 + 44, axi_clock, axi_reset, defaultClock);
    Vector#(4, Reg#(Bit#(24))) patternRegs <- replicateM(mkSyncReg(24'h00FFFFFF, axi_clock, axi_reset, defaultClock));
    Reg#(Bit#(1)) shadowTestPatternEnabled <- mkSyncReg(1, axi_clock, axi_reset, defaultClock);
    Reg#(Bool) waitingForVsync <- mkSyncReg(False, axi_clock, axi_reset, defaultClock);
    SyncPulseIfc vsyncCountPulse <- mkSyncHandshake(defaultClock, defaultReset, axi_clock);
    SyncPulseIfc sendVsyncIndication <- mkSyncHandshake(defaultClock, defaultReset, axi_clock);

    Reg#(Bit#(11)) lineCount <- mkReg(0);
    Reg#(Bit#(12)) pixelCount <- mkReg(0);
    Reg#(Bit#(1)) patternIndex0 <- mkReg(0);
    Reg#(Bit#(1)) patternIndex1 <- mkReg(0);
    Reg#(Bit#(1)) testPatternEnabled <- mkReg(1);
    Reg#(Bit#(24)) pixelData <- mkReg(24'hFF00FF);

    Reg#(VideoData#(Rgb888)) rgb888StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    Reg#(Bit#(32)) underflowCount <- mkReg(0);
    Reg#(Bit#(32)) underflowCountAxi <- mkSyncReg(0, defaultClock, defaultReset, axi_clock);
    Reg#(Bit#(32)) counter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) vsyncCounter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsed <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsedVsync <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);

    rule axicyclecount;
       counter <= counter + 1;
    endrule

    rule vsyncCount if (vsyncCountPulse.pulse());
       vsyncCounter <= vsyncCounter+1;
    endrule
    rule vsyncReceived if (sendVsyncIndication.pulse());
       elapsed <= counter;
       elapsedVsync <= vsyncCounter;
       indication.vsync(extend(counter - elapsed), extend(vsyncCounter - elapsedVsync));
       waitingForVsync <= False;
    endrule

    rule init_pattern;
        patternRegs[1] <= 24'h00FF0000; // blue
        patternRegs[2] <= 24'h0000FF00; // green
        patternRegs[3] <= 24'h000000FF; // red
        //patternRegs[1] <= 32'h80ff80ff; // yuv422 white
        //patternRegs[2] <= 32'h2c961596; // yuv422 green
        //patternRegs[3] <= 32'hff1d6b1d; // yuv422 red
    endrule

    rule inc_counters;
        if (lineCount == 0 && pixelCount == 0) begin
	    vsyncCountPulse.send();
            vsyncPulse.send();
            if (waitingForVsync) begin
	       sendVsyncIndication.send();
	    end
            testPatternEnabled <= shadowTestPatternEnabled;
        end
        if (pixelCount == numberOfPixels-1) begin
           pixelCount <= 0;
           patternIndex0 <= 0;
           if (lineCount == numberOfLines-1) begin
               lineCount <= 0;
               patternIndex1 <= 0;
           end
           else begin
               lineCount <= lineCount+1;
               if (lineCount >= lineMidpoint)
                   patternIndex1 <= 1;
           end
        end
        else begin
           pixelCount <= pixelCount + 1;
           if (pixelCount >= pixelMidpoint)
               patternIndex0 <= 1;
        end
    endrule

    let isActiveLine = (lineCount >= deLineCountMinimum && lineCount < deLineCountMaximum);
    let dataEnable = (pixelCount >= dePixelCountMinimum && pixelCount < dePixelCountMaximum && isActiveLine);
    rule output_data_rule;
        rgb888StageReg <= VideoData {de: pack(dataEnable),
	     vsync: pack(lineCount < vsyncWidth), hsync: pack(pixelCount < hsyncWidth), pixel: unpack(pixelData) };
    endrule

    rule testpattern_rule if (testPatternEnabled != 0);
       pixelData <= patternRegs[{patternIndex1, patternIndex0}];
    endrule

    interface Put request;
        method Action put(Bit#(32) v) if (testPatternEnabled == 0 && dataEnable);
	   pixelData <= v[23:0];
        endmethod
    endinterface: request

    interface HdmiInternalStatus status;
	method Bit#(11) getNumberOfLines();
	   return numberOfLines;
	endmethod
	method Bit#(12) getNumberOfPixels();
	   return numberOfPixels;
	endmethod
        method Bool dataEnable();
            return dataEnable;
        endmethod
    endinterface
    interface HdmiInternalRequest control;
        method Action setPatternColor(Bit#(32) v);
            patternRegs[0] <= v[23:0];
        endmethod
        method Action setTestPattern(Bit#(1) v);
            shadowTestPatternEnabled <= v;
        endmethod
        method Action setHsyncWidth(Bit#(12) width);
            hsyncWidth <= width;
        endmethod
        method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max, Bit#(12) mid);
            dePixelCountMinimum <= min;
            dePixelCountMaximum <= max;
            pixelMidpoint <= mid;
        endmethod
        method Action setVsyncWidth(Bit#(11) width);
            vsyncWidth <= width;
        endmethod
        method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max, Bit#(11) mid);
            deLineCountMinimum <= min;
            deLineCountMaximum <= max;
            lineMidpoint <= mid;
        endmethod
        method Action setNumberOfLines(Bit#(11) lines);
            numberOfLines <= lines;
        endmethod
        method Action setNumberOfPixels(Bit#(12) pixels);
            numberOfPixels <= pixels;
        endmethod
        method Action waitForVsync(Bit#(32) unused);
            waitingForVsync <= True;
        endmethod
    endinterface
   interface Get rgb888;
      method ActionValue#(VideoData#(Rgb888)) get();
	 return rgb888StageReg;
      endmethod
   endinterface
endmodule

module mkHDMI#(Get#(VideoData#(pixelType)) videoInput)(HDMI#(Bit#(pixelsz)))
   provisos (Bits#(VideoData#(pixelType), a__), Bits#(pixelType,pixelsz));
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   Wire#(VideoData#(pixelType)) video <- mkDWire(unpack(0));
   rule getvideo;
      let v <- videoInput.get();
      video <= v;
   endrule

   method Bit#(1) hdmi_vsync;
      return video.vsync;
   endmethod
   method Bit#(1) hdmi_hsync;
      return video.hsync;
   endmethod
   method Bit#(1) hdmi_de;
      return video.de;
   endmethod
   method Bit#(pixelsz) hdmi_data;
      return pack(video.pixel);
   endmethod
   interface hdmi_clock_if = defaultClock;
   interface deleteme_unused_reset = defaultReset;
endmodule

interface Rgb888ToYyuv;
   interface Put#(VideoData#(Rgb888)) rgb888;
   interface Get#(VideoData#(Yyuv)) yyuv;
endinterface

(* synthesize *)
module mkRgb888ToYyuv(Rgb888ToYyuv);
    Reg#(VideoData#(Rgb888)) rgb888StageReg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444Intermediates)) yuv444IntermediatesStageReg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444)) yuv444StageReg <- mkReg(unpack(0));
    Reg#(VideoData#(Yyuv)) yuv422StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    rule yuv444int_rule;
        let previous = rgb888StageReg;
        let pixel = previous.pixel;
        yuv444IntermediatesStageReg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: (previous.de != 0) ? rgbToYuvIntermediates(pixel) : unpack(0)
        };
    endrule

    rule yuv444_rule;
        let previous = yuv444IntermediatesStageReg;
        yuv444StageReg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
	    pixel: (previous.de != 0) ? yuvIntermediatesToYuv444(previous.pixel) : unpack(0)
        };
    endrule

    rule yuv422_rule;
        let previous = yuv444StageReg;
        if (previous.de != 0)
            evenOddPixelReg <= !evenOddPixelReg;
        Yyuv data = Yyuv { uv: evenOddPixelReg ? previous.pixel.u : previous.pixel.v,
                           yy: previous.pixel.y };
        yuv422StageReg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: data
        };
    endrule

   interface Put rgb888;
      method Action put(VideoData#(Rgb888) v);
	 rgb888StageReg <= v;
      endmethod
   endinterface
   interface Get yyuv;
      method ActionValue#(VideoData#(Yyuv)) get();
	 return yuv422StageReg;
      endmethod
   endinterface
endmodule

// Copyright (c) 2013 Nokia, Inc.
// 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 Clocks::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import SyncBits::*;
import YUV::*;

`ifdef ZC706
typedef 24 HdmiBits;
`else
typedef 16 HdmiBits;
`endif

interface HDMI#(type pixelType);
    method Bit#(1) hdmi_vsync;
    method Bit#(1) hdmi_hsync;
    method Bit#(1) hdmi_de;
    method pixelType hdmi_data;
    interface Clock hdmi_clock_if;
    interface Reset deleteme_unused_reset;
endinterface

interface HdmiInternalRequest;
    method Action setTestPattern(Bit#(1) v);
    method Action setPatternColor(Bit#(32) v);
    method Action setHsyncWidth(Bit#(12) hsyncWidth);
    method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max, Bit#(12) mid);
    method Action setVsyncWidth(Bit#(11) vsyncWidth);
    method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max, Bit#(11) mid);
    method Action setNumberOfLines(Bit#(11) lines);
    method Action setNumberOfPixels(Bit#(12) pixels);
    method Action waitForVsync(Bit#(32) unused);
endinterface
interface HdmiInternalIndication;
    method Action vsync(Bit#(64) v, Bit#(32) vs);
endinterface
interface HdmiInternalStatus;
    method Bit#(11) getNumberOfLines();
    method Bit#(12) getNumberOfPixels();
    method Bool dataEnable();
endinterface

interface HdmiGenerator#(type pixelType);
    interface HdmiInternalRequest control;
    interface HdmiInternalStatus  status;
    interface Get#(VideoData#(pixelType)) rgb888;
    interface Put#(Bit#(32)) request;
endinterface

module mkHdmiGenerator#(Clock axi_clock, Reset axi_reset,
   SyncPulseIfc vsyncPulse, HdmiInternalIndication indication)(HdmiGenerator#(Rgb888));
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    // 1920 * 1080
    Reg#(Bit#(12)) hsyncWidth <- mkSyncReg(44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMinimum <- mkSyncReg(192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelCountMaximum <- mkSyncReg(1920 + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) pixelMidpoint <- mkSyncReg((1920/2) + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) vsyncWidth <- mkSyncReg(5, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMinimum <- mkSyncReg(41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineCountMaximum <- mkSyncReg(1080+41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineMidpoint <- mkSyncReg((1080/2) + 41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) numberOfLines <- mkSyncReg(1080 + 45, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) numberOfPixels <- mkSyncReg(1920 + 192 + 44 + 44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineCount <- mkReg(0);
    Reg#(Bit#(12)) pixelCount <- mkReg(0);
    Vector#(4, Reg#(Bit#(24))) patternRegs <- replicateM(mkSyncReg(24'h00FFFFFF, axi_clock, axi_reset, defaultClock));
    Reg#(Bit#(1)) patternIndex0 <- mkReg(0);
    Reg#(Bit#(1)) patternIndex1 <- mkReg(0);
    Reg#(Bit#(1)) shadowTestPatternEnabled <- mkSyncReg(1, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(1)) testPatternEnabled <- mkReg(1);
    Reg#(Bool) waitingForVsync <- mkSyncReg(False, axi_clock, axi_reset, defaultClock);
    SyncPulseIfc vsyncCountPulse <- mkSyncHandshake(defaultClock, defaultReset, axi_clock);
    SyncPulseIfc sendVsyncIndication <- mkSyncHandshake(defaultClock, defaultReset, axi_clock);
    Reg#(Bit#(24)) pixelData <- mkReg(24'hFF00FF);
    FIFOF#(Bit#(24)) pixelFifo <- mkLFIFOF();

    Reg#(VideoData#(Rgb888)) rgb888StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    Reg#(Bit#(32)) underflowCount <- mkReg(0);
    Reg#(Bit#(32)) underflowCountAxi <- mkSyncReg(0, defaultClock, defaultReset, axi_clock);
    Reg#(Bit#(32)) counter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) vsyncCounter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsed <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsedVsync <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    rule axicyclecount;
       counter <= counter + 1;
    endrule

    rule vsyncCount if (vsyncCountPulse.pulse());
       vsyncCounter <= vsyncCounter+1;
    endrule
    rule vsyncReceived if (sendVsyncIndication.pulse());
       elapsed <= counter;
       elapsedVsync <= vsyncCounter;
       indication.vsync(extend(counter - elapsed), extend(vsyncCounter - elapsedVsync));
       waitingForVsync <= False;
    endrule

    rule init_pattern;
        patternRegs[1] <= 24'h00FF0000; // blue
        patternRegs[2] <= 24'h0000FF00; // green
        patternRegs[3] <= 24'h000000FF; // red
        //patternRegs[1] <= 32'h80ff80ff; // yuv422 white
        //patternRegs[2] <= 32'h2c961596; // yuv422 green
        //patternRegs[3] <= 32'hff1d6b1d; // yuv422 red
    endrule

    rule inc_counters;
        if (lineCount == 0 && pixelCount == 0) begin
	    vsyncCountPulse.send();
            vsyncPulse.send();
            if (waitingForVsync) begin
	       sendVsyncIndication.send();
	    end
            testPatternEnabled <= shadowTestPatternEnabled;
        end
        if (pixelCount == numberOfPixels-1) begin
           pixelCount <= 0;
           patternIndex0 <= 0;
           if (lineCount == numberOfLines-1) begin
               lineCount <= 0;
               patternIndex1 <= 0;
           end
           else begin
               lineCount <= lineCount+1;
               if (lineCount >= lineMidpoint)
                   patternIndex1 <= 1;
           end
        end
        else begin
           pixelCount <= pixelCount + 1;
           if (pixelCount >= pixelMidpoint)
               patternIndex0 <= 1;
        end
    endrule

        let isActiveLine = (lineCount >= deLineCountMinimum && lineCount < deLineCountMaximum);
        let dataEnable = (pixelCount >= dePixelCountMinimum && pixelCount < dePixelCountMaximum && isActiveLine);
    rule output_data_rule;
        let hsync = (pixelCount < hsyncWidth) ? 1 : 0;
        let vsync = (lineCount < vsyncWidth) ? 1 : 0;
       Rgb888 pixel = unpack(0);
       if (dataEnable) begin
	   pixel = unpack(pixelData);
       end
        rgb888StageReg <= VideoData {de: pack(dataEnable),
				     vsync: vsync, hsync: hsync, pixel: pixel };
    endrule

    rule testpattern_rule if (testPatternEnabled != 0);
       pixelData <= patternRegs[{patternIndex1, patternIndex0}];
    endrule

    interface Put request;
        method Action put(Bit#(32) v) if (testPatternEnabled == 0 && dataEnable);
	   pixelData <= v[23:0];
        endmethod
    endinterface: request

    interface HdmiInternalStatus status;
	method Bit#(11) getNumberOfLines();
	   return numberOfLines;
	endmethod
	method Bit#(12) getNumberOfPixels();
	   return numberOfPixels;
	endmethod
   method Bool dataEnable();
        let isActiveLine = (lineCount >= deLineCountMinimum && lineCount < deLineCountMaximum);
      return (pixelCount >= dePixelCountMinimum && pixelCount < dePixelCountMaximum && isActiveLine);
   endmethod

    endinterface
    interface HdmiInternalRequest control;
        method Action setPatternColor(Bit#(32) v);
            patternRegs[0] <= v[23:0];
        endmethod
        method Action setTestPattern(Bit#(1) v);
            shadowTestPatternEnabled <= v;
        endmethod
        method Action setHsyncWidth(Bit#(12) width);
            hsyncWidth <= width;
        endmethod
        method Action setDePixelCountMinMax(Bit#(12) min, Bit#(12) max, Bit#(12) mid);
            dePixelCountMinimum <= min;
            dePixelCountMaximum <= max;
            pixelMidpoint <= mid;
        endmethod
        method Action setVsyncWidth(Bit#(11) width);
            vsyncWidth <= width;
        endmethod
        method Action setDeLineCountMinMax(Bit#(11) min, Bit#(11) max, Bit#(11) mid);
            deLineCountMinimum <= min;
            deLineCountMaximum <= max;
            lineMidpoint <= mid;
        endmethod
        method Action setNumberOfLines(Bit#(11) lines);
            numberOfLines <= lines;
        endmethod
        method Action setNumberOfPixels(Bit#(12) pixels);
            numberOfPixels <= pixels;
        endmethod
        method Action waitForVsync(Bit#(32) unused);
            waitingForVsync <= True;
        endmethod
    endinterface
   interface Get rgb888;
      method ActionValue#(VideoData#(Rgb888)) get();
	 return rgb888StageReg;
      endmethod
   endinterface
endmodule

module mkHDMI#(Get#(VideoData#(pixelType)) videoInput)(HDMI#(Bit#(pixelsz)))
   provisos (Bits#(VideoData#(pixelType), a__), Bits#(pixelType,pixelsz));
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   Wire#(VideoData#(pixelType)) video <- mkDWire(unpack(0));
   rule getvideo;
      let v <- videoInput.get();
      video <= v;
   endrule

   method Bit#(1) hdmi_vsync;
      return video.vsync;
   endmethod
   method Bit#(1) hdmi_hsync;
      return video.hsync;
   endmethod
   method Bit#(1) hdmi_de;
      return video.de;
   endmethod
   method Bit#(pixelsz) hdmi_data;
      return pack(video.pixel);
   endmethod
   interface hdmi_clock_if = defaultClock;
   interface deleteme_unused_reset = defaultReset;
endmodule

interface Rgb888ToYyuv;
   interface Put#(VideoData#(Rgb888)) rgb888;
   interface Get#(VideoData#(Yyuv)) yyuv;
endinterface

(* synthesize *)
module mkRgb888ToYyuv(Rgb888ToYyuv);
    Reg#(VideoData#(Rgb888)) rgb888StageReg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444Intermediates)) yuv444IntermediatesStageReg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444)) yuv444StageReg <- mkReg(unpack(0));
    Reg#(VideoData#(Yyuv)) yuv422StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    rule yuv444int_rule;
        let previous = rgb888StageReg;
        let pixel = previous.pixel;
        yuv444IntermediatesStageReg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: (previous.de != 0) ? rgbToYuvIntermediates(pixel) : unpack(0)
        };
    endrule

    rule yuv444_rule;
        let previous = yuv444IntermediatesStageReg;
        yuv444StageReg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
	    pixel: (previous.de != 0) ? yuvIntermediatesToYuv444(previous.pixel) : unpack(0)
        };
    endrule

    rule yuv422_rule;
        let previous = yuv444StageReg;
        if (previous.de != 0)
            evenOddPixelReg <= !evenOddPixelReg;
        Yyuv data = Yyuv { uv: evenOddPixelReg ? previous.pixel.u : previous.pixel.v,
                           yy: previous.pixel.y };
        yuv422StageReg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: data
        };
    endrule

   interface Put rgb888;
      method Action put(VideoData#(Rgb888) v);
	 rgb888StageReg <= v;
      endmethod
   endinterface
   interface Get yyuv;
      method ActionValue#(VideoData#(Yyuv)) get();
	 return yuv422StageReg;
      endmethod
   endinterface
endmodule