///////////////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------
//-- Title      : Controller
//-------------------------------------------------------------------------------
//-- File       : Controller.v
//-- Author     : Corporate Applications Engineering
//-- Company    : Microsemi Corporation
//-- Device     : RTG4
//-- Standard   : Verilog
//-------------------------------------------------------------------------------
//-- Description: This code implementes the AXI slave logic to receive the  
//--              commands from Serdes AXI master and to control the DMA transfers.
//--              It controls the scatter gather DMA channels CH0 (PCIe to DDR) and
//--              CH1 (DDR to PCIe) based on the buffer descriptors. Using PCIe slave
//--              AXI read channel the controller reads the 8 buffer descriptors at  
//--                      a time. It also implements counters to return the number of cycles taken 
//--                      to complete the DMA transfer.
//-------------------------------------------------------------------------------
//-- Copyright (c) 2015   Microsemi Corporation
//--                      All rights reserved.
//-------------------------------------------------------------------------------
//-- Revisions  : V1.0
//-------------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////////////////////////// 
module Controller(
                  //global
                  input CLK,
                  input RESETn,
                  // AXI Slave interface
                  input[3 : 0] AWID,
                  input[31 : 0] AWADDR,
                  input[3 : 0] AWLEN,
                  input[2 : 0] AWSIZE,
                  input[1 : 0] AWBURST,
                  input AWVALID,
                  output reg AWREADY,
                  input[3 : 0] WID,
                  input[63 : 0] WDATA,
                  input[7 : 0] WSTRB,
                  input WLAST,
                  input WVALID,
                  output reg WREADY,
                  output reg[3 : 0] BID,
                  output[1 : 0] BRESP,
                  output reg BVALID,
                  input BREADY,
                  input[3 : 0] ARID,
                  input[31 : 0] ARADDR,
                  input[3 : 0] ARLEN,
                  input[2 : 0] ARSIZE,
                  input[1 : 0] ARBURST,
                  input ARVALID,
                  output reg ARREADY,
                  output reg[3 : 0] RID,
                  output reg[63 : 0] RDATA,
                  output[1 : 0] RRESP,
                  output reg RLAST,
                  output reg RVALID,
                  input RREADY,
                  //PCIe Slave AXI read data channel signals
                  input PCIE_M_RVALID,
                  input[63 : 0] PCIE_M_RDATA,
                  // DMA CH0 control signals
                  output[31 : 0] PC_BASE_ADDR,
                  output reg[23 : 0] DDR_OFFSET,
                  output[2 : 0] DMA_DIR,
                  output[17 : 0] DMA_SIZE,
                  output reg CH0_INTR,
                  input PCIE_READ_DONE,
                  input DDR_WRITE_DONE,
                  input PCIE_READ_BUSY,
                  input DDR_WRITE_BUSY,
                  // DMA CH1 control signals        
                  output reg[31 : 0] PC_BASE_ADDR_CH1,
                  output reg[23 : 0] DDR_OFFSET_CH1,
                  output reg[2 : 0] DMA_DIR_CH1,
                  output reg[17 : 0] DMA_SIZE_CH1,
                  output CH1_INTERRUPT,
                  input PCIE_WRITE_DONE,
                  input PCIE_WRITE_BUSY,
                  input PCIe_WRITE_RESP,
                  input DDR_READ_BUSY,
                  //LEDs and Switches
                  output reg[7 : 0] LED,
                  input[3 : 0] DIP_SWITCH);
  reg[31 : 0] DMA_CR;
  reg ch0_busy;
  reg ch0_busy_ch1;
  //ch0 dma controls
  reg[31 : 0] BDA_CH0;
  reg[55 : 0] BD_CH0[15 : 0];
  reg[3 : 0] usram_addr;
  reg[2 : 0] bd_ch0_st;
  reg[3 : 0] bd_cnt;
  reg ch0_done;
  reg ch0_intr_local;
  reg[2 : 0] ch0_status;
  reg[28 : 0] Nbytes;
  reg[28 : 0] Nbytes_1;
  reg[8 : 0] bda_ch0_addr;
  reg CH0_START;
  reg[31 : 0] PC_BASE_ADDR_0;
  reg[2 : 0] DMA_DIR_0;
  reg[17 : 0] DMA_SIZE_0;
  //ch1 dma controls
  reg[31 : 0] BDA_CH1;
  reg[55 : 0] BD_CH1[15 : 0];
  reg[3 : 0] usram_addr_ch1;
  reg[2 : 0] bd_ch1_st;
  reg[3 : 0] bd_cnt_ch1;
  reg ch1_done;
  reg ch1_intr_local;
  reg[2 : 0] ch1_status;
  reg[28 : 0] Nbytes_ch1;
  reg[28 : 0] Nbytes_1_ch1;
  reg[8 : 0] bda_ch1_addr;
  reg CH1_START;
  reg CH1_INTR;
  reg[31 : 0] PC_BASE_ADDR_1;
  reg[2 : 0] DMA_DIR_1;
  reg[17 : 0] DMA_SIZE_1;
  //fsm
  reg[20 : 0] waddr_int;
  reg[20 : 0] raddr_int;
  reg[1 : 0] rstate;
  reg[1 : 0] wstate;
  //clock counters
  reg[31 : 0] clk_cnt_ch0;
  reg[31 : 0] clk_cnt_0;
  reg[31 : 0] clk_cnt_ch1;
  reg[31 : 0] clk_cnt_1;
  //BAR1 memory IF
  reg[31 : 0] RW_reg; //scratchpad reg
  reg[8 : 0] mem_raddr;
  reg[9 : 0] mem_waddr;
  reg[31 : 0] mem_wdata;
  reg mem_write;
  wire[63 : 0] mem_rdata;
  assign BRESP = 2'b00;
  assign RRESP = 2'b00;
  assign PC_BASE_ADDR = ch0_busy_ch1 ? PC_BASE_ADDR_1 : PC_BASE_ADDR_0;
  assign DMA_DIR = ch0_busy_ch1 ? DMA_DIR_1 : DMA_DIR_0;
  assign DMA_SIZE = ch0_busy_ch1 ? DMA_SIZE_1 : DMA_SIZE_0;
  assign CH1_INTERRUPT = CH1_INTR & PCIe_WRITE_RESP;
  //axi read/write states
  localparam[1 : 0] axi_addr_st = 2'b00,
                    axi_data_st = 2'b01,
                    axi_resp_st = 2'b10,
                    axi_wait_st = 2'b11;
  //dma control states
  localparam[2 : 0] dma_init_st = 3'b000,
                    dma_wait_ch1 = 3'b001,
                    dma_get_BD = 3'b010,
                    dma_xfer_op = 3'b011,
                    dma_xfer_op_wait = 3'b100,
                    dma_next_BD = 3'b101,
                    dma_sim1 = 3'b110,
                    dma_sim2 = 3'b111;
  //**************************************************************************
  //**************************AXI SLAVE IF************************************
  //**************************************************************************
  //write address, write data and write response channels
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          waddr_int <= 0;
          BID <= 0;
          BVALID <= 1'b0;
          AWREADY <= 1'b0;
          WREADY <= 1'b0;
          DMA_CR <= 0;
          BDA_CH0 <= 0;
          BDA_CH1 <= 0;
          LED <= 0;
          RW_reg <= 0;
          mem_waddr <= 0;
          mem_wdata <= 0;
          mem_write <= 0;
          wstate <= axi_addr_st;
        end
      else
        begin
          case (wstate)
            axi_addr_st:
              begin
                BVALID <= 1'b0;
                if (AWVALID == 1'b1)
                  begin
                    AWREADY <= 1'b1;
                    waddr_int <= AWADDR[20 : 0];
                    BID <= AWID;
                    wstate <= axi_data_st;
                  end
                else
                  begin
                    wstate <= axi_addr_st;
                  end
                if (ch0_done == 1'b1)
                  DMA_CR[15 : 0] <= 0;
                if (ch1_done == 1'b1)
                  DMA_CR[31 : 16] <= 0;
              end
            axi_data_st:
              begin
                AWREADY <= 1'b0;
                WREADY <= 1'b1;
                if (WLAST == 1'b1 && WVALID == 1'b1)
                  wstate <= axi_resp_st;
                else
                  wstate <= axi_data_st;
                //getting DMA_CR
                if (waddr_int[15 : 0] == 16'hFC00 && WSTRB[7 : 4] == 4'hF)
                  begin
                    DMA_CR <= WDATA[63 : 32];
                  end
                else
                  if (waddr_int[15 : 0] == 16'hFC04 && WSTRB[7 : 4] == 4'hF)
                    begin
                      DMA_CR <= WDATA[63 : 32];
                    end
                //getting BDA_CH0 -- ch0 buffer descriptor address
                if (waddr_int[15 : 0] == 16'hFC08)
                  begin
                    BDA_CH0 <= WDATA[31 : 0];
                  end
                //getting BDA_CH1 -- ch1 buffer descriptor address
                if (waddr_int[15 : 0] == 16'hFC18)
                  begin
                    BDA_CH1 <= WDATA[31 : 0];
                  end
                //PCIe R/W
                if (waddr_int[15 : 0] == 16'hFC00 && WSTRB[3 : 0] == 4'hF)
                  begin
                    RW_reg <= WDATA[31 : 0];
                  end
                //LEDs
                if (waddr_int[15 : 0] == 16'hFCA0)
                  begin
                    LED <= WDATA[7 : 0];
                  end
                //BAR1 mem
                if (waddr_int[20] == 1'b1)
                  begin
                    if (WSTRB[3 : 0] == 4'hF)
                      begin
                        mem_waddr <= waddr_int[11 : 2];
                        mem_wdata <= WDATA[31 : 0];
                        mem_write <= 1'b1;
                      end
                    else
                      if (WSTRB[7 : 4] == 4'hF)
                        begin
                          mem_waddr <= { waddr_int[11 : 3], 1'b1 };
                          mem_wdata <= WDATA[63 : 32];
                          mem_write <= 1'b1;
                        end
                  end
              end
            axi_resp_st:
              begin
                WREADY <= 1'b0;
                mem_write <= 1'b0;
                if (BREADY == 1'b1)
                  begin
                    BVALID <= 1'b1;
                    wstate <= axi_addr_st;
                  end
                else
                  begin
                    BVALID <= 1'b0;
                    wstate <= axi_resp_st;
                  end
              end
            default:
              wstate <= axi_addr_st;
          endcase
        end
    end
  //read address and read data channels
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          raddr_int <= 0;
          ARREADY <= 1'b0;
          RID <= 0;
          RVALID <= 1'b0;
          RLAST <= 1'b0;
          mem_raddr <= 0;
          rstate <= axi_addr_st;
        end
      else
        begin
          case (rstate)
            axi_addr_st:
              begin
                RVALID <= 1'b0;
                RLAST <= 1'b0;
                if (ARVALID == 1'b1)
                  begin
                    RID <= ARID;
                    raddr_int <= ARADDR[20 : 0];
                    mem_raddr <= ARADDR[11 : 3];
                    ARREADY <= 1'b1;
                    rstate <= axi_wait_st;
                  end
              end
            axi_wait_st: //wait state
              begin
                rstate <= axi_resp_st;
              end
            axi_resp_st:
              begin
                ARREADY <= 1'b0;
                if (RREADY == 1'b1)
                  begin
                    RVALID <= 1'b1;
                    RLAST <= 1'b1;
                    rstate <= axi_addr_st;
                  end
              end
            default:
              rstate <= axi_addr_st;
          endcase
        end
    end
  //returing the data
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          RDATA <= 5; //for board detection 
        end
      else
        begin
          if (raddr_int[20] == 1'b1)
            begin
              RDATA <= mem_rdata; //for BAR1 4K memory
            end
          else
            begin
              case (raddr_int[15 : 0])
                //dma control reg and scratchpad reg
                16'hFC00:
                  begin
                    RDATA <= { DMA_CR, RW_reg };
                  end
                //ch0 buffer descriptor address
                16'hFC08:
                  begin
                    RDATA <= BDA_CH0;
                  end
                //ch0 status
                16'hFC10:
                  begin
                    RDATA <= { clk_cnt_ch0, ch0_status, Nbytes_1 }; //32-bit clock count + 3-bit status + 29-bit byte count
                  end
                16'hFC14:
                  begin
                    RDATA <= { clk_cnt_ch0, ch0_status, Nbytes_1 }; //32-bit clock count + 3-bit status + 29-bit byte count
                  end
                //ch1 buffer descriptor address
                16'hFC18:
                  begin
                    RDATA <= BDA_CH1;
                  end
                //ch1 status
                16'hFC20:
                  begin
                    RDATA <= { clk_cnt_ch1, ch1_status, Nbytes_1_ch1 }; //32-bit clock count + 3-bit status + 29-bit byte count
                  end
                16'hFC24:
                  begin
                    RDATA <= { clk_cnt_ch1, ch1_status, Nbytes_1_ch1 }; //32-bit clock count + 3-bit status + 29-bit byte count
                  end
                //clk frequency
                16'hFC28:
                  begin
                    RDATA <= 80;
                  end
                16'hFC30:
                  begin
                    RDATA <= DIP_SWITCH; //DIP switch status
                  end
                16'h8148:
                  begin
                    RDATA <= { 32'h3, 32'h5 }; //SGDMA board detection
                  end
                16'h814C:
                  begin
                    RDATA <= { 32'h3, 32'h5 }; //SGDMA board detection
                  end
                default:
                  RDATA <= { 32'h3, 32'h5 }; //SGDMA board detection
              endcase
            end
        end
    end
  //TPSRAM -- BAR1 4KB memory
  BAR1_LSRAM BAR1_LSRAM_0(
                          // Inputs
                          .CLK(CLK),
                          .RADDR(mem_raddr),
                          .WADDR(mem_waddr),
                          .WD(mem_wdata),
                          .WEN(mem_write),
                          // Outputs
                          .RD(mem_rdata));
  //**************************************************************************
  //**************************CH0 CONTROLLER**********************************
  //**************************************************************************
  //CH0
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          PC_BASE_ADDR_0 <= 0;
          DDR_OFFSET <= 0;
          DMA_DIR_0 <= 3'b111;
          DMA_SIZE_0 <= 18'h10; //default 16*8 = 128 bytes 
          bda_ch0_addr <= 0;
          bd_cnt <= 0;
          CH0_START <= 0;
          ch0_busy <= 0;
          ch0_done <= 0;
          ch0_status <= 0;
          CH0_INTR <= 0;
          ch0_intr_local <= 0;
          bd_ch0_st <= dma_init_st;
        end
      else
        begin
          case (bd_ch0_st)
            dma_init_st: //start sgdma operation
              begin
                ch0_intr_local <= 0;
                ch0_done <= 0;
                bd_cnt <= 0;
                PC_BASE_ADDR_0 <= BDA_CH0 + { bda_ch0_addr, 7'b0 }; //address + value * 128
                if (DMA_CR[15 : 0] == 16'hFFFF)
                  begin
                    CH0_INTR <= 0;
                    ch0_busy <= 1;
                    bd_ch0_st <= dma_wait_ch1;
                  end
              end
            dma_wait_ch1: //check if ch1 getting BDs
              begin
                if (ch0_busy_ch1 == 1'b0)
                  begin
                    CH0_START <= 1;
                    DMA_DIR_0 <= 3'b101; //read from PCIe
                    DMA_SIZE_0 <= 18'h10; //get first 8 BDs
                    bd_cnt <= 0;
                    bd_ch0_st <= dma_get_BD;
                  end
              end
            dma_get_BD: //get first 8 BDs
              begin
                if (PCIE_READ_DONE == 1'b1)
                  begin
                    CH0_START <= 0;
                    ch0_busy <= 0;
                    DMA_DIR_0 <= 3'b111;
                    bd_cnt <= 0;
                    bd_ch0_st <= dma_xfer_op;
                  end
              end
            dma_xfer_op: //initiate dma data transfer
              begin
                PC_BASE_ADDR_0 <= BD_CH0[bd_cnt][31 : 0];
                DMA_SIZE_0 <= BD_CH0[bd_cnt + 1][20 : 3];
                DDR_OFFSET <= BD_CH0[bd_cnt + 1][55 : 32];
                if (ch0_busy_ch1 == 1'b0)
                  begin
                    ch0_busy <= 1;
                    if (BD_CH0[bd_cnt + 1][31 : 24] == 8'hAA) //check for valid BD
                      begin
                        if (DDR_WRITE_BUSY == 1'b0 && PCIE_READ_BUSY == 1'b0)
                          begin
                            DMA_DIR_0 <= 3'b001; //pc to ddr                         
                            bd_ch0_st <= dma_xfer_op_wait;
                          end
                      end
                    else
                      begin
                        ch0_done <= 1'b1;
                        ch0_status <= 3'b001;
                        bd_ch0_st <= dma_next_BD;
                      end
                  end
              end
            dma_xfer_op_wait: //do dma till last BD 
              begin
                if (DDR_WRITE_DONE == 1'b1)
                  begin
                    DMA_DIR_0 <= 3'b111;
                    bd_cnt <= bd_cnt + 2;
                    ch0_busy <= 0;
                    if (BD_CH0[bd_cnt + 1][23] == 1'b1) //last dma transfer
                      begin
                        ch0_done <= 1'b1;
                        ch0_status <= 3'b000;
                        bd_ch0_st <= dma_next_BD;
                      end
                    else
                      begin
                        if (bd_cnt == 14) //get next 8 BDs 
                          begin
                            bda_ch0_addr <= bda_ch0_addr + 1'b1;
                            bd_ch0_st <= dma_next_BD;
                          end
                        else
                          begin
                            bd_ch0_st <= dma_xfer_op;
                          end
                      end
                  end
              end
            dma_next_BD:
              begin
                if (ch0_done) //dma op completed
                  begin
                    ch0_busy <= 0;
                    CH0_INTR <= 1;
                    ch0_intr_local <= 1;
                    bda_ch0_addr <= 0;
                    DMA_SIZE_0 <= 18'h10;
                    bd_ch0_st <= dma_init_st;
                  end
                else
                  begin //get 8 BDs
                    ch0_busy <= 1;
                    PC_BASE_ADDR_0 <= BDA_CH0 + { bda_ch0_addr, 7'b0 }; //address + value * 128
                    bd_ch0_st <= dma_wait_ch1;
                  end
              end
            default:
              bd_ch0_st <= dma_init_st;
          endcase
        end
    end
  //getting ch0 BDs
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          usram_addr <= 0;
        end
      else
        begin
          if (CH0_START == 1'b0)
            usram_addr <= 0;
          else
            if (PCIE_M_RVALID == 1'b1)
              begin
                BD_CH0[usram_addr] <= PCIE_M_RDATA;
                usram_addr <= usram_addr + 1;
              end
        end
    end
  //clk counting for DMA channel 0
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          clk_cnt_0 <= 0;
          clk_cnt_ch0 <= 0;
        end
      else
        begin
          //clk counter
          if (ch0_intr_local) //to reset the clk count value
            begin
              clk_cnt_0 <= 0;
              clk_cnt_ch0 <= clk_cnt_0;
            end
          else
            begin
              if (DMA_DIR_0 == 3'b001)
                begin
                  clk_cnt_0 <= clk_cnt_0 + 1;
                end
              else
                begin
                  clk_cnt_0 <= clk_cnt_0;
                end
            end
        end
    end
  //DMA ch0 byte count
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          Nbytes <= 0;
          Nbytes_1 <= 0;
        end
      else
        begin
          if (ch0_intr_local == 1'b1)
            begin
              Nbytes_1 <= Nbytes;
              Nbytes <= 0;
            end
          else
            if (DDR_WRITE_DONE == 1'b1)
              begin
                Nbytes <= Nbytes + DMA_SIZE;
              end
        end
    end
  //**************************************************************************
  //**************************CH1 CONTROLLER**********************************
  //**************************************************************************
  //CH1
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          PC_BASE_ADDR_CH1 <= 0;
          DDR_OFFSET_CH1 <= 0;
          DMA_DIR_CH1 <= 3'b111;
          DMA_SIZE_CH1 <= 18'h80; //default 128*8 bytes = 1KB - 8bursts
          PC_BASE_ADDR_1 <= 0;
          DMA_DIR_1 <= 3'b111;
          DMA_SIZE_1 <= 18'h10; //default 16*8 = 128 bytes - 1burst
          CH1_INTR <= 0;
          ch1_intr_local <= 0;
          CH1_START <= 0;
          ch0_busy_ch1 <= 0;
          ch1_done <= 0;
          ch1_status <= 3'b000;
          bd_cnt_ch1 <= 0;
          bda_ch1_addr <= 0;
          bd_ch1_st <= dma_init_st;
        end
      else
        begin
          case (bd_ch1_st)
            dma_sim1: //for simulation
              begin
                if (DMA_CR == 16'h11AA)
                  begin
                    PC_BASE_ADDR_CH1 <= 0;
                    DMA_DIR_CH1 <= 3'b110; //lsram to pc
                    bd_ch1_st <= dma_sim2;
                  end
              end
            dma_sim2: //for simulation
              begin
                if (PCIE_WRITE_DONE == 1'b1)
                  begin
                    DMA_DIR_CH1 <= 3'b111;
                    bd_ch1_st <= dma_init_st;
                  end
              end
            dma_init_st:
              begin
                ch1_intr_local <= 0;
                ch1_done <= 1'b0;
                if (DMA_CR[31 : 16] == 16'hFFFF && ch0_busy == 1'b0)
                  begin
                    CH1_INTR <= 0;
                    ch1_status <= 3'b000;
                    CH1_START <= 1;
                    ch0_busy_ch1 <= 1;
                    PC_BASE_ADDR_1 <= BDA_CH1;
                    DMA_DIR_1 <= 3'b101;
                    DMA_SIZE_1 <= 18'h10;
                    bd_cnt_ch1 <= 0;
                    bd_ch1_st <= dma_get_BD;
                  end
              end
            dma_get_BD: //get first 8 BDs
              begin
                if (PCIE_READ_DONE == 1'b1)
                  begin
                    CH1_START <= 0;
                    DMA_DIR_1 <= 3'b111;
                    bd_cnt_ch1 <= 0;
                    bd_ch1_st <= dma_xfer_op;
                  end
              end
            dma_xfer_op: ////initiate dma data transfer
              begin
                ch0_busy_ch1 <= 0;
                PC_BASE_ADDR_CH1 <= BD_CH1[bd_cnt_ch1][31 : 0];
                DDR_OFFSET_CH1 <= BD_CH1[bd_cnt_ch1 + 1][55 : 32];
                if (BD_CH1[bd_cnt_ch1 + 1][31 : 24] == 8'hAA) //check for valid BD
                  begin
                    if (DDR_READ_BUSY == 1'b0 && PCIE_WRITE_BUSY == 1'b0)
                      begin
                        DMA_SIZE_CH1 <= BD_CH1[bd_cnt_ch1 + 1][20 : 3];
                        DMA_DIR_CH1 <= 3'b010; //ddr to pc    
                        bd_ch1_st <= dma_xfer_op_wait;
                      end
                  end
                else
                  begin
                    ch1_done <= 1'b1;
                    ch1_status <= 3'b001; //report error
                    bd_ch1_st <= dma_next_BD;
                  end
              end
            dma_xfer_op_wait: //do dma till last BD
              begin
                if (PCIE_WRITE_DONE == 1'b1)
                  begin
                    DMA_DIR_CH1 <= 3'b111;
                    bd_cnt_ch1 <= bd_cnt_ch1 + 2;
                    if (BD_CH1[bd_cnt_ch1 + 1][23] == 1'b1) //last dma transfer
                      begin
                        ch1_done <= 1'b1;
                        ch1_status <= 3'b000; //no error
                        bd_ch1_st <= dma_next_BD;
                      end
                    else
                      begin
                        if (bd_cnt_ch1 == 14)
                          begin
                            bda_ch1_addr <= bda_ch1_addr + 1'b1; //address for next 8 BDs
                            bd_ch1_st <= dma_next_BD;
                          end
                        else
                          begin
                            bd_ch1_st <= dma_xfer_op;
                          end
                      end
                  end
              end
            dma_next_BD:
              begin
                if (ch1_done) //dma op completed
                  begin
                    DDR_OFFSET_CH1 <= 0;
                    CH1_INTR <= 1;
                    ch1_intr_local <= 1;
                    bd_cnt_ch1 <= 0;
                    bda_ch1_addr <= 0;
                    DMA_SIZE_1 <= 18'h10;
                    bd_ch1_st <= dma_init_st;
                  end
                else
                  begin
                    if (ch0_busy == 1'b0) //get 8 BDs
                      begin
                        CH1_START <= 1;
                        ch0_busy_ch1 <= 1;
                        PC_BASE_ADDR_1 <= BDA_CH1 + { bda_ch1_addr, 7'b0 }; //address + value * 128
                        DMA_DIR_1 <= 3'b101;
                        DMA_SIZE_1 <= 18'h10;
                        bd_ch1_st <= dma_get_BD;
                      end
                  end
              end
            default:
              bd_ch1_st <= dma_init_st;
          endcase
        end
    end
  //getting ch0 BDs
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          usram_addr_ch1 <= 0;
        end
      else
        begin
          if (CH1_START == 1'b0)
            usram_addr_ch1 <= 0;
          else
            if (PCIE_M_RVALID == 1'b1)
              begin
                BD_CH1[usram_addr_ch1] <= PCIE_M_RDATA;
                usram_addr_ch1 <= usram_addr_ch1 + 1;
              end
        end
    end
  //clk counting DMA channel 1
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          clk_cnt_1 <= 0;
          clk_cnt_ch1 <= 0;
        end
      else
        begin
          //clk counter
          if (ch1_intr_local) //to reset the clk count value
            begin
              clk_cnt_1 <= 0;
              clk_cnt_ch1 <= clk_cnt_1;
            end
          else
            begin
              if (DMA_DIR_CH1 == 3'b010)
                begin
                  clk_cnt_1 <= clk_cnt_1 + 1;
                end
              else
                begin
                  clk_cnt_1 <= clk_cnt_1;
                end
            end
        end
    end
  //DMA ch1 byte count
  always
    @(posedge CLK)
    begin
      if (RESETn == 1'b0)
        begin
          Nbytes_ch1 <= 0;
          Nbytes_1_ch1 <= 0;
        end
      else
        begin
          if (ch1_intr_local == 1'b1)
            begin
              Nbytes_1_ch1 <= Nbytes_ch1;
              Nbytes_ch1 <= 0;
            end
          else
            if (PCIE_WRITE_DONE == 1'b1)
              begin
                Nbytes_ch1 <= Nbytes_ch1 + DMA_SIZE_CH1;
              end
        end
    end
endmodule
