`include "constants.vams"
`include "disciplines.vams"

`define BITS 04

module v_busencoder_04 (vdd, vss, vout);
  input vdd, vss;
  output [`BITS - 1:0] vout;

  electrical vdd, vss;
  electrical [`BITS - 1:0] vout;

  /* Integer value to be encoded to the output vout[x:0]. */
  parameter integer value = 0 from [0:inf);
  /* Is a power supply present. If so the assert value will follow
   * the supply attached to vdd. */
  parameter string vdd_present = "no";
  /* If a power supply is not present, the assert value will take
   * a static value of v_assert. */
  parameter real v_assert = 1.0;
  /* This tells the code how to encode the value parameter.
   * The choices are bin, therm, onehot, raw. */
  parameter string encode_style = "bin";
  /* Invert output? 1: yes, 0: no. */
  parameter integer inv_out_en = 0;

  integer bincode;
  integer i;
  genvar j;

  analog begin
    bincode = 0;

    /* Binary encoded, not 2's compliment, from decimal formatted input. */
    if (encode_style == "bin")
      bincode = value;

    /* Thermometer encoded, from decimal formatted input. */
    if (encode_style == "therm")
      bincode = pow(2, value) - 1;

    /* One-hot encoded, from decimal formatted input. */
    if (encode_style == "onehot")
      bincode = value > 0 ? 1 << (value - 1) : 0;

    /* Raw input, e.g. "10111001", will be treated as the binary code to the output. */
    if (encode_style == "raw")
      for (i = 0; i < `BITS; i = i + 1)
        bincode = bincode + pow(2, i) * (value / pow(10, i) % 10 );

    /* Present computed bincode to output. */
    if (vdd_present == "yes")
      for (j = 0; j < `BITS; j = j + 1)
        V(vout[j], vss) <+ (bincode >> j) & 1 ? (inv_out_en ? 0 : V(vdd)) : (inv_out_en ? V(vdd) : 0);
    else
      for (j = 0; j < `BITS; j = j + 1)
        V(vout[j], vss) <+ (bincode >> j) & 1 ? (inv_out_en ? 0 : v_assert) : (inv_out_en ? v_assert : 0);
  end

endmodule
