AC620FPGA学习笔记——Verilog语法

Verilog语法

对于数字逻辑电路,主要有组合逻辑和时序逻辑
组合逻辑:多路选择器、译码器、加法器、乘法器等等
时序逻辑:计数器

module模块

module mux2(a,b,sel,out);

endmodule 

module: 模块声明(表示module到endmodule之间的内容是描述模块的代码)
mux2: 模块名字(自定义,相当于此模块的名称)
(a,b,sel,out): 括号内是端口列表(类似芯片的引脚定义)

端口类型与位宽

module mux2(a,b,sel,out,io);
	input a;
	input b;
	input sel;
	output out;
	inout io;
endmodule

input a: 表示端口a是输入端口(类似芯片的输入引脚)
output b: 表示端口b是输出端口(类似芯片的输出引脚)
inout io: 表示端口io是双向端口(类似芯片的双向引脚)

module mux2(
	input [7:0] a,
	input [7:0] b,
	input sel,
	output [7:0] out,
	inout io
);

endmodule

与前两个例子功能相同,只是另一种写法,将端口的输入输出描述放入括号内完成
注:input [7:0] a 表示输入端口是一个8bit的总线,相当于8根导线,并且编号为:7 6 5 4 3 2 1 0

内部信号

module mux2(
	input [7:0] a,
	input [7:0] b,
	input sel,
	output [7:0] out,
	inout io
);
	wire oe;
	reg ow;
endmodule

wire oe; 表示名称为oe内部信号(相当于芯片内部的一根导线)
reg ow; 表示名称为ow内部信号(相当于芯片内部的一位寄存器)
注:导线不存在存储功能,只有连接功能,所以对于时序逻辑电路无法使用wire型的信号,而组合逻辑电路无法使用reg型变量,但在Verilog语法中任何处于always中的信号均应为reg型

连续赋值语句

module mux2(
	input [7:0] a,
	input [7:0] b,
	input sel,
	output [7:0] out,
	inout io
);
	wire oe;
	assign out = sel ? a : b;
	
	assign oe = sel;
	assign io = oe ? out[0] : 1'bz;
endmodule

assign out = xxx: 将等号右边组合逻辑(xxx)的输出与导线out相连接(对于连续赋值语句assign,只能是wire型的信号)
sel ? a : b: 组合逻辑,sel 为1 输出a 反之输出b
1’bz: 一个高阻态(z)信号
4’b1001; 表示4位二进制1001
4’d9; 表示4位十进制9
4’hc; 表示4位十六进制c
32’hff_00_ff_00 表示32位十六进制ff00ff00

位操作

module mux2(
	input [7:0] a,
	input [7:0] b,
	input sel,
	output [7:0] out,
	inout io
);
	wire oe;
	assign out = sel ? a : b;
	
	assign oe = sel;
	assign io = oe ? out[0] : 1'bz;

	wire [2:0]m;
	assign m = out[5:3];
	//reg [7:0]shift_a;
	//shift_a <= {shift_a[0],shift_a[7:1]};

	wire [3:0] x;
	wire [3:0] y;
	wire [7:0] z;
	z = {x,y};
	z = {2{x}};

	
endmodule 

截取

assign m = out[5:3]; 将out总线编号为:5 4 3的导线连接到总线m上(默认连接到m的 2 1 0号导线上)

移位

shift_a <= {shift_a[0],shift_a[7:1]}; 时序逻辑内的操作,每次右移一位(循环右移)。
将shift_a总线重新拼接
右移0次shift_a的导线编号:7 6 5 4 3 2 1 0
右移1次shift_a的导线编号:0 7 6 5 4 3 2 1
右移2次shift_a的导线编号:1 0 7 6 5 4 3 2
.
.
.

拼接

z = {x,y}; 将x与y总线进行拼接
拼接前: x( 3 2 1 0 ) y( 3 2 1 0 )
拼接后: z( 7 6 5 4 3 2 1 0 )
其中z[7]与x[3]相接
z[3]与y[3]相接,以此类推

z = {2{x}}; 等效于z = {x,x};
同理z = {3{x}};等效于z = {x,x,x};

运算

对于语法来说+ - * / 四则运算是可以通过的
但是在实际应用中由于资源有限,对于乘法和除法尽量使用加减法和移位代替,尤其是除法操作,可以使用IP核

逻辑运算

&& 逻辑与
|| 逻辑或
! 逻辑非
& 按位与
| 按位或
~ 按位非

时序逻辑

module counter(
	clk,
	en,
	clr,
	cnt_value
);
	input clk;		//时钟信号
	input en;	//使能信号
	input clr;		//清零信号
	
	output [3:0] cnt_value;
	
	reg [3:0] cnt;	//4位计数用寄存器

	always@(posedge clk or posedge clr)	//clk上升沿触发 或 clr上升沿触发
	if(clr)
		cnt <= 4'b0;
	else if(en) begin
		cnt <= cnt + 1'b1;
	end
	assign cnt_value = cnt;


endmodule

always@(posedge clk or posedge clr) 表示时序逻辑部分,posedge为上升沿,negedge为下降沿
注:同一个信号禁止同时出现上升与下降的触发

Test Bench

用于对编写好的moudle进行功能测试所编写的逻辑,仅用在仿真验证环节

`timescale 1ns/1ns
`define clk_period 10
module counter_tb;
	
	reg clk_t;
	reg en_t;
	reg clr_t;

	wire [7:0]cnt_value_t;


	counter counter_1(
		.clk(clk_t),
		.en(en_t),
		.clr(clr_t),
		.cnt_value(cnt_value_t[7:4])
	);

	counter counter_2(
		.clk(clk_t),
		.en(en_t),
		.clr(clr_t),
		.cnt_value(cnt_value_t[3:0])
	);

	initial clk_t = 1;	//初始化clk_t的值
	always #(`clk_period/2) clk_t = ~clk_t;
	//always表示循环
	initial begin
		en_t = 0;
		clr_t = 0;

		#(`clk_period*20)	//延时

		ent_t = 1;

		#(`clk_period*200)

		ent_t = 0;

		#(`clk_period*200)

		clr_t = 1;

		#(`clk_period*200)
		
		clr_t = 0;

		#(`clk_period*200)
		
		$stop;
	end
endmodule

timescale 第一个参数表示步进,第二个表示精度,一般写成相同的
`define clk_period 10 重定义,与C语言相同
counter counter_1 类似C++中类的实例化,counter是类名,counter_1是实例化后的名称

随机数

myrand = {$random};	
myrand2 = {$random} % 65536;	// 0 - 65535
myrand3 = $random % 65536;		//-65535 - 65535

花括号类似绝对值

测试Task

task press_key
	begin
		...
	end
end task

类似C语言中的函数,press_key是函数名
调用的时候很简单,如下:

always@(posedge press)
	press_key;

循环repeat

repeat(50) begin
	myrand = {$random} % 65536;
	#myrand key = ~key;
end

循环指定次数,例子中是循环50次

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: FPGA是一种可编程逻辑器件,可以通过编程实现各种功能。而Verilog是一种硬件描述语言,用于描述FPGA中的电路。Verilog基础语法包括模块定义、端口定义、信号定义、赋值语句、条件语句、循环语句等。模块定义是Verilog中最基本的语法,用于定义一个电路模块。端口定义用于定义模块的输入输出端口。信号定义用于定义模块内部的信号。赋值语句用于给信号赋值。条件语句用于根据条件执行不同的代码。循环语句用于重复执行一段代码。掌握Verilog基础语法学习FPGA编程的基础。 ### 回答2: FPGA是一种可编程逻辑器件,它可以通过硬件描述语言来编写自定义的逻辑电路来实现各种功能。其中,Verilog是一种常用的硬件描述语言,有助于实现FPGA的功能。 Verilog语言主要由模块、端口、信号、语句和运算符五个基本部分组成。模块是Verilog中的最基本的语法单元,类似于传统程序语言中的函数,模块之间可以通过实例化进行连接。端口则是与外部世界进行通信的接口,可以分为输入端口(input)和输出端口(output)两种类型。信号是Verilog中表示数字信号的基本单元,可以是位向量、整数或实数。语句则是Verilog中描述操作和行为的语言,常用的语句包括赋值语句、分支语句和循环语句。运算符则是Verilog中用于进行操作的符号,包括算数运算符、逻辑运算符和位运算符。 在Verilog语言中,还有一些常用的结构体和命令可以帮助我们更方便地实现FPGA的功能。其中,常用的结构体包括always语句、case语句和module归档,常用的命令包括initial语句、wire语句和reg语句。always语句可以在指定的触发条件下执行某一段代码,case语句可以根据不同的条件执行不同的代码段,module归档则可以将多个模块合并为一个模块。initial语句可用于在仿真开始前初始化某些信号,wire语句则用于声明并连接信号,reg语句则用于声明并存储信号。 总体而言,了解FPGAVerilog基础语法可以帮助我们更好地理解FPGA技术的应用和实现。然而,理论知识只有结合实际操作和实验才能更好地掌握。所以,我们还需要结合实际项目来进行练习和实践,从而更好地掌握FPGAVerilog基础语法。 ### 回答3: FPGA(可编程门阵列)是一种可编程逻辑器件,可以用来创建定制的数字电路。Verilog是一种硬件描述语言,用于描述数字电路的结构和行为。 Verilog基础语法有以下几个部分: 1.模块定义:Verilog代码以模块的形式进行组织,每个模块都有一个名称和端口列表。模块定义以module关键字开始,以endmodule关键字结束。 2.端口声明:模块的端口是输入和输出连接到其他模块或FPGA芯片的引脚。端口可以是输入(input)、输出(output)或双向(inout)。端口声明在模块定义中。 3.信号声明:信号是描述数字电路中状态的变量。可以是单个位(wire)或多位(reg),在模块中声明。 4.赋值语句:用来为信号赋值,包括非阻塞赋值(<=)、阻塞赋值(=)和连续赋值(assign)。 5.条件分支语句:if, else if和else语句是用来控制程序流程,实现条件判断。 6.循环语句:Verilog支持for、while、do while和forever等类型的循环语句,可以在程序中实现迭代操作。 7.模块实例化:用来将其他模块作为子模块嵌入到当前模块中,从而实现复杂的数字电路。 除上述基本语法外,Verilog还有其他常用语法,如always块、initial块和function定义等。需要深入了解和使用Verilog,可以参考相关资料和教程。掌握了Verilog语法,可以使用FPGA搭建各种个性化的数字电路,用于嵌入式系统、数字信号处理、计算机网络等各种应用领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值