veryl-std 0.20.0

A modern hardware description language
Documentation
pub module slicer #(
    param WIDTH          : u32   = 1           ,
    param TYPE           : type  = logic<WIDTH>,
    param STAGES         : u32   = 1           ,
    param ASCENDING_ORDER: bbool = true        ,
    param FULL_BANDWIDTH : bbool = true        ,
    param DISABLE_MBFF   : bbool = false       ,
    param USE_RESET      : bbool = false       ,
) (
    i_clk  : input  clock,
    i_rst  : input  reset,
    o_ready: output logic,
    i_valid: input  logic,
    i_data : input  TYPE ,
    i_ready: input  logic,
    o_valid: output logic,
    o_data : output TYPE ,
) {
    const W: u32 = $bits(TYPE);

    var ready: logic    [STAGES + 1];
    var valid: logic    [STAGES + 1];
    var data : logic<W> [STAGES + 1];

    if ASCENDING_ORDER :g {
        always_comb {
            o_ready  = ready[0];
            valid[0] = i_valid;
            data[0]  = i_data;
        }

        always_comb {
            ready[STAGES] = i_ready;
            o_valid       = valid[STAGES];
            o_data        = data[STAGES];
        }

        for i in 0..STAGES :g {
            const RESET: bbool = USE_RESET && (i == (STAGES - 1));

            if FULL_BANDWIDTH :g {
                inst u_slicer: slicer_unit_fb #(
                    WIDTH       : W           ,
                    DISABLE_MBFF: DISABLE_MBFF,
                    USE_RESET   : RESET       ,
                ) (
                    i_clk  : i_clk       ,
                    i_rst  : i_rst       ,
                    o_ready: ready[i + 0],
                    i_valid: valid[i + 0],
                    i_data : data[i + 0] ,
                    i_ready: ready[i + 1],
                    o_valid: valid[i + 1],
                    o_data : data[i + 1] ,
                );
            } else {
                inst u_slicer: slicer_unit_hb #(
                    WIDTH       : W           ,
                    DISABLE_MBFF: DISABLE_MBFF,
                    USE_RESET   : RESET       ,
                ) (
                    i_clk  : i_clk       ,
                    i_rst  : i_rst       ,
                    o_ready: ready[i + 0],
                    i_valid: valid[i + 0],
                    i_data : data[i + 0] ,
                    i_ready: ready[i + 1],
                    o_valid: valid[i + 1],
                    o_data : data[i + 1] ,
                );
            }
        }
    } else {
        always_comb {
            o_ready       = ready[STAGES];
            valid[STAGES] = i_valid;
            data[STAGES]  = i_data;
        }

        always_comb {
            ready[0] = i_ready;
            o_valid  = valid[0];
            o_data   = data[0];
        }

        for i in 0..STAGES :g {
            const RESET: bbool = USE_RESET && (i == 0);

            if FULL_BANDWIDTH :g {
                inst u_slicer: slicer_unit_fb #(
                    WIDTH       : W           ,
                    DISABLE_MBFF: DISABLE_MBFF,
                    USE_RESET   : RESET       ,
                ) (
                    i_clk  : i_clk       ,
                    i_rst  : i_rst       ,
                    o_ready: ready[i + 1],
                    i_valid: valid[i + 1],
                    i_data : data[i + 1] ,
                    i_ready: ready[i + 0],
                    o_valid: valid[i + 0],
                    o_data : data[i + 0] ,
                );
            } else {
                inst u_slicer: slicer_unit_hb #(
                    WIDTH       : W           ,
                    DISABLE_MBFF: DISABLE_MBFF,
                    USE_RESET   : RESET       ,
                ) (
                    i_clk  : i_clk       ,
                    i_rst  : i_rst       ,
                    o_ready: ready[i + 1],
                    i_valid: valid[i + 1],
                    i_data : data[i + 1] ,
                    i_ready: ready[i + 0],
                    o_valid: valid[i + 0],
                    o_data : data[i + 0] ,
                );
            }
        }
    }
}

#[test(test_std_slicer)]
embed (inline) sv{{{
module test_std_slicer;
`ifndef VERILATOR
  timeunit 1ns/1ps;

  bit clk;
  bit rst_n;

  always #1 begin
    clk ^=1;
  end

  initial begin
    rst_n = 1;
    @(posedge clk);
    rst_n = 0;
    @(posedge clk);
    rst_n = 1;
  end

  bit       ready_a;
  bit       valid_a;
  bit [7:0] data_a;
  bit       ack_a;
  bit       ready_b;
  bit       valid_b;
  bit [7:0] data_b;
  bit       ready_c;
  bit       valid_c;
  bit [7:0] data_c;
  bit       ack_c;

  assign  ack_a = ready_a && valid_a;
  assign  ack_c = ready_c && valid_c;

  clocking cb @(posedge clk);
    input   ready_a;
    output  valid_a;
    output  data_a;
    input   ack_a;
    output  ready_c;
    input   valid_c;
    input   data_c;
    input   ack_c;
  endclocking

  initial begin
    cb.valid_a  <= '0;
    cb.data_a   <= '0;

    @(negedge rst_n);
    @(posedge rst_n);

    for (int i = 0;i < 10;++i) begin
      cb.valid_a  <= '1;
      cb.data_a   <= i;
      do begin
        @(cb);
      end while (!cb.ack_a);
    end

    cb.valid_a  <= '0;
    cb.data_a   <= '0;
  end

  initial begin
    cb.ready_c  <= '0;

    @(negedge rst_n);
    @(posedge rst_n);

    forever begin
      cb.ready_c  <= $urandom_range(0, 1);
      @(cb);
    end
  end

  initial begin
    for (int i = 0;i < 10;++i) begin
      do begin
        @(cb);
      end while (!cb.ack_c);

      assert (cb.data_c == i)
      else $error("data is not matched");
    end

    $finish;
  end

  std_slicer #(
    .WIDTH          (8  ),
    .STAGES         (2  ),
    .FULL_BANDWIDTH (1  )
  ) u_slicer_fb (
    .i_clk    (clk      ),
    .i_rst    (rst_n    ),
    .o_ready  (ready_a  ),
    .i_valid  (valid_a  ),
    .i_data   (data_a   ),
    .i_ready  (ready_b  ),
    .o_valid  (valid_b  ),
    .o_data   (data_b   )
  );

  std_slicer #(
    .WIDTH          (8  ),
    .STAGES         (2  ),
    .FULL_BANDWIDTH (0  )
  ) u_slicer_hb (
    .i_clk    (clk      ),
    .i_rst    (rst_n    ),
    .o_ready  (ready_b  ),
    .i_valid  (valid_b  ),
    .i_data   (data_b   ),
    .i_ready  (ready_c  ),
    .o_valid  (valid_c  ),
    .o_data   (data_c   )
  );
`endif
endmodule
}}}