// *************************************************************************** //
// file     : HBFctl.v
// desp     : control modules, include pecnt, crdctl, outctl, crom 
// author   : duweitao@cuc.edu.cn
// date     : July.23th.2007
// version  : 0.2
// modified : change the crom output address generation
// *************************************************************************** // 
`ifdef INCTSC
`include "timescale.v"
`endif
// module pecnt(), pe counter
module pecnt(
  CLK   ,   // clock , posedge 
  RST   ,   // high level reset asyn
  DINEN ,   // data input enable
  PECY);    // pe cycle counter

  // global param
  parameter C2Q       = 0;    // time of DFF clock to Q in ns 
  parameter PCYMAX    = 0;    // max value of pe counter
  parameter PCYWL     = 0;    // word length pe cycle counter 
  parameter PCYIDL    = 0;    // pe cycle idle value
  
  input CLK, RST, DINEN;
  output [PCYWL-1:0 ] PECY;
  
  reg [PCYWL-1:0] PECY;     // combo logic
  
  always @ (posedge CLK or posedge RST) begin
    if(RST) begin
        PECY <= PCYIDL;
    end // if(RST) begin
    else begin
      if(DINEN) begin
        PECY <= #C2Q 1'b0;
      end 
      else begin
        if((PECY >= 0)&&(PECY < PCYMAX)) begin
          PECY <= #C2Q PECY + 1'b1;
        end
        else begin
          PECY <= #C2Q PCYIDL;
        end
      end 
    end //else (RST) begin
  end // always @ (posedge CLK or posedge RST)  begin
endmodule   // pecnt()

// module crdctl(), coeff rom read control
module crdctl(
  CLK   ,   // clock , posedge 
  RST   ,   // high level reset asyn
  DINEN ,   // data input enable
  PECY  ,   // PE cycle counter 
  CRD   ,   // crom read data
  RE    ,   // crom read enable
  CRA   ,   // crom read address
  COEF );   // clock output only for simulation

parameter COEFWL    = 0;
parameter K1        = 0;
parameter K2        = 0;
parameter C2Q       = 0;    // time of DFF clock to Q in ns 
parameter PCYMAX    = 0;    // max value of pe counter
parameter PCYWL     = 0;    // word length pe cycle counter 
parameter PCYIDL    = 0;    // pe cycle idle value
parameter CADDRWL   = 0;    // crom addr word length

  input                     CLK,   RST,   DINEN;   
  input     [PCYWL-1:0]     PECY;   
  input     [COEFWL-1:0]    CRD; 
  output                    RE;   
  output    [CADDRWL-1:0]   CRA;   
  output    [COEFWL-1:0]    COEF; 
  
  reg                   RE;   
  reg   [CADDRWL-1:0]   CRA;   
  reg   [CADDRWL-1:0]   idx;   
  reg   [CADDRWL-1:0]   offset;   
  reg   [COEFWL-1:0]    COEF; 

always @ (*) begin
  if((PECY >= 0) && (PECY < K1)) begin      // for y1(n,0)
    idx     = PECY[CADDRWL-1:0];
    offset  = 0;
    CRA     = idx;
    COEF    = CRD;
    RE      = 1'b1;
  end   // if(PECY [0,K1)
  else if((PECY >= K1)&&(PECY < K1+K2)) begin  // for y2(n,0)
    idx     = K1+K2-1-PECY[CADDRWL-1:0];
    COEF    = CRD;
    RE      = 1;
    if((idx <= K2-1) && (idx >= (K2>>1))) begin
      offset  = ({1'b0,idx} << 1) - K2 + 1;
    end
    else begin
      offset  = {idx[CADDRWL-2:0],1'b0};
    end
    CRA     = offset + K1;
  end // else if(PECY [K1, K1+K2)
  else if((PECY >= K1+K2)&&(PECY < K1+2*K2)) begin  // for y2(n,2)
    idx     = PECY[CADDRWL-1:0]-K1-K2;
    COEF    = CRD;
    RE      = 1;
    if((idx >= 0) && (idx < (K2>>1))) begin
      offset  = {idx[CADDRWL-2:0], 1'b0};
    end
    else begin
      offset  = ({1'b0,idx} << 1) - K2 + 1;
    end
    CRA     = offset + K1;
  end   // else if(PECY[K1+K2, K1+2K2)
  else begin  
    // TODO, to be updated
    idx     = 0;
    offset  = 0;
    CRA     = idx;
    COEF    = CRD;
    RE      = 0;
  end // else (PECY [K1+K2, K1+2K2-1)
end     // always(*)

endmodule   // module crdctl()



