いろいろ疑問はあるのですが。。。。とりあえず、log2のfloorをverilogで実装しました。C言語で記述すると、
#include <math.h>
int32_t out_val =floor(log2(val));
これをverilogで実装します。
module clog2(
input clk,
input reset_n,
input [18:0] val,
output reg [31:0] out_val
);
reg [31:0] clog2 = 32'h0;
reg [18:0] in_val;
always @(posedge clk, negedge reset_n) begin
if (!reset_n) begin
out_val = 32'h0;
end else begin
in_val = val;
for (clog2=0; in_val>0; clog2=clog2+1) begin
in_val = in_val>>1;
end
out_val = clog2 - 1;
end
end
forの中で、演算結果を利用しているので、ブロッキングで記述しているが、順序回路で、ブロッキングで書いていいのか不安。。。。
次は、verilatorのテストコード
#include <iostream>
#include <verilated.h>
#include "Vclog2.h"
#include <verilated_fst_c.h>
#include <math.h>
int time_counter = 0;
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
// Instantiate DUT
Vclog2 *dut = new Vclog2();
// Trace DUMP ON
Verilated::traceEverOn(true);
VerilatedFstC* tfp = new VerilatedFstC;
dut->trace(tfp, 100); // Trace 100 levels of hierarchy
tfp->open("simx.fst");
// Format
dut->reset_n = 0;
dut->clk = 0;
// Reset Time
while (time_counter < 10) {
dut->eval();
tfp->dump(time_counter); // 波形ダンプ用の記述を追加
time_counter++;
}
// Release reset
dut->reset_n = 1;
dut->val=0;
while (time_counter < 4000 && !Verilated::gotFinish()) {
dut->clk = !dut->clk; // Toggle clock
if (dut->clk)
dut->val++;
// Evaluate DUT
dut->eval();
if (dut->clk) {
int c_lang_result = (int)floor(log2(dut->val));
if (c_lang_result != dut->out_val) {
printf("%d %d %f %f\n", dut->val, dut->out_val, floor(log2(dut->val)), log2(dut->val));
}
}
tfp->dump(time_counter); // 波形ダンプ用の記述を追加
time_counter++;
}
dut->final();
tfp->close();
dut->val++;のところ、最初、clkが1、0で両方で実行していたので、結果が期待通りにならなかった。入力値を買えるところもclkを意識しないとね。
ビルド方法
verilator --cc --exe --trace-fst --trace-params --trace-structs --trace-underscore \
clog2.v -exe test_clog2.cpp
make -C obj_dir -f Vclog2.mk
実行は、
./obj_dir/Vclog2
で、行います。
実装したコードは、こちらになります。