The CNRZ-5 Code

The CNRZ-5 code is used to transmit 5 bits over a collection of 6 wires. Its codebook consists of 32 quaternary codewords. The codewords are permutations of the vector (+1,1/3,1/3,-1/3,-1/3,-1). The encoder creates for an input of five bits four sets of bit masks of length 6. The first, called "one" has a 1 in exactly those positions where the corresponding codeword has a +1, and zeros elsewhere. The second bit mask, called "onethird" has a 1 in exactly those positions where the corresponding codeword has a +1/3 and zeros elsewhere. The third bit mask called monethird has a 1 in exactly those positions where the corresponding codeword has a -1/3 and zeros elsewhere. Finally, the last mask called mone has a 1 in exactly those positions where the corresponding codeword has a -1 and zeros elsewhere. Accordingly, the Hamming weight of one and mone is 1, whereas the Hamming weight of onethird and monethird is 2.

The following verilog code is one implementation of an encoder. It is not optimized and only serves as a proof of concept.

//
// CNRZ-5 encoder logic only (without flipflops).
//

module cnrz5 (
    input [4:0]  x,
    output [5:0] one,
    output [5:0] onethird,
    output [5:0] monethird,
    output [5:0] mone);


   // Input is a 2-bit vector 'i'
   // Output consists of a 9-bit vector
   function [8:0] a1(input [1:0] i);
      begin
   case (i)
     2'b00     : a1 = 9'b100010001;
     2'b01     : a1 = 9'b010100001;
     2'b10     : a1 = 9'b001010100;
     2'b11     : a1 = 9'b001100010;
     default   : a1 = 9'bxxxxxxxxx;
   endcase
      end
   endfunction // a1


   function [23:0] comp( input [4:0] x );
      reg [8:0] p;
      reg [8:0] q;
      reg [0:0] e;

      begin
   p=a1({x[1:0]});
   q=a1({x[3:2]});
   e={x[4:4]};

   if ( e == 1'b0)
     comp = {p[2:0],3'b000,p[5:3],q[2:0],p[8:6],q[5:3],3'b000,q[8:6]};
   else
     comp = {3'b000,q[2:0],p[2:0],q[5:3],p[5:3],q[8:6],p[8:6],3'b000};
      end
   endfunction // comp

   wire [23:0] code;

   assign code      = comp(x);
   assign one       = code[23:18];
   assign onethird  = code[17:12];
   assign monethird = code[11:6];
   assign mone      = code[5:0];

endmodule // enc5b6w

A possible driver is given below:

module driver;
   reg clk;

   reg [4:0] enc_x;
   wire [5:0] enc_one;
   wire [5:0] enc_onethird;
   wire [5:0] enc_monethird;
   wire [5:0] enc_mone;

   cnrz5 enc(
         .x(enc_x),
         .one(enc_one),
         .onethird(enc_onethird),
         .monethird(enc_monethird),
         .mone(enc_mone));

   always
     #1 clk=~clk;
   initial
     begin: sweep_inputs
  integer i;
  clk =0'b0;
  for ( i = 0; i < 32; i = i+1 )
    begin
       @(posedge clk);
       enc_x=i;
       @(negedge clk);
       $display("%x",{enc_one, enc_onethird, enc_monethird, enc_mone});
    end
  #10 $finish;
     end
endmodule // driver

The codewords created by this driver are given below. Each 6-digit hex-code represents 4 6-bit vectors wherein the first one is one, the second one is onethird, the third one is monethird, and the last one is mone:

211884,221484,811284,421284,211902,221502,811302,421302,
214881,224481,814281,424281,212901,222501,812301,422301,
04a520,04a910,062508,052908,04c4a0,04c890,064488,054888,
10a460,10a850,122448,112848,08c460,08c850,0a4448,094848