Decoupled Queue 생성

YumeIroVillain·2023년 8월 25일
0

Chisel 독학

목록 보기
41/44

Flipped(Decoupled()) 및 entries를 입력으로 받는다.

class QueueModule[T <: Data](ioType: T, entries: Int) extends MultiIOModule {
  val in = IO(Flipped(Decoupled(ioType)))
  val out = IO(Decoupled(ioType))
  out <> Queue(in, entries)
}
println(getVerilog(new QueueModule(UInt(8.W),4)))
module Queue(
  input        clock,
  input        reset,
  output       io_enq_ready,
  input        io_enq_valid,
  input  [7:0] io_enq_bits,
  input        io_deq_ready,
  output       io_deq_valid,
  output [7:0] io_deq_bits
);
  reg [7:0] ram [0:3]; // @[Decoupled.scala 218:16]
  wire [7:0] ram_io_deq_bits_MPORT_data; // @[Decoupled.scala 218:16]
  wire [1:0] ram_io_deq_bits_MPORT_addr; // @[Decoupled.scala 218:16]
  wire [7:0] ram_MPORT_data; // @[Decoupled.scala 218:16]
  wire [1:0] ram_MPORT_addr; // @[Decoupled.scala 218:16]
  wire  ram_MPORT_mask; // @[Decoupled.scala 218:16]
  wire  ram_MPORT_en; // @[Decoupled.scala 218:16]
  reg [1:0] value; // @[Counter.scala 60:40]
  reg [1:0] value_1; // @[Counter.scala 60:40]
  reg  maybe_full; // @[Decoupled.scala 221:27]
  wire  ptr_match = value == value_1; // @[Decoupled.scala 223:33]
  wire  empty = ptr_match & ~maybe_full; // @[Decoupled.scala 224:25]
  wire  full = ptr_match & maybe_full; // @[Decoupled.scala 225:24]
  wire  do_enq = io_enq_ready & io_enq_valid; // @[Decoupled.scala 40:37]
  wire  do_deq = io_deq_ready & io_deq_valid; // @[Decoupled.scala 40:37]
  wire [1:0] _value_T_1 = value + 2'h1; // @[Counter.scala 76:24]
  wire [1:0] _value_T_3 = value_1 + 2'h1; // @[Counter.scala 76:24]
  assign ram_io_deq_bits_MPORT_addr = value_1;
  assign ram_io_deq_bits_MPORT_data = ram[ram_io_deq_bits_MPORT_addr]; // @[Decoupled.scala 218:16]
  assign ram_MPORT_data = io_enq_bits;
  assign ram_MPORT_addr = value;
  assign ram_MPORT_mask = 1'h1;
  assign ram_MPORT_en = io_enq_ready & io_enq_valid;
  assign io_enq_ready = ~full; // @[Decoupled.scala 241:19]
  assign io_deq_valid = ~empty; // @[Decoupled.scala 240:19]
  assign io_deq_bits = ram_io_deq_bits_MPORT_data; // @[Decoupled.scala 242:15]
  always @(posedge clock) begin
    if(ram_MPORT_en & ram_MPORT_mask) begin
      ram[ram_MPORT_addr] <= ram_MPORT_data; // @[Decoupled.scala 218:16]
    end
    if (reset) begin // @[Counter.scala 60:40]
      value <= 2'h0; // @[Counter.scala 60:40]
    end else if (do_enq) begin // @[Decoupled.scala 229:17]
      value <= _value_T_1; // @[Counter.scala 76:15]
    end
    if (reset) begin // @[Counter.scala 60:40]
      value_1 <= 2'h0; // @[Counter.scala 60:40]
    end else if (do_deq) begin // @[Decoupled.scala 233:17]
      value_1 <= _value_T_3; // @[Counter.scala 76:15]
    end
    if (reset) begin // @[Decoupled.scala 221:27]
      maybe_full <= 1'h0; // @[Decoupled.scala 221:27]
    end else if (do_enq != do_deq) begin // @[Decoupled.scala 236:28]
      maybe_full <= do_enq; // @[Decoupled.scala 237:16]
    end
  end
endmodule
module QueueModule(
  input        clock,
  input        reset,
  output       in_ready,
  input        in_valid,
  input  [7:0] in_bits,
  input        out_ready,
  output       out_valid,
  output [7:0] out_bits
);
  wire  q_clock; // @[Decoupled.scala 296:21]
  wire  q_reset; // @[Decoupled.scala 296:21]
  wire  q_io_enq_ready; // @[Decoupled.scala 296:21]
  wire  q_io_enq_valid; // @[Decoupled.scala 296:21]
  wire [7:0] q_io_enq_bits; // @[Decoupled.scala 296:21]
  wire  q_io_deq_ready; // @[Decoupled.scala 296:21]
  wire  q_io_deq_valid; // @[Decoupled.scala 296:21]
  wire [7:0] q_io_deq_bits; // @[Decoupled.scala 296:21]
  Queue q ( // @[Decoupled.scala 296:21]
    .clock(q_clock),
    .reset(q_reset),
    .io_enq_ready(q_io_enq_ready),
    .io_enq_valid(q_io_enq_valid),
    .io_enq_bits(q_io_enq_bits),
    .io_deq_ready(q_io_deq_ready),
    .io_deq_valid(q_io_deq_valid),
    .io_deq_bits(q_io_deq_bits)
  );
  assign in_ready = q_io_enq_ready; // @[Decoupled.scala 299:17]
  assign out_valid = q_io_deq_valid; // @[cmd7.sc 4:7]
  assign out_bits = q_io_deq_bits; // @[cmd7.sc 4:7]
  assign q_clock = clock;
  assign q_reset = reset;
  assign q_io_enq_valid = in_valid; // @[Decoupled.scala 297:22]
  assign q_io_enq_bits = in_bits; // @[Decoupled.scala 298:21]
  assign q_io_deq_ready = out_ready; // @[cmd7.sc 4:7]
endmodule

test에 사용하기 위해서는, initSource 및 setSourceClock 메소드를 통해, 제대로 ready-valid 신호가 초기화되었는지 확인사살해줘야 한다.

There is some required boiler plate initSource, setSourceClock, etc that is necessary to ensure that the ready and valid fields are all initialized correctly at the beginning of the test.

test(new QueueModule(UInt(9.W), entries = 200)) { c =>
    // Example testsequence showing the use and behavior of Queue
    c.in.initSource()
    c.in.setSourceClock(c.clock)
    c.out.initSink()
    c.out.setSinkClock(c.clock)
    
    val testVector = Seq.tabulate(200){ i => i.U }

    testVector.zip(testVector).foreach { case (in, out) =>
      c.in.enqueueNow(in)
        println(s"in: $in")
      c.out.expectDequeueNow(out)
        println(s"out: $out")
    }
}

결과

Elaborating design...
Done elaborating.
in: UInt<1>(0)
out: UInt<1>(0)
in: UInt<1>(1)
out: UInt<1>(1)
in: UInt<2>(2)
out: UInt<2>(2)
in: UInt<2>(3)
out: UInt<2>(3)
in: UInt<3>(4)
out: UInt<3>(4)
in: UInt<3>(5)
out: UInt<3>(5)
in: UInt<3>(6)
out: UInt<3>(6)
in: UInt<3>(7)
out: UInt<3>(7)
in: UInt<4>(8)
out: UInt<4>(8)
in: UInt<4>(9)
out: UInt<4>(9)
in: UInt<4>(10)
out: UInt<4>(10)
in: UInt<4>(11)
...
in: UInt<8>(199)
out: UInt<8>(199)
...
test QueueModule Success: 0 tests passed in 402 cycles in 0.149193 seconds 2694.50 Hz

profile
HW SW 둘다 공부하는 혼종의 넋두리 블로그 / SKKU SSE 17 / SWM 11th

0개의 댓글