概要
windowsでiverilogやってみた。
verilogでECU書いてみた。
写真
ECUの仕様
クランクセンサーのみ、36歯1欠
360度で動く
出力は、インジェクターとイグニッションコイル
サンプルコード
module ecu (input wire clk, input wire rst_n, input wire crank_pulse, output reg efi_trigger, output reg ign_trigger);
reg [8:0] crank_angle_360;
reg crank_d1;
wire crank_edge;
reg [19:0] t_count;
reg [19:0] t_last_tooth;
reg sync_ready;
wire missing_tooth_detected;
assign crank_edge = (crank_pulse == 1'b1) && (crank_d1 == 1'b0);
assign missing_tooth_detected = crank_edge && sync_ready && (t_count > (t_last_tooth + (t_last_tooth >> 1)));
initial
begin
$monitor("Angle: %d efi: %d ign: %d", crank_angle_360, efi_trigger, ign_trigger);
end
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
crank_d1 <= 1'b0;
crank_angle_360 <= 9'd0;
t_count <= 20'd0;
t_last_tooth <= 20'd0;
sync_ready <= 1'b0;
end
else
begin
crank_d1 <= crank_pulse;
if (crank_edge)
begin
t_count <= 20'd0;
if (missing_tooth_detected)
begin
crank_angle_360 <= 9'd0;
end
else
begin
t_last_tooth <= t_count;
if (t_count > 20'd10)
begin
sync_ready <= 1'b1;
end
if (crank_angle_360 >= 9'd350)
begin
crank_angle_360 <= 9'd0;
end
else
begin
crank_angle_360 <= crank_angle_360 + 9'd10;
end
end
end
else
begin
if (t_count < 20'hFFFFF)
begin
t_count <= t_count + 20'd1;
end
end
end
end
always @(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
efi_trigger <= 1'b0;
ign_trigger <= 1'b0;
end
else
begin
if (crank_angle_360 == 9'd30)
begin
efi_trigger <= 1'b1;
end
else if (crank_angle_360 == 9'd120)
begin
efi_trigger <= 1'b0;
end
if (crank_angle_360 == 9'd340)
begin
ign_trigger <= 1'b1;
end
else if (crank_angle_360 == 9'd0)
begin
ign_trigger <= 1'b0;
end
end
end
endmodule
テストベンチ
`timescale 1ns / 1ps
module test;
localparam TOOTH_PERIOD = 200000;
integer i;
reg clk;
reg rst_n;
reg crank_pulse;
wire efi_trigger;
wire ign_trigger;
ecu uut (.clk(clk), .rst_n(rst_n), .crank_pulse(crank_pulse), .efi_trigger(efi_trigger), .ign_trigger(ign_trigger));
initial
begin
$dumpfile("test.vcd");
$dumpvars(0, test);
clk = 0;
rst_n = 1;
crank_pulse = 0;
#100;
rst_n = 0;
#100;
rst_n = 1;
$display("--- シミュレーション開始 (36-1歯クランク信号入力) ---");
repeat (3)
begin
for (i = 1; i <= 35; i = i + 1)
begin
crank_pulse = 1;
#(TOOTH_PERIOD / 2);
crank_pulse = 0;
#(TOOTH_PERIOD / 2);
end
$display("[TB] 欠歯エリア通過");
crank_pulse = 0;
#TOOTH_PERIOD;
end
$display("--- シミュレーション終了 ---");
$finish;
end
always
begin
#10
clk = ~clk;
end
endmodule
実行結果
>vvp a.out
VCD info: dumpfile test.vcd opened for output.
Angle: x efi: x ign: x
Angle: 0 efi: 0 ign: 0
--- シミュレーション開始 (36-1歯クランク信号入力) ---
Angle: 10 efi: 0 ign: 0
Angle: 20 efi: 0 ign: 0
Angle: 30 efi: 0 ign: 0
Angle: 30 efi: 1 ign: 0
Angle: 40 efi: 1 ign: 0
Angle: 50 efi: 1 ign: 0
Angle: 60 efi: 1 ign: 0
Angle: 70 efi: 1 ign: 0
Angle: 80 efi: 1 ign: 0
Angle: 90 efi: 1 ign: 0
Angle: 100 efi: 1 ign: 0
Angle: 110 efi: 1 ign: 0
Angle: 120 efi: 1 ign: 0
Angle: 120 efi: 0 ign: 0
Angle: 130 efi: 0 ign: 0
Angle: 140 efi: 0 ign: 0
Angle: 150 efi: 0 ign: 0
Angle: 160 efi: 0 ign: 0
Angle: 170 efi: 0 ign: 0
Angle: 180 efi: 0 ign: 0
Angle: 190 efi: 0 ign: 0
Angle: 200 efi: 0 ign: 0
Angle: 210 efi: 0 ign: 0
Angle: 220 efi: 0 ign: 0
Angle: 230 efi: 0 ign: 0
Angle: 240 efi: 0 ign: 0
Angle: 250 efi: 0 ign: 0
Angle: 260 efi: 0 ign: 0
Angle: 270 efi: 0 ign: 0
Angle: 280 efi: 0 ign: 0
Angle: 290 efi: 0 ign: 0
Angle: 300 efi: 0 ign: 0
Angle: 310 efi: 0 ign: 0
Angle: 320 efi: 0 ign: 0
Angle: 330 efi: 0 ign: 0
Angle: 340 efi: 0 ign: 0
Angle: 340 efi: 0 ign: 1
Angle: 350 efi: 0 ign: 1
[TB] 欠歯エリア通過
Angle: 0 efi: 0 ign: 1
Angle: 0 efi: 0 ign: 0
Angle: 10 efi: 0 ign: 0
Angle: 20 efi: 0 ign: 0
Angle: 30 efi: 0 ign: 0
Angle: 30 efi: 1 ign: 0
Angle: 40 efi: 1 ign: 0
Angle: 50 efi: 1 ign: 0
Angle: 60 efi: 1 ign: 0
Angle: 70 efi: 1 ign: 0
Angle: 80 efi: 1 ign: 0
Angle: 90 efi: 1 ign: 0
Angle: 100 efi: 1 ign: 0
Angle: 110 efi: 1 ign: 0
Angle: 120 efi: 1 ign: 0
Angle: 120 efi: 0 ign: 0
Angle: 130 efi: 0 ign: 0
Angle: 140 efi: 0 ign: 0
Angle: 150 efi: 0 ign: 0
Angle: 160 efi: 0 ign: 0
Angle: 170 efi: 0 ign: 0
Angle: 180 efi: 0 ign: 0
Angle: 190 efi: 0 ign: 0
Angle: 200 efi: 0 ign: 0
Angle: 210 efi: 0 ign: 0
Angle: 220 efi: 0 ign: 0
Angle: 230 efi: 0 ign: 0
Angle: 240 efi: 0 ign: 0
Angle: 250 efi: 0 ign: 0
Angle: 260 efi: 0 ign: 0
Angle: 270 efi: 0 ign: 0
Angle: 280 efi: 0 ign: 0
Angle: 290 efi: 0 ign: 0
Angle: 300 efi: 0 ign: 0
Angle: 310 efi: 0 ign: 0
Angle: 320 efi: 0 ign: 0
Angle: 330 efi: 0 ign: 0
Angle: 340 efi: 0 ign: 0
Angle: 340 efi: 0 ign: 1
[TB] 欠歯エリア通過
Angle: 0 efi: 0 ign: 1
Angle: 0 efi: 0 ign: 0
Angle: 10 efi: 0 ign: 0
Angle: 20 efi: 0 ign: 0
Angle: 30 efi: 0 ign: 0
Angle: 30 efi: 1 ign: 0
Angle: 40 efi: 1 ign: 0
Angle: 50 efi: 1 ign: 0
Angle: 60 efi: 1 ign: 0
Angle: 70 efi: 1 ign: 0
Angle: 80 efi: 1 ign: 0
Angle: 90 efi: 1 ign: 0
Angle: 100 efi: 1 ign: 0
Angle: 110 efi: 1 ign: 0
Angle: 120 efi: 1 ign: 0
Angle: 120 efi: 0 ign: 0
Angle: 130 efi: 0 ign: 0
Angle: 140 efi: 0 ign: 0
Angle: 150 efi: 0 ign: 0
Angle: 160 efi: 0 ign: 0
Angle: 170 efi: 0 ign: 0
Angle: 180 efi: 0 ign: 0
Angle: 190 efi: 0 ign: 0
Angle: 200 efi: 0 ign: 0
Angle: 210 efi: 0 ign: 0
Angle: 220 efi: 0 ign: 0
Angle: 230 efi: 0 ign: 0
Angle: 240 efi: 0 ign: 0
Angle: 250 efi: 0 ign: 0
Angle: 260 efi: 0 ign: 0
Angle: 270 efi: 0 ign: 0
Angle: 280 efi: 0 ign: 0
Angle: 290 efi: 0 ign: 0
Angle: 300 efi: 0 ign: 0
Angle: 310 efi: 0 ign: 0
Angle: 320 efi: 0 ign: 0
Angle: 330 efi: 0 ign: 0
Angle: 340 efi: 0 ign: 0
Angle: 340 efi: 0 ign: 1
[TB] 欠歯エリア通過
--- シミュレーション終了 ---
ecu9.v:133: $finish called at 21600200000 (1ps)
以上。
