//exp/microboone/study2010/study_compressor_100304/ march8,2011 module compressor_100227 ( clk128,nocomp,channel,datin,fstin,lstin,davin, //compdat,compdav,compfst,complst, davout,datout,fstout,lstout,blkout, init,eventnumber,wordcount,checksum,heddav, blklst,blocknumber,framenumber ); /* hoffman lossless data compression udat - dat code -3 000001 -2 0001 -1 01 0 1 +1 001 +2 00001 +3 0000001 datout format: bit 15 14 13 12 11 - 00 header words 1 1 1 1 first word 1 1 0 0 channel# last word 1 1 0 1 adc not compressed 1 0 0 0 adc compressed 0 {code, code , } */ input clk128; //128Mhz clock input nocomp; //compression off input [5:0] channel; //first word channel# input [15:0] datin; //input word input fstin; //first input word flag input lstin; //last input word flag input davin; //valid input word flag //output [15:0] compdat; //output compdav; //output compfst; //output complst; output davout; //valid output word flag output fstout; //first output word flag output lstout; //last output word flag output [29:0] datout; //output word output [7:0] blkout; //block number input init; //reset event number output [23:0] eventnumber; //trigger count output [23:0] wordcount; //compressor word count output [23:0] checksum; //compressor data sum output heddav; //valid header data input blklst; input [23:0] blocknumber; output [23:0] framenumber; //the compressor pipeline: reg u0fst; reg u1fst; reg u2fst; reg u3fst; reg u0lst; reg u1lst; reg u2lst; reg u3lst; reg u0val; reg u1val; reg u2val; reg u3val; reg [15:0] u0dat; reg [15:0] u1dat; reg [15:0] u2dat; reg [15:0] u3dat; reg [5:0] u0ch; reg [5:0] u1ch; reg [5:0] u2ch; reg [5:0] u3ch; always @ (posedge clk128) begin u0fst <= fstin; u1fst <= u0fst; u2fst <= u1fst; u3fst <= u2fst; if (fstin) u0dat <= {10'h000,channel[5:0]}; else if (lstin) u0dat <= {10'h000,channel[5:0]};///// else u0dat <= datin; u1dat <= u0dat; u2dat <= u1dat; u3dat <= u2dat; u0val <= davin; u1val <= u0val; u2val <= u1val; u3val <= u2val; u0lst <= lstin; u1lst <= u0lst; u2lst <= u1lst; u3lst <= u2lst; u0ch <= channel; u1ch <= u0ch; u2ch <= u1ch; u3ch <= u2ch; end //the difference between successive adc samples: reg [11:0] diff; reg pos; reg neg; wire gt; wire lt; assign gt = u0dat[11:0] >= u1dat[11:0]; assign lt = u1dat[11:0] > u0dat[11:0]; always @ (posedge clk128) begin if (fstin) diff <= 12'h000; else if (gt) diff <= (u0dat[11:0] - u1dat[11:0]); else if (lt) diff <= (u1dat[11:0] - u0dat[11:0]); pos <= gt; neg <= lt; end //the compression codes: reg pos0; reg neg1; reg pos1; reg neg2; reg pos2; reg neg3; reg pos3; reg other; reg uother; always @ (posedge clk128) begin if (!u1fst & u1val & pos & (diff==0)) pos0 <= 1'b1; else pos0 <= 1'b0; if (!u1fst & u1val & neg & (diff==1)) neg1 <= 1'b1; else neg1 <= 1'b0; if (!u1fst & u1val & pos & (diff==1)) pos1 <= 1'b1; else pos1 <= 1'b0; if (!u1fst & u1val & neg & (diff==2)) neg2 <= 1'b1; else neg2 <= 1'b0; if (!u1fst & u1val & pos & (diff==2)) pos2 <= 1'b1; else pos2 <= 1'b0; if (!u1fst & u1val & neg & (diff==3)) neg3 <= 1'b1; else neg3 <= 1'b0; if (!u1fst & u1val & pos & (diff==3)) pos3 <= 1'b1; else pos3 <= 1'b0; if (diff>3) other <= 1'b1; else other <= 1'b0; uother <= other; end //huffman compression: reg [15:0] comp; wire pre; assign pre = ((diff>3) | u2lst) & !other & u2val; always @ (posedge clk128) begin if (u2fst) comp <= {16'h0000}; else if (u2lst) comp <= {16'h0000}; else if (other) comp <= {16'h0000}; else if (pre) comp <= {16'h0000}; else if (pos0 &(comp[0]==0)) comp <= {1'b1,1'b1,comp[14:1]}; else if (pos0 &(comp[0]!=0)) comp <= {1'b1,1'b1,14'h0000}; else if (neg1 &(comp[1:0]==0)) comp <= {1'b1,2'b01,comp[14:2]}; else if (neg1 &(comp[1:0]!=0)) comp <= {1'b1,2'b01,13'h0000}; else if (pos1 &(comp[2:0]==0)) comp <= {1'b1,3'b001,comp[14:3]}; else if (pos1 &(comp[2:0]!=0)) comp <= {1'b1,3'b001,12'h000}; else if (neg2 &(comp[3:0]==0)) comp <= {1'b1,4'b0001,comp[14:4]}; else if (neg2 &(comp[3:0]!=0)) comp <= {1'b1,4'b0001,11'h000}; else if (pos2 &(comp[4:0]==0)) comp <= {1'b1,5'b00001,comp[14:5]}; else if (pos2 &(comp[4:0]!=0)) comp <= {1'b1,5'b00001,10'h000}; else if (neg3 &(comp[5:0]==0)) comp <= {1'b1,6'b000001,comp[14:6]}; else if (neg3 &(comp[5:0]!=0)) comp <= {1'b1,6'b000001,9'h000}; else if (pos3 &(comp[6:0]==0)) comp <= {1'b1,7'b0000001,comp[14:7]}; else if (pos3 &(comp[6:0]!=0)) comp <= {1'b1,7'b0000001,8'h00}; end wire full; assign full = (pos0 & (comp[0]!=0)) | (neg1 & (comp[1:0]!=0)) | (pos1 & (comp[2:0]!=0)) | (neg2 & (comp[3:0]!=0)) | (pos2 & (comp[4:0]!=0)) | (neg3 & (comp[5:0]!=0)) | (pos3 & (comp[6:0]!=0)) ; //16bit compressor output with fst,lst,dav flags : reg [17:0] data; reg [5:0] ch; always @ (posedge clk128) begin if (u3val & u3fst) data <= {2'b01,4'b0100,u3dat[11:0]}; else if (u3val & u3lst) data <= {2'b11,4'b0101,u3dat[11:0]}; else if (u3val & nocomp) data <= {2'b10,u3dat[15:0]}; else if (u3val & pre) data <= {2'b10,comp[15:0]}; else if (u3val & full) data <= {2'b10,comp[15:0]}; else if (u3val & (other | uother)) data <= {2'b10,4'b0000,u3dat[11:0]}; else data <= 18'h0000; ch <= u3ch; end wire compdav; wire compfst; wire complst; wire [15:0] compdat; assign compdat = data[15:0]; assign compdav = (data[17:16]>0); assign compfst = (data[17:16]==2'b01) & (ch==0); assign complst = (data[17:16]==2'b11) & (ch==63); //________________________________________________________ //convert the 16bit stream to a 24bit stream: wire [23:0] dat24; wire dav24; wire fst24; wire lst24; width24_3 convertwidth ( .init (init), .clk128(clk128), .datin(compdat), .davin(compdav), .fstin(compfst), .lstin(complst), //24bit stream: .datout(dat24), .davout(dav24), .fstout(fst24), .lstout(lst24) ); //__________________________________________________________________ //hamming code for the 24bit stream: wire [29:0] datout; reg davout; reg fstout; reg lstout; reg [7:0] blkout; hammingcode encode24 ( .clock(clk128), .data(dat24), .q(datout) ); //assign a block number for the event: always @ (posedge clk128) begin davout <= dav24; fstout <= fst24; lstout <= lst24; if (lst24) blkout <= eventnumber[7:0]; else blkout <= 8'h00; end //___________________________________ //create header data: reg [23:0] eventnumber; reg [23:0] wordcount; reg [23:0] checksum; reg [23:0] count; reg [23:0] accum; reg heddav; reg [23:0] blocknum; reg [23:0] framenumber; always @ (posedge clk128) begin if (init) eventnumber <= 24'h000001; else if (complst) eventnumber <= eventnumber + 24'h000001; else eventnumber <= eventnumber; if (init) count <= 24'd0; else if (compfst) count <= 24'h000000; else if (compdav) count <= count + 24'h000001; else count <= count; if (complst) wordcount <= count; if (init) accum <= 24'd0; else if (compfst) accum <= {8'h00,compdat}; else if (compdav) accum <= accum + {8'h00,compdat}; else accum <= accum; if (init) checksum <= 24'd0; else if (complst) checksum <= accum; if (init) blocknum <= 24'd0; else if (blklst) blocknum <= blocknumber; if (init) framenumber <= 24'd0; else if (complst) framenumber <= blocknum; heddav <= complst; end endmodule