Skip to content

Instantly share code, notes, and snippets.

@mirichi
Created June 6, 2015 03:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mirichi/233fc39c2f4e971aa86b to your computer and use it in GitHub Desktop.
Save mirichi/233fc39c2f4e971aa86b to your computer and use it in GitHub Desktop.
deadbeefを順にA~Dレジスタに書き込む命令をROMに書いたコード
require './hsim'
# 1bitデータ2つを1bitで選択するマルチプレクサ(スリーステートバッファ版)
class Mux1_1
def initialize
@tsb1 = ThreeStateBuffer.new
@tsb2 = ThreeStateBuffer.new
@bus = Bus.new
@not = NOT.new
@bus.add(@tsb1)
@bus.add(@tsb2)
@tsb1.g = @not.o
end
def s=(v)
@not.a = @tsb2.g = v
end
def d0=(v)
@tsb1.d = v
end
def d1=(v)
@tsb2.d = v
end
def o
@bus.o
end
def inspect
"#{HLHASH[@bus.o.get]}"
end
end
# 4bitデータ2つを1bitで選択するマルチプレクサ
class Mux1_4
def initialize
@mux3 = Mux1_1.new
@mux2 = Mux1_1.new
@mux1 = Mux1_1.new
@mux0 = Mux1_1.new
end
def s=(v)
@mux3.s = v
@mux2.s = v
@mux1.s = v
@mux0.s = v
end
def d0=(v)
@mux3.d0 = v[0]
@mux2.d0 = v[1]
@mux1.d0 = v[2]
@mux0.d0 = v[3]
end
def d1=(v)
@mux3.d1 = v[0]
@mux2.d1 = v[1]
@mux1.d1 = v[2]
@mux0.d1 = v[3]
end
def o
[
@mux3.o,
@mux2.o,
@mux1.o,
@mux0.o
]
end
def inspect
"#{HLHASH[@mux3.o.get]}"+
"#{HLHASH[@mux2.o.get]}"+
"#{HLHASH[@mux1.o.get]}"+
"#{HLHASH[@mux0.o.get]}"
end
end
# 8bitデータ2つを1bitで選択するマルチプレクサ
class Mux1_8
def initialize
@mux7 = Mux1_1.new
@mux6 = Mux1_1.new
@mux5 = Mux1_1.new
@mux4 = Mux1_1.new
@mux3 = Mux1_1.new
@mux2 = Mux1_1.new
@mux1 = Mux1_1.new
@mux0 = Mux1_1.new
end
def s=(v)
@mux7.s = v
@mux6.s = v
@mux5.s = v
@mux4.s = v
@mux3.s = v
@mux2.s = v
@mux1.s = v
@mux0.s = v
end
def d0=(v)
@mux7.d0 = v[0]
@mux6.d0 = v[1]
@mux5.d0 = v[2]
@mux4.d0 = v[3]
@mux3.d0 = v[4]
@mux2.d0 = v[5]
@mux1.d0 = v[6]
@mux0.d0 = v[7]
end
def d1=(v)
@mux7.d1 = v[0]
@mux6.d1 = v[1]
@mux5.d1 = v[2]
@mux4.d1 = v[3]
@mux3.d1 = v[4]
@mux2.d1 = v[5]
@mux1.d1 = v[6]
@mux0.d1 = v[7]
end
def o
[
@mux7.o,
@mux6.o,
@mux5.o,
@mux4.o,
@mux3.o,
@mux2.o,
@mux1.o,
@mux0.o
]
end
def inspect
"#{HLHASH[@mux7.o.get]}"+
"#{HLHASH[@mux6.o.get]}"+
"#{HLHASH[@mux5.o.get]}"+
"#{HLHASH[@mux4.o.get]}"+
"#{HLHASH[@mux3.o.get]}"+
"#{HLHASH[@mux2.o.get]}"+
"#{HLHASH[@mux1.o.get]}"+
"#{HLHASH[@mux0.o.get]}"
end
end
# 8bitデータ4つを2bitで選択するマルチプレクサ
class Mux2_8
def initialize
@mux0 = Mux1_8.new
@mux1 = Mux1_8.new
@mux2 = Mux1_8.new
@mux2.d0 = @mux0.o
@mux2.d1 = @mux1.o
end
def s=(v)
@mux0.s = v[1]
@mux1.s = v[1]
@mux2.s = v[0]
end
def d0=(v)
@mux0.d0 = v
end
def d1=(v)
@mux0.d1 = v
end
def d2=(v)
@mux1.d0 = v
end
def d3=(v)
@mux1.d1 = v
end
def o
@mux2.o
end
def inspect
"#{HLHASH[@mux2.o[0].get]}"+
"#{HLHASH[@mux2.o[1].get]}"+
"#{HLHASH[@mux2.o[2].get]}"+
"#{HLHASH[@mux2.o[3].get]}"
end
end
# 8bit*4の容量を持つROM
class ROM32bit
def initialize
@mux = Mux2_8.new
@tsb7 = ThreeStateBuffer.new
@tsb6 = ThreeStateBuffer.new
@tsb5 = ThreeStateBuffer.new
@tsb4 = ThreeStateBuffer.new
@tsb3 = ThreeStateBuffer.new
@tsb2 = ThreeStateBuffer.new
@tsb1 = ThreeStateBuffer.new
@tsb0 = ThreeStateBuffer.new
@not = NOT.new
@tsb7.d = @mux.o[0]
@tsb6.d = @mux.o[1]
@tsb5.d = @mux.o[2]
@tsb4.d = @mux.o[3]
@tsb3.d = @mux.o[4]
@tsb2.d = @mux.o[5]
@tsb1.d = @mux.o[6]
@tsb0.d = @mux.o[7]
@tsb7.g = @not.o
@tsb6.g = @not.o
@tsb5.g = @not.o
@tsb4.g = @not.o
@tsb3.g = @not.o
@tsb2.g = @not.o
@tsb1.g = @not.o
@tsb0.g = @not.o
end
# アドレス線(2本)
def a=(v)
@mux.s = [v[0], v[1]]
end
# チップセレクト
def csb=(v)
@not.a = v
end
# 保持データの接続
def d=(v)
@mux.d0 = [v[0][0], v[0][1], v[0][2], v[0][3], v[0][4], v[0][5], v[0][6], v[0][7]]
@mux.d1 = [v[1][0], v[1][1], v[1][2], v[1][3], v[1][4], v[1][5], v[1][6], v[1][7]]
@mux.d2 = [v[2][0], v[2][1], v[2][2], v[2][3], v[2][4], v[2][5], v[2][6], v[2][7]]
@mux.d3 = [v[3][0], v[3][1], v[3][2], v[3][3], v[3][4], v[3][5], v[3][6], v[3][7]]
end
# 出力(スリーステートバッファ)
def o
[
@tsb7,
@tsb6,
@tsb5,
@tsb4,
@tsb3,
@tsb2,
@tsb1,
@tsb0
]
end
def inspect
"#{HLHASH[@tsb7.o.get]}"+
"#{HLHASH[@tsb6.o.get]}"+
"#{HLHASH[@tsb5.o.get]}"+
"#{HLHASH[@tsb4.o.get]}"+
"#{HLHASH[@tsb3.o.get]}"+
"#{HLHASH[@tsb2.o.get]}"+
"#{HLHASH[@tsb1.o.get]}"+
"#{HLHASH[@tsb0.o.get]}"
end
end
# 2bitの入力から4bitのどれかを選択してHにするセレクタ
class Selector2
def initialize
@and3 = AND.new
@and2 = AND.new
@and1 = AND.new
@and0 = AND.new
@not0 = NOT.new
@not1 = NOT.new
@and2.a = @not0.o
@and1.b = @not1.o
@and0.a = @not0.o
@and0.b = @not1.o
end
def s=(v)
@not0.a = v[1]
@not1.a = v[0]
@and3.a = v[1]
@and3.b = v[0]
@and1.a = v[1]
@and2.b = v[0]
end
def o
[
@and3.o,
@and2.o,
@and1.o,
@and0.o
]
end
def inspect
"#{HLHASH[@and3.o.get]}"+
"#{HLHASH[@and2.o.get]}"+
"#{HLHASH[@and1.o.get]}"+
"#{HLHASH[@and0.o.get]}"
end
end
# 4bitレジスタ
class Register4
def initialize
@dff3 = DFF.new
@dff2 = DFF.new
@dff1 = DFF.new
@dff0 = DFF.new
@mux = Mux1_4.new
@mux.d0 = self.o
@dff3.d = @mux.o[0]
@dff2.d = @mux.o[1]
@dff1.d = @mux.o[2]
@dff0.d = @mux.o[3]
end
def clk=(v)
@dff3.clk = v
@dff2.clk = v
@dff1.clk = v
@dff0.clk = v
end
def d=(v)
@mux.d1 = v
end
# writeが1
def rw=(v)
@mux.s = v
end
def clrb=(v)
@dff3.clrb = v
@dff2.clrb = v
@dff1.clrb = v
@dff0.clrb = v
end
def o
[
@dff3.q,
@dff2.q,
@dff1.q,
@dff0.q,
]
end
def inspect
"#{HLHASH[@dff3.q.get]}"+
"#{HLHASH[@dff2.q.get]}"+
"#{HLHASH[@dff1.q.get]}"+
"#{HLHASH[@dff0.q.get]}"
end
end
vcc = OutputPin.new(H)
gnd = OutputPin.new(L)
# deadROM
dead_rom = ROM32bit.new
dead_rom.d = [
[gnd, gnd, vcc, vcc, gnd, vcc, gnd, gnd], # mov a, 0xd
[gnd, gnd, vcc, vcc, vcc, gnd, gnd, vcc], # mov b, 0xe
[gnd, gnd, vcc, gnd, vcc, gnd, vcc, gnd], # mov c, 0xa
[gnd, gnd, vcc, vcc, gnd, vcc, vcc, vcc] # mov d, 0xd
]
# beefROM
beef_rom = ROM32bit.new
beef_rom.d = [
[gnd, gnd, vcc, gnd, vcc, vcc, gnd, gnd], # mov a, 0xb
[gnd, gnd, vcc, vcc, vcc, gnd, gnd, vcc], # mov b, 0xe
[gnd, gnd, vcc, vcc, vcc, gnd, vcc, gnd], # mov c, 0xe
[gnd, gnd, vcc, vcc, vcc, vcc, vcc, vcc] # mov d, 0xf
]
# データバス
bus7 = Bus.new
bus6 = Bus.new
bus5 = Bus.new
bus4 = Bus.new
bus3 = Bus.new
bus2 = Bus.new
bus1 = Bus.new
bus0 = Bus.new
# チップセレクト用
_not = NOT.new
# クロックとクリアの入力線
clk = Line.new
clrb = Line.new
# 4bitカウンタ
c4 = Counter4.new
c4.clk = clk.o
c4.clrb = clrb.o
# ROMにカウンタの値を接続
dead_rom.a = [c4.o[2], c4.o[3]]
dead_rom.csb = c4.o[1]
beef_rom.a = [c4.o[2], c4.o[3]]
beef_rom.csb = _not.o
_not.a = c4.o[1]
# ROMの出力はThreeStateBufferなのでBusオブジェクトにaddする
bus7.add dead_rom.o[0]
bus7.add beef_rom.o[0]
bus6.add dead_rom.o[1]
bus6.add beef_rom.o[1]
bus5.add dead_rom.o[2]
bus5.add beef_rom.o[2]
bus4.add dead_rom.o[3]
bus4.add beef_rom.o[3]
bus3.add dead_rom.o[4]
bus3.add beef_rom.o[4]
bus2.add dead_rom.o[5]
bus2.add beef_rom.o[5]
bus1.add dead_rom.o[6]
bus1.add beef_rom.o[6]
bus0.add dead_rom.o[7]
bus0.add beef_rom.o[7]
# 4bitレジスタabcd作成
rega = Register4.new
regb = Register4.new
regc = Register4.new
regd = Register4.new
rega.clk = regb.clk = regc.clk = regd.clk = clk.o
rega.clrb = regb.clrb = regc.clrb = regd.clrb = clrb.o
# レジスタに書き込みする値はROM内の命令のbit5~bit2
rega.d = regb.d = regc.d = regd.d = [bus5.o, bus4.o, bus3.o, bus2.o]
# 2bitセレクタ
sel = Selector2.new
# セレクタの入力はROM内の命令のbit1~bit0
sel.s = [bus1.o, bus0.o]
# セレクタの出力はレジスタのrwに繋ぐ
rega.rw = sel.o[3]
regb.rw = sel.o[2]
regc.rw = sel.o[1]
regd.rw = sel.o[0]
# 簡易ロジックアナライザ
require 'dxruby'
module LogicAnalyzer
@@probes = []
def self.probes
@@probes
end
class Probe < Struct.new(:name, :outpin)
end
def self.analyze(&b)
f = Fiber.new(&b)
buf = []
# 実行
while f.resume(:la) != :la
tmp = []
@@probes.each do |pr|
tmp.push(pr.outpin.get)
end
buf.push(tmp)
end
image = Image.new(640, 480)
size = 480 / @@probes.size
font = Font.new(size)
x = @@probes.map{|v|font.get_width(v.name)}.max + 15
# 画像作成
@@probes.each.with_index do |pr, i|
image.draw_font(10, i * size, pr.name, font)
tmp = false
buf.each.with_index do |b, j|
if tmp != b[i]
image.line(j * 10 + x, i * size + 8, j * 10 + x, i * size + size - 1, C_WHITE)
end
image.line(j * 10 + x, i * size + (b[i] ? 8 : size - 1), j * 10 + x + 10, i * size + (b[i] ? 8 : size - 1), C_WHITE)
tmp = b[i]
end
end
Window.loop do
Window.draw(0, 0, image)
break if Input.key_push?(K_ESCAPE)
end
end
end
# プローブ接続
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("clk", clk.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b0", bus0.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b1", bus1.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b2", bus2.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b3", bus3.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b4", bus4.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("d b5", bus5.o)
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b0", rega.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b1", rega.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b2", rega.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("areg b3", rega.o[0])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b0", regb.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b1", regb.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b2", regb.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("breg b3", regb.o[0])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b0", regc.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b1", regc.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b2", regc.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("creg b3", regc.o[0])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b0", regd.o[3])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b1", regd.o[2])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b2", regd.o[1])
LogicAnalyzer::probes << LogicAnalyzer::Probe.new("dreg b3", regd.o[0])
# アナライズ
LogicAnalyzer.analyze do
clk.d = L
clrb.d = H
clrb.d = L
clrb.d = H
Fiber.yield
9.times do
clk.d = L
Fiber.yield
clk.d = H
Fiber.yield
end
:la
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment