CORE ICE
The Core class in nxm.ice.lib provides the standard framework for developing a Java callable Core. The wrappers for each hardware implementation are auto-generated by the inner class definitions in the Java reference class.
The Foo.v code contains the Verilog implementation of the Core. It is used for both the VHS and ICE implementations. The Xilinx ISE or Xflow can be used to generate the bit file to be loaded into the ICE processor module. The Xilinx script provided in the ICE Toolkit's -soc zip file option uses the xflow process to automate compilation of designs.
For example:
unix> alias xi $ICEROOT/code/soc/xilinx unix> xi make v6m hhu 1 USER
will compile the cores defined in the $ICEROOT/code/soc/v6m/mdefs.h file's PE_USER branch and create the download file $ICEROOT/dat/icev6m_hhu.prm which can be loaded into the processor module by resetting the card with the PMFPGA=u
flag. The hh
in the signature is automatic for processor modules mounted on PIC5 and later cards.
Example
Here is an example Verilog implementation of the noop function contained in the file noopengine.v:
/* Noop FPGA Core */ module noopengine (sclk,srst, scs,saddr, swr,swrbus, srd,srdbus, sack, ioclk, istat,iena,isel,ibus, ostat,oena,osel,obus, test); parameter PORT=1; // engine index parameter IBW=64; // I/O bus width - 32b in processor modules, 64b in main boards (PIC5) parameter SBW=32; // System bus width - always 32 localparam DBW=32; // Data bus width (internal core use) input sclk; // system clock input srst; // system reset input scs; // system select (qualifies swr and srd for this core) input swr; // register write input srd; // register read input [31:0] saddr; // register address input [31:0] swrbus; // register data output [31:0] srdbus; // register data output sack; // acknowledge input ioclk; // I/O data bus clock output istat; // istat - ready to accept 64 by burst input iena; // input enable (one cycle early) (continuous 64 byte burst) input [7:0] isel; // input channel selection input [IBW-1:0] ibus; // input data bus output ostat; // ostat - ready to provide 64 byte burst input oena; // output enable (one cycle early) (continuous 64 byte burst) output [7:0] osel; // output channel selection output [IBW-1:0] obus;// output data bus output [7:0] test; // 8 test signals for scope probes wire L=0, H=1; assign sack=H; assign osel=0; // single channel core // system register address resolution - with pipeline wire [7:0] sb; swrbank #(0,8) swb (sclk,scs,swr,saddr,sb); wire swrsys = sb[0]; // system register (required) wire swrdec = sb[1]; // decimation register (optional) wire swrgain = sb[2]; // gain register (optional) wire swrfreq = sb[3]; // freq register (optional wire swrflag = sb[7]; // flag register (optional) // system registers - written to by pic_cport() host control software reg [31:0] system,dec,gain; always @(posedge sclk) begin if (srst) system <= 0; else if (swrsys) system <= swrbus; if (srst) dec <= 0; else if (swrdec) dec <= swrbus; end wire enable = system[0]; // core enable wire dir = system[1]; // direction ? output:input wire reduce = system[2]; // reduction ? enable:disable wire [3:0] ifmt = system[11:8]; // input format bit[2:0]? 0=16b 1=8b 2=4b 3=1b 4=32b bit[3]?complex:real wire [3:0] ofmt = system[15:12]; // output format bit[2:0]? 0=16b 1=8b 2=4b 3=1b 4=32b bit[3]?complex:real wire reset = !enable; // core reset (at boot or disabled) wire vena,wena,vstat,wstat; wire [DBW-1:0] vbus,wbus; reg ival; always @(posedge ioclk) ival <= iena; // handle iena early // this reformats any input type to output format 4'h8 = complex 16b fifoNxMfmt #(IBW,DBW) fi (ioclk,reset, ifmt,istat,ival,ibus, sclk,reset, 4'h8, vstat,vena,vbus); // example function - replace with call to user verilog or vhdl here noop inst (sclk,reset,reduce,dec, vstat,vena,vbus, wstat,wena,wbus); // this reformats the 4'h8 = complex 16b to any output type fifoNxMfmti #(IBW,DBW) fo (ioclk,reset, ofmt,ostat,oena,obus, sclk,reset, 4'h8, wstat,wena,wbus); spram #(2,32,0) rs (sclk,scs, saddr[10:2],swr, swrbus,srdbus); // example readback 2kB ram assign test = {oena,ostat,iena,istat,wena,vena,dir,reset}; // example test probe endmodule
The above code is the ICE system interface and dataflow engine. It handles the system register interface, as well as the dataflow buffering and reformatting. The specific functional code should be kept separate to allow the function to migrate easily to other frameworks. The following block contains the decimation function handled by the Noop core:
module noop (clk,reset,reduce,dec, vstat,vena,vbus, wstat,wena,wbus); input clk,reset,reduce; input [31:0] dec; input vstat,wstat; output vena,wena; input [31:0] vbus; output [31:0] wbus; // example noop with dec = decimation-1 reg [9:0] count; reg vena,vval; wire zero = (count==0); wire load = (vena && zero); always @(posedge clk) begin if (reset) count <= 0; else if (load) count <= dec[9:0]; else if (vena) count <= count-1; vena <= vstat && wstat && !reset; vval <= vena && (zero || !reduce); end assign wena = vval; assign wbus = vbus; endmodule