文章目录
- 一、认识SystemVerilog
- SystemVerilog的语言特性
- SystemVerilog的应用领域
- SystemVerilog的优势
- SystemVerilog的未来发展方向
- 二、流水灯代码
- 流水灯部分
- testbench仿真文件
- 三、用systemVerilog实现超声波测距
- 计时器
- 测距部分
- led部分
- 数码管部分
- 采样部分
- 顶层文件
- 引脚绑定
- 效果
- 四、SysTemVerilog与verilog的区别
- 1.语言功能的增强
- 2.设计流程的优化
- 3.工具社区的支持
一、认识SystemVerilog
SystemVerilog是一种功能强大的硬件描述语言和验证语言。随着电子设计自动化(EDA)技术的不断进步,以及对数字系统设计和验证要求的提高,SystemVerilog应运而生.
SystemVerilog的语言特性
- 数据类型与建模能力:SystemVerilog提供了丰富的数据类型和强大的建模能力,这使得设计者能够精确地描述硬件的行为和结构。这种高级的数据类型支持,让设计更加灵活且易于理解和维护。
- 面向对象的特性:与传统的Verilog相比,SystemVerilog增加了面向对象编程的概念,如类、继承和多态等。这使得代码模块性更强,更易于管理和复用,大大提高了开发效率和可维护性。
- 并发处理的支持:SystemVerilog支持并发处理,允许设计者模拟真实的硬件并行操作环境,这对于描述复杂的硬件系统至关重要。
- 接口和连接:通过引入接口这一概念,SystemVerilog简化了模块间的通信方式,提高了设计的清晰度和模块间的互操作性。
SystemVerilog的应用领域
- ASIC与FPGA设计:SystemVerilog被广泛应用于ASIC和FPGA的设计流程中,支持从逻辑综合到验证的各个阶段,能够满足不同规模和复杂度的设计需求。
- 验证环境构建:SystemVerilog的验证功能特别强大,它为验证工程师提供了构建全面测试套件和验证环境的能力,特别是在复杂的系统级验证中表现出色。
- 新兴领域的应用:随着技术的发展,SystemVerilog开始在自动驾驶、人工智能、云计算等新兴领域中得到应用,用于构建和验证复杂的系统模型。
SystemVerilog的优势
- 模块化和可重用性:面向对象的特性使得SystemVerilog的设计更加模块化,易于维护和重用,这有助于缩短产品开发周期并降低成本。
- 集成的验证功能:SystemVerilog不仅是一个设计语言,它还集成了丰富的验证功能,如约束随机生成、功能覆盖率分析等,这些都是提高验证效率和质量的关键工具。
- 丰富的生态系统:众多EDA厂商和开源社区的支持,为SystemVerilog提供了强大的工具链和生态系统,从而使得开发者能够更加便捷地进行设计和验证工作。
SystemVerilog的未来发展方向
-
应用领域的拓展:随着技术的进步和市场需求的变化,SystemVerilog预计将进一步拓展其在多个新兴领域的应用,如物联网、5G通信等。
-
语言特性的增强:为了跟上技术发展的步伐,SystemVerilog将持续更新其语言特性,包括增强建模能力、扩展验证功能等,以适应更加复杂的设计需求。
-
工具链的优化与集成:EDA厂商将继续优化SystemVerilog相关工具的性能,提供更加集成化的解决方案,以便为用户提供更加高效和便捷的开发体验。
总之,SystemVerilog作为一种先进的硬件描述和验证语言,它的出现极大地推动了数字系统设计和验证领域的发展。通过提供模块化、面向对象的特性,以及集成的验证功能,SystemVerilog不仅提高了设计的质量和效率,还为应对日益增长的设计复杂性提供了强有力的工具。
二、流水灯代码
流水灯部分
module led_water_light(
input wire clk, // 时钟信号
input wire rst_n, // 复位信号,低电平有效
output reg [7:0] led // 8个LED灯
);
// 内部逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
led <= 8'b00000000; // 复位时所有LED熄灭
end else begin
integer i; // 声明整数变量
for (i = 0; i < 8; i++) begin
led <= (8'b00000001 << i); // 点亮第i位LED
#125; // 等待一个时钟周期,假设为20ns,则0.5s需要250个周期
end
end
end
endmodule
testbench仿真文件
// tb_led_water_light.sv
module tb_led_water_light();
// Parameters
parameter CLK_PERIOD = 20; // 定义时钟周期参数
// Inputs
logic clk;
logic rst_n;
// Outputs
wire [7:0] led;
// 实例化被测试模块
led_water_light uut (
.clk(clk),
.rst_n(rst_n),
.led(led)
);
// 时钟信号生成
always #(CLK_PERIOD / 2) clk = ~clk;
// 测试序列
initial begin
// 初始化信号
clk = 0;
rst_n = 0;
// 等待一个时钟周期
#(CLK_PERIOD * 10);
// 释放复位信号
rst_n = 1;
// 等待足够的时间来观察LED的变化
#(CLK_PERIOD * 1000); // 等待50个时钟周期,即2ms
// 再次触发复位
rst_n = 0;
#(CLK_PERIOD * 10);
rst_n = 1;
// 继续观察LED变化
#(CLK_PERIOD * 1000); // 再次等待50个时钟周期,即2ms
// 结束仿真
$finish;
end
// 监控输出变化
initial begin
$monitor("Time = %t, rst_n = %b, led = %b", $time, rst_n, led);
end
endmodule
这里加速了一下,实际每个灯亮0.5秒
三、用systemVerilog实现超声波测距
关于HC-SR04模块可以参考我之前stm32的博客https://blog.csdn.net/cbm2001/article/details/139374257?spm=1001.2014.3001.5501
下面是代码:
计时器
module clk_us(
input logic clk , //system clock 50MHz
input logic rst_n , //reset ,low valid
output logic clk_us //
);
//Parameter Declarations
parameter CNT_MAX = 19'd50;//1us的计数值为 50 * Tclk(20ns)
//Interrnal wire/reg declarations
logic [5:00] cnt ; //Counter
logic add_cnt ; //Counter Enable
logic end_cnt ; //Counter Reset
//Logic Description
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 'd0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 'd0;
end
else begin
cnt <= cnt + 1'b1;
end
end
else begin
cnt <= cnt;
end
end
assign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt >= CNT_MAX - 19'd1;
assign clk_us = end_cnt;
endmodule
测距部分
module Echo(
input logic clk , //clock 50MHz
input logic clk_us , //system clock 1MHz
input logic rst_n , //reset ,low valid
input logic echo , //
output logic [18:00] data_o //检测距离,保留3位小数,*1000实现
);
/* S(um) = 17 * t --> x.abc cm */
//Parameter Declarations
parameter T_MAX = 16'd60_000;//510cm 对应计数值
//Interrnal wire/reg declarations
logic r1_echo,r2_echo; //边沿检测
logic echo_pos,echo_neg; //
logic [15:00] cnt ; //Counter
logic add_cnt ; //Counter Enable
logic end_cnt ; //Counter Reset
logic [18:00] data_r ;
//Logic Description
//如果使用clk_us 检测边沿,延时2us,差值过大
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
r1_echo <= 1'b0;
r2_echo <= 1'b0;
end
else begin
r1_echo <= echo;
r2_echo <= r1_echo;
end
end
assign echo_pos = r1_echo & ~r2_echo;
assign echo_neg = ~r1_echo & r2_echo;
always @(posedge clk_us or negedge rst_n)begin
if(!rst_n)begin
cnt <= 'd0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= cnt;
end
else begin
cnt <= cnt + 1'b1;
end
end
else begin //echo 低电平 归零
cnt <= 'd0;
end
end
assign add_cnt = echo;
assign end_cnt = add_cnt && cnt >= T_MAX - 1; //超出最大测量范围则保持不变,极限
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
data_r <= 'd2;
end
else if(echo_neg)begin
data_r <= (cnt << 4) + cnt;
end
else begin
data_r <= data_r;
end
end //always end
assign data_o = data_r >> 1;
endmodule
led部分
module Trig(
input logic clk_us , //system clock 1MHz
input logic rst_n , //reset ,low valid
output logic trig //触发测距信号
);
//Parameter Declarations
parameter CYCLE_MAX = 19'd300_000;
//Interrnal wire/reg declarations
logic [18:00] cnt ; //Counter
logic add_cnt ; //Counter Enable
logic end_cnt ; //Counter Reset
//Logic Description
always @(posedge clk_us or negedge rst_n)begin
if(!rst_n)begin
cnt <= 'd0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 'd0;
end
else begin
cnt <= cnt + 1'b1;
end
end
else begin
cnt <= cnt;
end
end
assign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt >= CYCLE_MAX - 9'd1;
assign trig = cnt < 15 ? 1'b1 : 1'b0;
endmodule
数码管部分
module seg(
input logic clk ,
input logic rst_n ,
input logic [18:0] data_o ,
output logic [6:0] hex1 ,
output logic [6:0] hex2 ,
output logic [6:0] hex3 ,
output logic [6:0] hex4 ,
output logic [6:0] hex5 ,
output logic [6:0] hex6 ,
output logic [6:0] hex7 ,
output logic [6:0] hex8
);
parameter NOTION = 4'd10,
FUSHU = 4'd11;
parameter MAX20us = 10'd1000;
logic [9:0] cnt_20us;
logic [7:0] sel_r;
logic [3:0] number;
logic [6:0] seg_r;
logic [6:0] hex1_r;
logic [6:0] hex2_r;
logic [6:0] hex3_r;
logic [6:0] hex4_r;
logic [6:0] hex5_r;
logic [6:0] hex6_r;
logic [6:0] hex7_r;
logic [6:0] hex8_r;
//20微妙计数器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_20us <= 10'd0;
end
else if (cnt_20us == MAX20us - 1'd1) begin
cnt_20us <= 10'd0;
end
else begin
cnt_20us <= cnt_20us + 1'd1;
end
end
//单个信号sel_r位拼接约束
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
sel_r <= 8'b11_11_11_10;
end
else if (cnt_20us == MAX20us - 1'd1) begin
sel_r <= {sel_r[6:0],sel_r[7]};
end
else begin
sel_r <= sel_r;
end
end
/*拿到数字*/
always @(*) begin
case (sel_r)
8'b11_11_11_10: number = NOTION ;
8'b11_11_11_01: number = data_o/10_0000 ;
8'b11_11_10_11: number = (data_o%10_0000)/1_0000 ;
8'b11_11_01_11: number = ((data_o%10_0000)%1_0000)/1000 ;
8'b11_10_11_11: number = FUSHU ;
8'b11_01_11_11: number = (((data_o%10_0000)%1_0000)%1000)/100 ;
8'b10_11_11_11: number = ((((data_o%10_0000)%1_0000)%1000)%100)/10 ;
8'b01_11_11_11: number = ((((data_o%10_0000)%1_0000)%1000)%100)%10 ;
default: number = 4'd0 ;
endcase
end
/*通过数字解析出seg值*/
always @(*) begin
case (number)
4'd0 : seg_r = 7'b100_0000;
4'd1 : seg_r = 7'b111_1001;
4'd2 : seg_r = 7'b010_0100;
4'd3 : seg_r = 7'b011_0000;
4'd4 : seg_r = 7'b001_1001;
4'd5 : seg_r = 7'b001_0010;
4'd6 : seg_r = 7'b000_0010;
4'd7 : seg_r = 7'b111_1000;
4'd8 : seg_r = 7'b000_0000;
4'd9 : seg_r = 7'b001_0000;
NOTION : seg_r = 7'b111_1111;
FUSHU : seg_r = 7'b011_1111;
default : seg_r = 7'b111_1111;
endcase
end
always @(*) begin
case (sel_r)
8'b11_11_11_10: hex1_r = seg_r;
8'b11_11_11_01: hex2_r = seg_r;
8'b11_11_10_11: hex3_r = seg_r;
8'b11_11_01_11: hex4_r = seg_r;
8'b11_10_11_11: hex5_r = seg_r;
8'b11_01_11_11: hex6_r = seg_r;
8'b10_11_11_11: hex7_r = seg_r;
8'b01_11_11_11: hex8_r = seg_r;
default: seg_r = seg_r;
endcase
end
assign hex1 = hex1_r;
assign hex2 = hex2_r;
assign hex3 = hex3_r;
assign hex4 = hex4_r;
assign hex5 = hex5_r;
assign hex6 = hex6_r;
assign hex7 = hex7_r;
assign hex8 = hex8_r;
endmodule
采样部分
module Trig(
input logic clk_us , //system clock 1MHz
input logic rst_n , //reset ,low valid
output logic trig //触发测距信号
);
//Parameter Declarations
parameter CYCLE_MAX = 19'd300_000;
//Interrnal wire/reg declarations
logic [18:00] cnt ; //Counter
logic add_cnt ; //Counter Enable
logic end_cnt ; //Counter Reset
//Logic Description
always @(posedge clk_us or negedge rst_n)begin
if(!rst_n)begin
cnt <= 'd0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 'd0;
end
else begin
cnt <= cnt + 1'b1;
end
end
else begin
cnt <= cnt;
end
end
assign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt >= CYCLE_MAX - 9'd1;
assign trig = cnt < 15 ? 1'b1 : 1'b0;
endmodule
顶层文件
module top (
input logic clk ,
input logic rst_n ,
input logic echo ,
output logic [3:0]led,
output logic trig ,
output logic [6:0] hex1 ,
output logic [6:0] hex2 ,
output logic [6:0] hex3 ,
output logic [6:0] hex4 ,
output logic [6:0] hex5 ,
output logic [6:0] hex6 ,
output logic [6:0] hex7 ,
output logic [6:0] hex8
);
wire [18:0] data_o;
Trig inster_Trig(
.clk_us (clk_us ), //system clock 1MHz
.rst_n (rst_n ), //reset ,low valid
.trig (trig ) //触发测距信号
);
clk_us insert_clk_us(
.clk (clk ),
.rst_n (rst_n),
.clk_us (clk_us)
);
Echo inster_Echo(
.clk (clk ),
.clk_us (clk_us ),
.rst_n (rst_n ),
.echo (echo ),
.data_o (data_o )
);
LED inster_LED(
.clk (clk ) ,
.rst_n (rst_n) ,
.dis (data_o ) ,
.led (led )
);
seg inster_seg(
.clk (clk ) ,
.rst_n (rst_n ) ,
.data_o (data_o) ,
.hex1 (hex1) ,
.hex2 (hex2) ,
.hex3 (hex3) ,
.hex4 (hex4) ,
.hex5 (hex5 ) ,
.hex6 (hex6 ) ,
.hex7 (hex7 ) ,
.hex8 (hex8 )
);
endmodule
引脚绑定
注意HC-SR04模块的连线以自己接线为准
效果
距离<10cm,亮两个灯,那个减号是小数点
距离在10~20cm亮一个灯
距离>20cm,亮三个灯
四、SysTemVerilog与verilog的区别
SystemVerilog并不是与Verilog完全相同,而是Verilog的扩展和超集。虽然SystemVerilog继承了Verilog的基本结构和语法,但是它通过引入面向对象编程、动态线程控制、高层抽象数据类型等先进特性,极大地扩展了Verilog的功能。下面是SystemVerilog相对于Verilog的几个主要差异:
1.语言功能的增强
- 面向对象的特性:SystemVerilog引入了类、继承、多态等面向对象的概念,这不仅提高了代码的重用性和模块化,还使得测试平台的构建更为灵活和强大。
- 并发模型的改进:SystemVerilog提供了fork-join语法,支持更加精细的并发控制,这对于复杂的验证环境尤其重要。
- 数据类型的丰富:除了基本的wire和reg类型,SystemVerilog还新增了如logic、enum、struct等多种数据类型,支持更广泛的设计需求。
- 验证能力的提升
约束随机生成:SystemVerilog支持带约束的随机生成技术,这可以自动产生更多样化的测试场景,极大地提高验证的覆盖率和效率。 - 功能覆盖率分析:内置的功能覆盖率分析工具帮助验证工程师精确地量化验证进度,确保设计满足所有功能要求。
- 断言的支持:通过SVA(SystemVerilog Assertions),SystemVerilog允许设计者在代码中直接嵌入断言,以监测设计行为的特定属性,这对排查问题和确保设计的正确性至关重要。
2.设计流程的优化
- 接口的概念:SystemVerilog中的接口是一种强大的结构,它允许设计者将相关的信号组合在一起,简化模块间的连接,提高设计的清晰度和可维护性。
- 时间精度的控制:SystemVerilog提供了更为精确的时间控制机制,支持从秒到飞秒的多种时间单位,这有助于处理高速设计中的时间精度问题。
3.工具社区的支持
- 更多的工具支持:由于其强大的功能和广泛的应用,多数现代EDA工具都原生支持SystemVerilog,为用户提供了丰富的设计和验证工具链。
- 活跃的开发社区:围绕SystemVerilog形成了一个活跃的开发社区,许多开源项目和论坛都在不断促进这一语言的发展和完善。
,支持更广泛的设计需求。
- 验证能力的提升
约束随机生成:SystemVerilog支持带约束的随机生成技术,这可以自动产生更多样化的测试场景,极大地提高验证的覆盖率和效率。 - 功能覆盖率分析:内置的功能覆盖率分析工具帮助验证工程师精确地量化验证进度,确保设计满足所有功能要求。
- 断言的支持:通过SVA(SystemVerilog Assertions),SystemVerilog允许设计者在代码中直接嵌入断言,以监测设计行为的特定属性,这对排查问题和确保设计的正确性至关重要。