田中太郎
画像を入力して回路で処理し、出力を画像に直すまでを行うテストベンチを作成しました
概要
BMP画像をテストベンチに与えると、8ビットのデータに変換して1クロック毎に回路に与える
回路は画像データを2値化して出力する
出力データが有効のときはvalidがHighになる
入力データをすべて処理し終わるとinterruptがHighになる
テストベンチ
tb.sv
テストベンチ。BMPの画像ファイルを読み込んで回路に与える。
画像処理後のデータを画像データ(BMP)にして保存する
シーケンスは
画像読み込み
→enableを1サイクルHigh
→画像データを1画素ずつ回路に入力
→回路から出力されるvalidがHighのときのデータ(dout)を画像ファイルとして順次書き込み
→回路から出力されるinterruptがHighになったらファイルの書き込みを終了してテストを終了する
module tb;
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, tb);
end
localparam IMG_W = 512;
localparam IMG_H = 512;
int f;
bit [7:0] bmp[54+1024];
bit [7:0] data[IMG_H*IMG_W];
logic [7:0] din;
logic [7:0] dout;
bit enable;
bit valid;
bit interrupt;
bit clk = 0;
bit rst_n = 0;
always #5 clk = ~clk;
initial begin
f = $fopen("rob.bmp", "rb");
$fread(bmp, f, 0, 54+1024);
$fread(data, f, 0, IMG_H*IMG_W);
$fclose(f);
f = $fopen("result.bmp", "wb");
foreach (bmp[i])
$fwrite(f, "%c", bmp[i]);
#50 rst_n = 1;
enable = 1;
fork
foreach (data[i]) begin
din = data[i];
@(posedge clk);
end
join_none
@(posedge clk);
enable = 0;
forever begin
if (valid) begin
$fwrite(f, "%c", dout);
end
@(posedge clk);
if (interrupt) begin
break;
end
end
$fclose(f);
$finish;
end
sample #(
.IMG_W(IMG_W),
.IMG_H(IMG_H)
) u_sample(
.clk(clk),
.rst_n(rst_n),
.enable(enable),
.din(din),
.valid(valid),
.dout(dout),
.interrupt(interrupt)
);
endmodule
画像処理回路
入力されるdinを画像処理してdoutとして出力する
enableがHighになっているときのdinが有効
有効なdoutを出力するときはvalidをHighにする
入力された画像の処理がすべて完了するとinterruptがHighにする
top.sv
DUTのトップ。main.svとctrl.svをインスタンスしている。
module top #(
parameter IMG_W = 512,
parameter IMG_H = 512
)(
input clk,
input rst_n,
input enable,
input [7:0] din,
output logic valid,
output logic [7:0] dout,
output logic interrupt
);
localparam LATENCY = 1; // main回路のレイテンシを設定する
ctrl #(
.IMG_W(IMG_W),
.IMG_H(IMG_H),
.LATENCY(LATENCY)
) i_ctrl(
.clk(clk),
.rst_n(rst_n),
.enable(enable),
.valid(valid),
.interrupt(interrupt)
);
main #(
) i_main(
.clk(clk),
.rst_n(rst_n),
.din(din),
.dout(dout)
);
endmodule
main.sv
画像処理回路。今回の画像処理は2値化。
module main #(
)(
input clk,
input rst_n,
input [7:0] din,
output logic [7:0] dout
);
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
dout <= '0;
end
else begin
if (din > 127) begin
dout <= '1;
end
else begin
dout <= '0;
end
end
end
endmodule
ctrl.sv
制御回路。入力されるenableからvalid, interruptの出力タイミングを制御する
module ctrl #(
parameter IMG_W = 512,
parameter IMG_H = 512,
parameter LATENCY = 1
)(
input clk,
input rst_n,
input enable,
output logic valid,
output logic interrupt
);
logic [18:0] cnt;
logic enable_d;
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
enable_d <= '0;
end
else begin
enable_d <= enable;
end
end
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
cnt <= '1;
end
else begin
if (enable & ~enable_d) begin
cnt <= '0;
end
else if (cnt < IMG_W*IMG_H + LATENCY - 1) begin
cnt <= cnt + 1'b1;
end
end
end
always_comb begin
if (cnt == IMG_W*IMG_H + LATENCY - 1) begin
interrupt = '1;
end
else begin
interrupt = '0;
end
end
always_comb begin
if (LATENCY <= cnt && cnt < IMG_W*IMG_H + LATENCY - 1) begin
valid = '1;
end
else begin
valid = '0;
end
end
endmodule
動作確認
入力
出力
まとめ
画像処理するテストベンチ、回路を作成しました
水平方向に順次処理するような画像処理であれば、main.svのLATENCYをいじれば流用できると思います
コメント