pwmをgolangでシミュレーションする
目的
LPFシミュレータを作成する際に、実際のpwm波形生成してくれる関数郡があるととても助かるため。
え? ModelSim いえ、知らない子ですね。
Virolog HDL 実装
VerilogHDL で記述(更新見込み)
10bit固定
module pwmc (
input wire clk,
input wire [9:0] vq,
output wire pulse
);
reg [9:0] cnt;
wire [10:0] qc = {1'b1, vq} - {1'b0, cnt};
assign pulse = qc[10];
always @(posedge clk) begin
cnt <= cnt + 10'b1;
end
initial begin
cnt = 10'b0;
end
endmodule
こんな感じの回路。
簡単だね。
Go言語実装 1
func xor3
Go言語って3入力XORないんですか?
作っていきます。
真理値表とカルノー図がこちら。
これらより以下の論理関数が導き出せる
y = a\cdot b\cdot c + a\cdot\overline{b}\cdot\overline{c} + \overline{a}\cdot b \cdot\overline{c} + \overline{a}\cdot\overline{b}\cdot c
つまり
func xor3(a, b, c bool) bool {
return a && b && c || a && !b && !c ||
!a && b && !c || !a && !b && c
}
こうですね。
func fullAdder
全加算器もないんですか?
作っていきます。
和
入力a, bについて
各疑似ビットは
ans[i] = xor3(a[i], b[i], キャリーc)
キャリーcは
c = a[i] \cdot b[i] + b[i] \cdot c + c \cdot a[i]
と表せる。
つまり
func fullAdder(a, b []bool) []bool {
ans := make([]bool, len(a))
c := false
for i := 0; i < len(ans); i++ {
ans[i] = xor3(a[i], b[i], c)
c = (a[i] && b[i]) || (b[i] && c) || (c && a[i])
}
return ans
}
こうですね。
func countUp
カウンタ回路作るのに、
インクリメントないんですか?
作っていきます。
fullAdderを使用してもいいのですが、
もう少し簡略化できますね。
func countUp(inp []bool) []bool {
ans := make([]bool, len(inp))
c := true
for i := 0; i < len(ans); i++ {
ans[i] = xor3(inp[i], c, false)
c = inp[i] && c
}
return ans
}
func allFlip
減算回路作るためにすべての疑似ビットを反転させる関数を用意しておきます。
func allFlip(inp []bool) []bool {
ans := make([]bool, len(inp))
for i := 0; i < len(ans); i++ {
ans[i] = !inp[i]
}
return ans
}
func fullSubber
減算回路のための準備が整いました。
真の減算回路ではないのでご注意ください。
func fullSubber(a, b []bool) []bool {
return fullAdder(a, allFlip(b))
}
真の減算回路は以下の記述となります。
func subber(a, b []bool) []bool {
return fullAdder(a, countUp(allFlip(b)))
}
差 = 引かれる数 + ビット反転(引く数)+ 1
func lb
string -> []bool
変換関数。なお、
inp[n] -> ans[0],
inp[0] -> ans[n]
というエンディアン変換(?)も行う。
つまり
"0100"は
inp[0] : 0
inp[1] : 1
inp[2] : 0
inp[3] : 0
であるが、
ans[0] : 0
ans[1] : 0
ans[2] : 1
ans[3] : 0
としてくれる。
ありがたい。
func lb(inp string) []bool {
ans := make([]bool, len(inp))
for i := 0; i < len(ans); i++ {
if inp[len(ans) - 1 - i] == '1' {
ans[i] = true
} else {
ans[i] = false
}
}
return ans
}
pwmc struct
type Pwmc struct {
count []bool
bitWidth int
}
func NewPwmc(bw int) *Pwmc {
ins := new(Pwmc)
ins.bitWidth = bw
ins.count = make([]bool, bw)
return ins
}
func (ins *Pwmc) ClockUp (vq []bool) bool {
qc := fullSubber(
append(vq, lb("1")...), append(ins.count, lb("0")...))
ins.count = countUp(ins.count)
return qc[ins.bitWidth]
}
順に 宣言、コンストラクタ、alwaysブロック
メイン関数
func main() {
num_plot := 50
pwmins := NewPwmc(5)
val_inp := lb ("01000")
for i := 0; i < num_plot; i++ {
if pwmins.ClockUp(val_inp) {
fmt.Println (i, 1)
} else {
fmt.Println (i, 0)
}
}
}
そのままです。
gnuplot
コード群