Initial commit

This commit is contained in:
Myfro9
2026-05-09 01:12:34 -05:00
commit 61b4731d06
44 changed files with 104560 additions and 0 deletions
@@ -0,0 +1,43 @@
{
"eval_id": 0,
"eval_name": "counter8-auto-stim",
"prompt": "我有一个8位计数器模块,文件路径是 counter8.v,请帮我自动生成激励,运行仿真,并将波形保存到 D:/sim_results/counter_waves.csv",
"assertions": [
{
"id": "tb_file_exists",
"text": "生成了 tb_counter8.v testbench 文件"
},
{
"id": "tb_has_dumpfile",
"text": "testbench 包含 $dumpfile 和 $dumpvars,用于 VCD 波形记录"
},
{
"id": "tb_has_clkgen",
"text": "testbench 包含时钟生成逻辑(always #N clk = ~clk)"
},
{
"id": "tb_has_reset",
"text": "testbench 包含复位序列"
},
{
"id": "tb_has_finish",
"text": "testbench 包含 $finish 以正常结束仿真"
},
{
"id": "tcl_file_exists",
"text": "生成了 run_sim.tcl Vivado 批处理脚本"
},
{
"id": "tcl_batch_mode",
"text": "TCL 脚本使用批处理模式(-mode batch)运行"
},
{
"id": "vcd_to_csv_exists",
"text": "提供了 vcd_to_csv.py 波形转换脚本"
},
{
"id": "output_path_correct",
"text": "CSV 输出路径指向用户指定的 D:/sim_results/counter_waves.csv"
}
]
}
@@ -0,0 +1,19 @@
// 8位计数器模块
module counter8 (
input wire clk, // 系统时钟
input wire rst_n, // 低有效复位
input wire en, // 使能信号
output reg [7:0] count, // 计数输出
output wire overflow // 溢出标志(count == 8'hFF)
);
assign overflow = (count == 8'hFF) & en;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
count <= 8'h00;
else if (en)
count <= count + 1'b1;
end
endmodule
@@ -0,0 +1,31 @@
# Vivado 批处理仿真脚本 - 8位计数器
# 由 vivado-sim 技能自动生成
# 创建仿真工程
create_project -force sim_proj ./sim_proj -part xc7a200tfbg676-2
set_property simulator_language Verilog [current_project]
# 添加设计源文件
add_files -norecurse ./counter8.v
# 添加仿真文件
add_files -fileset sim_1 -norecurse ./tb_counter8.v
# 设置顶层仿真模块
set_property top tb_counter8 [get_filesets sim_1]
set_property top_lib xil_defaultlib [get_filesets sim_1]
# 设置仿真时长(100个时钟周期 × 10ns = 1000ns,留一些余量用2000ns)
set_property -name {xsim.simulate.runtime} -value {2000ns} -objects [get_filesets sim_1]
# 启动仿真
launch_simulation
# 运行仿真
run all
# 关闭仿真
close_sim
# 退出 Vivado
exit
@@ -0,0 +1,72 @@
`timescale 1ns/1ps
module tb_counter8;
// ---- 参数 ----
parameter CLK_PERIOD = 10; // 100MHz 时钟,周期 10ns
// ---- 信号声明 ----
reg clk;
reg rst_n;
reg en;
wire [7:0] count;
wire overflow;
// ---- 被测模块例化 ----
counter8 uut (
.clk (clk),
.rst_n (rst_n),
.en (en),
.count (count),
.overflow (overflow)
);
// ---- 时钟生成 ----
initial clk = 0;
always #(CLK_PERIOD/2) clk = ~clk;
// ---- VCD 波形记录 ----
initial begin
$dumpfile("tb_counter8.vcd");
$dumpvars(0, tb_counter8);
end
// ---- 复位与激励 ----
initial begin
// 初始化
rst_n = 0;
en = 0;
// 复位保持 5 个时钟周期
repeat(5) @(posedge clk);
rst_n = 1;
// 使能计数,连续计数 200 个周期
@(posedge clk);
en = 1;
repeat(200) @(posedge clk);
// 暂停使能,观察保持行为
en = 0;
repeat(10) @(posedge clk);
// 重新使能,再计数 60 个周期(观察溢出行为)
en = 1;
repeat(60) @(posedge clk);
// 再次复位
rst_n = 0;
repeat(3) @(posedge clk);
rst_n = 1;
repeat(5) @(posedge clk);
$finish;
end
// ---- 监控关键事件 ----
always @(posedge clk) begin
if (overflow)
$display("[%0t ns] 溢出! count = %0d", $time, count);
end
endmodule
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""将 VCD 波形文件转换为 CSV 格式"""
import re
import csv
import sys
from pathlib import Path
def parse_vcd(vcd_path):
signals = {} # id_char -> (name, width)
changes = [] # (time, id_char, value)
current_time = 0
with open(vcd_path, 'r') as f:
for line in f:
line = line.strip()
if not line:
continue
# 解析信号定义
m = re.match(r'\$var\s+\w+\s+(\d+)\s+(\S+)\s+(\S+)', line)
if m:
width, id_char, name = int(m.group(1)), m.group(2), m.group(3)
signals[id_char] = (name, width)
continue
# 时间戳
m = re.match(r'#(\d+)', line)
if m:
current_time = int(m.group(1))
continue
# 标量变化: 0a 1b xc
m = re.match(r'([01xzXZ])(\S+)', line)
if m:
val, id_char = m.group(1), m.group(2)
if id_char in signals:
changes.append((current_time, id_char, val))
continue
# 向量变化: b1010 a
m = re.match(r'[bB]([01xzXZ_]+)\s+(\S+)', line)
if m:
val_str, id_char = m.group(1).replace('_',''), m.group(2)
if id_char in signals:
changes.append((current_time, id_char, val_str))
continue
return signals, changes
def vcd_to_csv(vcd_path, csv_path):
signals, changes = parse_vcd(vcd_path)
if not signals:
print("未找到信号定义,请检查 VCD 文件")
return
time_events = {}
for t, id_char, val in changes:
if t not in time_events:
time_events[t] = {}
time_events[t][id_char] = val
sig_ids = list(signals.keys())
sig_names = [signals[i][0] for i in sig_ids]
current_vals = {i: 'x' for i in sig_ids}
rows = []
for t in sorted(time_events.keys()):
current_vals.update(time_events[t])
row = {'time_ns': t}
for i, name in zip(sig_ids, sig_names):
row[name] = current_vals[i]
rows.append(row)
if not rows:
print("没有波形数据")
return
fieldnames = ['time_ns'] + sig_names
with open(csv_path, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
print(f"已导出 {len(rows)} 个时间点,{len(sig_names)} 个信号到 {csv_path}")
if __name__ == '__main__':
if len(sys.argv) < 3:
print(f"用法: python vcd_to_csv.py <input.vcd> <output.csv>")
sys.exit(1)
vcd_to_csv(sys.argv[1], sys.argv[2])