HDLのRuby実装であるRHDLをさわってみた
FPGAの話を聞いてHDLに興味をもったので、いろいろ調べてレポート書くついでにゴニョゴニョしました。RHDLというのがあったので、本に載ってたサンプルコード(VHDL)をもとにテストを書いて、コードの内容をRubyで書き換えてみました。コードの内容は、16ビットデータのパリティのエンコードです。参考にしたのは以下の本です。
HDLによる高性能ディジタル回路設計―ソフトウェア感覚を離れてハードウェアを意識する (Design Wave BOOKS)
- 作者: 森岡澄夫
- 出版社/メーカー: CQ出版
- 発売日: 2002/10
- メディア: 単行本
- 購入: 2人 クリック: 11回
- この商品を含むブログ (9件) を見る
あと、テストの内容説明は手抜きです。走るのがわかれば良かった。今は反省している。でも面倒なので気にしない。気が向いたら直します。
require 'hardware/RHDL' include RHDL CRC_Enc = model { # 入出力端子の宣言 inputs data_in, start_in, valid_in, reset_n, clk outputs data_out, start_out, valid_out init { # レジスタやノードの宣言 parity_reg = Signal(BitVector(0, 16)) datacnt_reg = Signal(0) STATE_TYPE = EnumType(:waitdata, :calcparity, :outparity) state_reg = Signal(STATE_TYPE) # レジスタ、ノード、出力端子への代入 define_behavior { # 1クロックごとの処理 process(clk) { behavior { if clk.event && clk == 1 if reset_n == 0 state_reg.assign(:waitdata) else case state_reg.inspect when :waitdata if start_in == 1 && valid_in == 1 parity_reg[15].assign(0) parity_reg[14].assign(0) parity_reg[13].assign(0) parity_reg[12].assign(data_in) parity_reg[11].assign(0) parity_reg[10].assign(0) parity_reg[9].assign(0) parity_reg[8].assign(0) parity_reg[7].assign(0) parity_reg[6].assign(0) parity_reg[5].assign(data_in) parity_reg[4].assign(0) parity_reg[3].assign(0) parity_reg[2].assign(0) parity_reg[1].assign(0) parity_reg[0].assign(data_in) datacnt_reg <= 0 state_reg.assign(:calcparity) end when :calcparity if valid_in == 1 comp = parity_reg[15] ^ data_in parity_reg[15].assign(parity_reg[14]) parity_reg[14].assign(parity_reg[13]) parity_reg[13].assign(parity_reg[12]) parity_reg[12].assign(parity_reg[11] ^ comp) parity_reg[11].assign(parity_reg[10]) parity_reg[10].assign(parity_reg[9]) parity_reg[9].assign(parity_reg[8]) parity_reg[8].assign(parity_reg[7]) parity_reg[7].assign(parity_reg[6]) parity_reg[6].assign(parity_reg[5]) parity_reg[5].assign(parity_reg[4] ^ comp) parity_reg[4].assign(parity_reg[3]) parity_reg[3].assign(parity_reg[2]) parity_reg[2].assign(parity_reg[1]) parity_reg[1].assign(parity_reg[0]) parity_reg[0].assign(comp) end if datacnt_reg == 15 datacnt_reg <= 0 state_reg.assign(:outparity) else datacnt_reg <= datacnt_reg + 1 end when :outparity if datacnt_reg == 15 state_reg.assign(:waitdata) else parity_reg[15].assign(parity_reg[14]) parity_reg[14].assign(parity_reg[13]) parity_reg[13].assign(parity_reg[12]) parity_reg[12].assign(parity_reg[11]) parity_reg[11].assign(parity_reg[10]) parity_reg[10].assign(parity_reg[9]) parity_reg[9].assign(parity_reg[8]) parity_reg[8].assign(parity_reg[7]) parity_reg[7].assign(parity_reg[6]) parity_reg[6].assign(parity_reg[5]) parity_reg[5].assign(parity_reg[4]) parity_reg[4].assign(parity_reg[3]) parity_reg[3].assign(parity_reg[2]) parity_reg[2].assign(parity_reg[1]) parity_reg[1].assign(parity_reg[0]) datacnt_reg <= datacnt_reg + 1 end else state_reg.assign(:waitdata) end end end } } # レジスタ、入力端子が変化したときに行われる処理 process(state_reg, parity_reg, data_in, start_in, valid_in) { behavior { data_out <= (state_reg == :outparity ? parity_reg[15] : data_in) start_out <= (start_in * valid_in) valid_out <= (((state_reg == :waitdata && start_in == 1 && valid_in == 1) || (state_reg == :calcparity && valid_in == 1) || state_reg == :outparity) ? 1 : 0) } } } } } require 'rubygems' require 'spec' require 'Simulator' describe "simulate crcenc" do include RHDL include Simulator before(:all) do @data_in = Signal(Bit(0)) @start_in = Signal(Bit(0)) @valid_in = Signal(Bit(0)) @reset_n = Signal(Bit(0)) @clk = Signal(Bit(0)) @data_out = Signal(Bit()) @start_out = Signal(Bit()) @valid_out = Signal(Bit()) @crcenc = CRC_Enc.new(:data_in => @data_in, :start_in => @start_in, :valid_in => @valid_in, :reset_n => @reset_n, :clk => @clk, :data_out => @data_out, :start_out => @start_out, :valid_out => @valid_out) # step { puts "@reset_n = #{@reset_n} : @start_in = #{@start_in} : @valid_in = #{@valid_in} : @data_in = #{@data_in}"; @clk <= @clk.inv } step { @clk <= @clk.inv } step puts '' end it "initial clock check" do @clk.should == 0 @reset_n <= 1 end it "00(reset_n should be 1)" do @reset_n.should == 1 @valid_in <= 1 @start_in <= 1 @data_in <= 1 end it "01" do "#{@valid_out}#{@start_out}#{@data_out}".should == '111' @start_in <= 0 end it "02" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' @data_in <= 0 end it "03" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' @data_in <= 1 end it "04" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "05" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' @data_in <= 0 end it "06" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' @data_in <= 1 end it "07" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "08" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "09" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' @data_in <= 0 end it "10" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' @data_in <= 1 end it "11" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "12" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' @data_in <= 0 end it "13" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "14" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' @data_in <= 1 end it "15" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "16" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' @valid_in <= 0 @data_in <= 0 end it "17" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "18" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "19" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "20" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "21" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "22" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "23" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "24" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "25" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "26" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "27" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "28" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "29" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "30" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end it "31" do "#{@valid_out}#{@start_out}#{@data_out}".should == '100' end it "32" do "#{@valid_out}#{@start_out}#{@data_out}".should == '101' end after do step step puts '' end end