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