*참고
Tilelink의 경우 valid = true후 ready가 오지 않더라도 valid를 false로 바꾸고 끝낼 수 있도록 설계되어있다. 이 때문에 아래 나오게될 "Decoupled" 를 기반으로 한 readyValid IO를 사용한다.
AXI protocol의 경우 valid = true후 ready가 올때까지 대기해야만한다. 따라서 valid = false가 되지 않도록 해야하므로
"Irrevocable"를 기반으로 한 readyValid IO를 사용한다.
Valid
- valid
- bits
Decoupled
- valid
- bits
- ready
- fire - Bool that is true if and only if ready & valid
- enq(data) - Sends data and sets valid to true (doesn't check ready)
- noenq - Sets valid to false
- deq/nodeq - Like enq/noenq for receiver
Decoupled 선언시 아래와 같이 ready/valid/bits 3개가 port 선언됨
<> : biconnection 에 대한 동작
Flipped : input output의 상태를 바꿔줌
위와 같이 연결한다면
특정 대상에 대한 in/output 상태를 flipped로 감싸면 정확히 반대가 된 상태이므로 <>를 사용하여 위와 같이 쉽게 연결할 수 있음
위와 같이 연결하면,
위와 같이 한번에 연결 가능함
Like Wire Assign : Manual Assign wire of bit Width
class Reducer(n: Int, m: Int) extends Module {
class BundleIO extends Bundle{
val in: Vec[UInt] = Input(Vec(n, UInt(m.W)))
val out: UInt = Output(UInt((m + 1).W))
}
val io: BundleIO = IO(new BundleIO())
require(n > 0)
// val totalSoFar = Seq.fill(n - 1)(Wire(UInt((m + 1).W)))
// var totalSoFar: UInt = io.in(0)
// totalSoFar.pad(5)
var totalSoFar2: UInt = Wire(UInt(3.W))
totalSoFar2 := io.in(0)
// totalSoFar2.pad(5)
for (i <- 1 until n)
totalSoFar2 = io.in(i) + totalSoFar2
io.out := totalSoFar2
}
Decoupled 선언시,
val decup = Decoupled(UInt())
output인 bits, valid를 반드시 정의해주어야한다
ready는 선택사항
Flipped(Decoupled)면 ready를 반드시 지정해주어야함
가능예제
Decoupled
val io = IO(new Bundle {
val decup = Decoupled(UInt())
})
io.decup.bits := 5.U
io.decup.valid := true.B
Flipped(Decoupled)
val io = IO(new Bundle {
val decup = Flipped(Decoupled(UInt(5.W)))
})
io.decup.ready := true.B
Vec 를 IO로 썼을때, 예제1,
Vec는 IO의 for문 같은 존재임
class ArbiterTest(n: Int, m: Int) extends Module {
val io = IO(new Bundle {
val req = Flipped(Vec(5, Decoupled(UInt(10.W))))
})
io.req(0).ready := true.B
io.req(1).ready := true.B
io.req(2).ready := true.B
io.req(3).ready := true.B
io.req(4).ready := true.B
// val arb = Module(new Arbiter(UInt(n.W), 10))
}
module ArbiterTest(
input clock,
input reset,
output io_req_0_ready,
input io_req_0_valid,
input [9:0] io_req_0_bits,
output io_req_1_ready,
input io_req_1_valid,
input [9:0] io_req_1_bits,
output io_req_2_ready,
input io_req_2_valid,
input [9:0] io_req_2_bits,
output io_req_3_ready,
input io_req_3_valid,
input [9:0] io_req_3_bits,
output io_req_4_ready,
input io_req_4_valid,
input [9:0] io_req_4_bits
);
assign io_req_0_ready = 1'h1; // @[ArbiterTest.scala 16:19]
assign io_req_1_ready = 1'h1; // @[ArbiterTest.scala 17:19]
assign io_req_2_ready = 1'h1; // @[ArbiterTest.scala 18:19]
assign io_req_3_ready = 1'h1; // @[ArbiterTest.scala 19:19]
assign io_req_4_ready = 1'h1; // @[ArbiterTest.scala 20:19]
endmodule
Vec 를 IO로 썼을때, 예제2
class ArbiterTest(n: Int, m: Int) extends Module {
val io = IO(new Bundle {
val req = Vec(5, Decoupled(UInt(10.W)))
})
io.req(0).bits := 10.U
io.req(1).bits := 10.U
io.req(2).bits := 10.U
io.req(3).bits := 10.U
io.req(4).bits := 10.U
io.req(0).valid := true.B
io.req(1).valid := true.B
io.req(2).valid := true.B
io.req(3).valid := true.B
io.req(4).valid := true.B
}
module ArbiterTest(
input clock,
input reset,
input io_req_0_ready,
output io_req_0_valid,
output [9:0] io_req_0_bits,
input io_req_1_ready,
output io_req_1_valid,
output [9:0] io_req_1_bits,
input io_req_2_ready,
output io_req_2_valid,
output [9:0] io_req_2_bits,
input io_req_3_ready,
output io_req_3_valid,
output [9:0] io_req_3_bits,
input io_req_4_ready,
output io_req_4_valid,
output [9:0] io_req_4_bits
);
assign io_req_0_valid = 1'h1; // @[ArbiterTest.scala 19:19]
assign io_req_0_bits = 10'ha; // @[ArbiterTest.scala 13:18]
assign io_req_1_valid = 1'h1; // @[ArbiterTest.scala 20:19]
assign io_req_1_bits = 10'ha; // @[ArbiterTest.scala 14:18]
assign io_req_2_valid = 1'h1; // @[ArbiterTest.scala 21:19]
assign io_req_2_bits = 10'ha; // @[ArbiterTest.scala 15:18]
assign io_req_3_valid = 1'h1; // @[ArbiterTest.scala 22:19]
assign io_req_3_bits = 10'ha; // @[ArbiterTest.scala 16:18]
assign io_req_4_valid = 1'h1; // @[ArbiterTest.scala 23:19]
assign io_req_4_bits = 10'ha; // @[ArbiterTest.scala 17:18]
endmodule
<> biconnect 연결 예제 1
class InnerModule extends Module(){
val io = IO(new Bundle {
val intermediateDecoupled = Flipped(Decoupled(UInt(5.W)))
val intermediateDecoupledOut = Decoupled(UInt())
})
io.intermediateDecoupled.ready := true.B
io.intermediateDecoupledOut.valid := io.intermediateDecoupled.ready
io.intermediateDecoupledOut.bits := io.intermediateDecoupled.bits
}
class ArbiterTest(n: Int, m: Int) extends Module {
val io = IO(new Bundle {
val in = Flipped(Decoupled(UInt(n.W)))
val out = Decoupled(UInt(n.W))
})
val innerModuler = Module(new InnerModule)
innerModuler.io.intermediateDecoupled <> io.in
io.out <> innerModuler.io.intermediateDecoupledOut
}
Flipped는 Flipped와 <> 되고
unFlipped 는 unFlipped와 <> 됨
<> biconnect 연결 예제 2
class InnerModule extends Module(){
val io = IO(new Bundle {
val in11 = Input(UInt(5.W))
val out11 = Output(UInt(5.W))
val out12 = Output(UInt(5.W))
})
val w = Wire(UInt(5.W))
io.in11 <> io.out11
w <> io.in11
io.out12 <> (w +& 10.U)
}
class ArbiterTest(n: Int, m: Int) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(n.W))
val enable = Input(Bool())
val out = Output(UInt(n.W))
val out2 = Output(UInt(n.W))
val out3 = Flipped(Decoupled(UInt(m.W)))
val vecin = Input(Vec(6, UInt(5.W)))
val vecout = Flipped(Input(Vec(6, UInt(5.W))))
})
private val inner = Module(new InnerModule())
inner.io.in11 <> io.in
io.out <> inner.io.out11
io.out2 <> inner.io.out12
io.out3.ready <> io.enable
val mediator = Wire(Vec(6, UInt(5.W)))
mediator <> io.vecin
io.vecout <> mediator
}
object ArbiterTest extends App{
(new ChiselStage).emitVerilog(new ArbiterTest(8,15))
//(new ChiselStage).emitVerilog(f.asInstanceOf[RawModule])
val targetDir = "test_run_dir/gcd"
(new ElkStage).execute(
Array("-td", targetDir),
Seq(ChiselGeneratorAnnotation(() => new ArbiterTest(8,15)))
)
}
<>로 input과 output을 연결할 수 있고, input/input도 연결할 수 있고, output/output도 연결할 수 있고 wire/input, wire/output도 가능하다.
module InnerModule(
input [4:0] io_in11,
output [4:0] io_out11,
output [4:0] io_out12
);
wire [5:0] _io_out12_T = io_in11 + 5'ha; // @[ArbiterTest.scala 21:18]
assign io_out11 = io_in11; // @[ArbiterTest.scala 19:11]
assign io_out12 = _io_out12_T[4:0]; // @[ArbiterTest.scala 21:12]
endmodule
module ArbiterTest(
input clock,
input reset,
input [7:0] io_in,
input io_enable,
output [7:0] io_out,
output [7:0] io_out2,
output io_out3_ready,
input io_out3_valid,
input [14:0] io_out3_bits,
input [4:0] io_vecin_0,
input [4:0] io_vecin_1,
input [4:0] io_vecin_2,
input [4:0] io_vecin_3,
input [4:0] io_vecin_4,
input [4:0] io_vecin_5,
output [4:0] io_vecout_0,
output [4:0] io_vecout_1,
output [4:0] io_vecout_2,
output [4:0] io_vecout_3,
output [4:0] io_vecout_4,
output [4:0] io_vecout_5
);
wire [4:0] inner_io_in11; // @[ArbiterTest.scala 35:29]
wire [4:0] inner_io_out11; // @[ArbiterTest.scala 35:29]
wire [4:0] inner_io_out12; // @[ArbiterTest.scala 35:29]
InnerModule inner ( // @[ArbiterTest.scala 35:29]
.io_in11(inner_io_in11),
.io_out11(inner_io_out11),
.io_out12(inner_io_out12)
);
assign io_out = {{3'd0}, inner_io_out11}; // @[ArbiterTest.scala 38:10]
assign io_out2 = {{3'd0}, inner_io_out12}; // @[ArbiterTest.scala 39:11]
assign io_out3_ready = io_enable; // @[ArbiterTest.scala 40:17]
assign io_vecout_0 = io_vecin_0; // @[ArbiterTest.scala 42:22 43:12]
assign io_vecout_1 = io_vecin_1; // @[ArbiterTest.scala 42:22 43:12]
assign io_vecout_2 = io_vecin_2; // @[ArbiterTest.scala 42:22 43:12]
assign io_vecout_3 = io_vecin_3; // @[ArbiterTest.scala 42:22 43:12]
assign io_vecout_4 = io_vecin_4; // @[ArbiterTest.scala 42:22 43:12]
assign io_vecout_5 = io_vecin_5; // @[ArbiterTest.scala 42:22 43:12]
assign inner_io_in11 = io_in[4:0]; // @[ArbiterTest.scala 37:17]
endmodule
Flipped, <> Wiring, Reg 응용 예제
class InnerModule extends Module(){
val io = IO(new Bundle {
val in11 = Input(UInt(5.W))
val out11 = Output(UInt(5.W))
val out12 = Output(UInt(5.W))
})
val w = Wire(UInt(5.W))
io.in11 <> io.out11
w <> io.in11
io.out12 <> (w +& 10.U)
}
class ArbiterTest(n: Int, m: Int) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(n.W))
val enable = Input(Bool())
val out = Output(UInt(n.W))
val out2 = Output(UInt(n.W))
val out3 = Flipped(Decoupled(UInt(m.W)))
val vecin = Input(Vec(6, UInt(5.W)))
val vecout = Flipped(Input(Vec(6, UInt(5.W))))
// val req = Flipped(Vec(n, Decoupled(UInt(n.W))))
})
private val inner = Module(new InnerModule())
inner.io.in11 <> io.in
io.out <> inner.io.out11
io.out2 <> inner.io.out12
io.out3.ready <> io.enable
val mediator = Wire(Vec(6, UInt(5.W)))
mediator <> io.vecin
// io.vecout <> mediator
val regs = Mem(6, UInt(64.W))
// regs <> mediator
for (p <- 0 until 6) {
regs(p) := mediator(p)
}
for (p <- 0 until 6) {
when(regs(p) > 5.U){
io.vecout(p) := regs(p)
}.otherwise{
if(p != 0)
{
io.vecout(p) := regs(p-1)
}
else{
io.vecout(p) := regs(p)
}
}
}
}
generating된 모델 일부