CORE VHS

From ICE Enterprises
Jump to navigation Jump to search

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. Verilator converts the Verilog code into functionally equivalent C++ code. This is intended for development and debug purposes only and should not be deployed as part of a performance critical system.

The software hooks to the Verilator output code are conditionally compiled from the Foo.c file.

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