Initial commit
This commit is contained in:
@@ -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])
|
||||
Reference in New Issue
Block a user