Chiselで分周クロックを作って、RISCVの合成をTiming Metさせました!

先日、Vivadoで合成したら、タイミングMetしませんでした。 そのため、何らかの対策をすることが必要になりました。 それは、パイプライン設計とマルチクロックです。

thira2.hatenablog.com

パイプラインは中々に手間なので、マルチクロックにしようと思いました。 タイミングが貴妃爺RISCVの部分を2分周したクロックで動かすというわけです。

じゃあそうしようと分周器を作しました。 こんな感じで作れました。clock用の型があるのは面白いですね。

  val r_cnt   = RegInit(1.U(div.W))
  val r_clock = RegInit(false.B)
  r_cnt   := r_cnt - 1.U
  r_clock := r_cnt(0)
  io.clock := r_clock.asCloc

で、非同期箇所にメタス対策用のFFを並べようとして気がつきました。 あ、メモリ部分が面倒だ、と。 そうなんです、メモリが高速クロック側と低速クロック側で使われるるため、少々工夫をしないといけないんです。 設計してもいいんですが、めんどくさいなーと思いました。

で、ぼんやりと眺めていて気がつきました。 そもそも全体を低速クロックで動かせばいいじゃんと笑

というわけで、以下で修正してみました。 さて、合成すると。。

mod Top for timing met. · moamoai/chisel_top@b5e8fcc · GitHub

  • chiselで2分周器を作成し、Topに追加
  • Vivadoでcreate_generated_clock制約を以下のように付与
  val clk_div2 = Wire(Clock())
  val i_div2 = Module(new Divider)
  clk_div2 := i_div2.io.clock
withClock (clk_div2) {
-----
}
create_generated_clock -name clk_div2 -source [get_ports clock] -divide_by 2 [get_pins i_div2/r_clock_reg/Q]

ピカリン。Metしました!!

f:id:thira2:20200311010309p:plain

あとがき

Chiselでクロック分ける方法と、Vivadoで分周クロックを使う方法を学びました。 まさかこんなにあっさり動くとは、FPGA/Chiselのツールの出来はすごいです。 やはり、最先端のツールは違います。

といいますが、私がASIC作ってた頃と大分様子が変わっているみたいな気がしてきました。