ROM の設定その2
前からある case の中身を吐くだけのクラスはほぼよいので、ちょっと手直ししてラッピングするものを作った。printf がちょろちょろ混ざってるんで、ヒアドキュメントにできればもうちょっときれいになるものの、わからず。(perl みたく $ を付けるわけではないので #{} かな?)
prefix, assignment, safix に別けたのは同期ROM や SDRAM もどきを継承して作ってしまうため。
class AsyncROM def initialize(data_width, be) @bin = Binary.new(data_width, be, '=') end def Open(file) return @bin.Open(file) end def prefix(f, name) f << '//autogenerated by incdump' f << "\n" f.printf("module %s #(\n", name) f << "\tparameter WAITTIME = 'x\n" f << ")(\n" f.printf("\tinput [%d:0] a, output [%d:0] d, ", @bin.AddressWidth - 1, @bin.DataWidth - 1) f << "input ce, output Wait\n);\n" end def assignment(f, list) f.printf("\tfunction [%d:0] q;\n", @bin.DataWidth - 1) f.printf("\t\tinput [%d:0] a;\n", @bin.AddressWidth - 1) f << "\t\tcase(a)\n" f.printf("default: q = {%d{1'b1}};\n", @bin.DataWidth) i = 0 list.each{|t| @bin.Print(f, t) if(i < 4) i += 1 f << ' ' else i = 0 f << "\n" end } if(i != 0) f << "\n" end f << "\t\tendcase\n\tendfunction\n" end def safix(f) f.printf("\tassign #WAITTIME d = ce == 1'b1 ? {%d{1'bz}} : q(a);\n", @bin.DataWidth) f << "\tassign #WAITTIME Wait = ~ce;\n" f << "endmodule\n" end def Dump(f, modulename, list = nil) prefix(f, modulename) if(list == nil) list = [] @bin.Size.times{|i| list << i } end assignment(f, list) safix(f) end end
これを別途生成アプリから呼ぶことにする。今回は単純にこんな感じ。 list が対象アドレスなんだが、ちょっと微妙かもしれない。VRAM 解析してキャラクタアドレスを算出すると重複しまくるから uniq は必須であろう。
require 'd:/work/verilog/incdump.rb' begin f = File.open(ARGV.shift, "w") f << '`include "timescale.h"' f << "\n" rom = AsyncROM.new(8, false) romlist = ['a10.bin', '11a.bin', '11b.bin'] romlist.each{|romimage| if(rom.Open(romimage) == false) puts romimage + " open error" return end } list = [0, 1, 0x10000] rom.Dump(f, "pcmrom", list) f.close end
こうするとこういう ROM が生成される。
`include "timescale.h" //autogenerated by incdump module pcmrom #( parameter WAITTIME = 'x )( input [18:0] a, output [7:0] d, input ce, output Wait ); function [7:0] q; input [18:0] a; case(a) default: q = {8{1'b1}}; 19'h00000: q = 8'h40; 19'h00001: q = 8'h3d; 19'h10000: q = 8'h40; endcase endfunction assign #WAITTIME d = ce == 1'b1 ? {8{1'bz}} : q(a); assign #WAITTIME Wait = ~ce; endmodule
試しにテストベンチに通してみたところいい感じだ。