【Verilog零基础入门-边看边练】学习笔记——第六讲 时序逻辑代码设计和仿真(相邻点累加)

一、相邻点累加逻辑设计

所需软件

Verilog编程软件:Lattice Diamond(3.11.0.396.4_Diamond_x64)

Verilog仿真软件:ModelSim SE-64 10.2c(modelsim-win64-10.2c-se)

方法:用always语句块、组合逻辑实现相邻16点累加逻辑设计

符号图: 

时序图:

 

Verilog代码:

Part1:Test13_sigma_16p.v文件(Verilog工程文件)

//2022-06-02
//相邻16点累加
//逻辑:对输入的信号进行补码运算,之后对得到的补码进行升位运算,升位之后再进行16点的相加,最后输出

//定义端口 时序逻辑:时钟,复位
module Test13_sigma_16p(
					clk,				//因为是时序逻辑,所有包含时钟clk和复位res
					res,
					data_in,			//采样数据(输入的信号,为8位带符号位的原码)
					syn_in,				//采样时钟
					data_out,			//累加和(输出累加结果,为补码)
					syn_out				//累加和同步脉冲(为一个系统时钟周期宽度的脉冲)
					);
					
//定义端口属性					
input				clk;				//系统时钟(因为是时序逻辑,所以包含时钟clk和复位res)
input				res;
input[7:0]			data_in;			//采样数据(输入的信号,为8位带符号位的原码),在采样时钟syn_in的上升沿变化
input				syn_in;				//采样时钟
output[11:0]		data_out;			//累加和(输出累加结果,为补码):data_in在相邻16点相加得到data_out,并由syn_out同步
output				syn_out;			//累加和同步脉冲(为一个系统时钟周期宽度的脉冲)

reg					syn_in_n1;			//采样时钟syn_in的反向延时
wire				syn_pulse;			//采样脉冲尖(用作采样时钟上升沿识别脉冲)

assign				syn_pulse=syn_in&syn_in_n1;		//采样脉冲尖:采样时钟syn_in和采样时钟的反向延时syn_in_n1的“与”
reg[3:0]			con_syn;			//采样时钟脉冲尖循环计数值(采样时钟循环计数器)
wire[7:0]			comp_8;				//输入的信号的补码
wire[11:0]			d_12;				//输入的信号的补码进行升位运算后的结果

//补码运算
assign				comp_8=data_in[7]?{data_in[7],~data_in[6:0]+1}:data_in;	//对输入的信号进行补码运算,补码运算值赋给comp_8

//升位运算:正数,前面扩展4个0;负数,前面扩展4个1;即对符号位的复制
assign				d_12={comp_8[7],comp_8[7],comp_8[7],comp_8[7],comp_8};	//对输入的信号的补码comp_8进行升位运算
reg[11:0]			sigma;				//对输入的信号的补码进行升位运算后,对升位运算结果进行16点的累加计算
reg[11:0]			data_out;			//16点的累加计算的累加和(系统输出值)
reg					syn_out;			//累加和同步脉冲

//一旦定义了一个触发器,就需要对它复位
always@(posedge clk or negedge res)	
if(~res) begin							//复位信号下降沿,reg型变量清零
	syn_in_n1<=0;						//清零 采样时钟syn_in的反向延时syn_in_n1也需要进行复位
	con_syn<=0;							//清零 采样时钟循环计数器
	sigma<=0;data_out<=0;
	syn_out<=0;
end
	else begin
		syn_in_n1<=~syn_in;				//syn_in_n1为采样时钟syn_in的反向延时
		if(syn_pulse) begin				//若采样脉冲尖syn_pulse为高电平(是脉冲尖)
			con_syn<=con_syn+1;			//则对循环计数脉冲尖con_syn进行计数(基于系统时钟的计数,但是在波形图上,计数基于采样脉冲尖)
		end
		
		if(syn_pulse) begin				//若采样脉冲尖syn_pulse为高电平(是脉冲尖)
			if(con_syn==15)begin		//若循环计数脉冲尖con_syn(采样时钟循环计数器=)的个数达到15个
				sigma<=d_12;			//保留当前时刻输入信号(将输入的信号的补码进行升位运算的运算结果赋给sigma)
				data_out<=sigma;		//输出之前时钟计数15内输入信号累加结果(将输入的信号的补码进行升位运算的最终(累加15次)运算结果赋给系统输出变量data_out)
				syn_out<=1;				//将累加和同步脉冲syn_out置为高电平1
			end
			else begin
				sigma<=sigma+d_12;		//累和输入信号(对输入的信号的补码的升位运算值d_12进行累加计算)
			end
				
		end		
		else begin
			syn_out<=0;					//累加和同步脉冲syn_out为低电平0(使为高电平时的syn_out是一个尖、data_out一直保持)。
		end
	end
endmodule

Part2:Test13_sigma_16p_tb.v文件(Verilog仿真文件)

//2022-06-02
//相邻16点累加-testbench of Test13_sigma_16p
`timescale 1ns/10ps
module Test13_sigma_16p_tb;
//输入
reg					clk_in,res_in;
reg[7:0]			data_in;
reg					syn_in;
//输出
wire[11:0]			data_out;
wire				syn_out;

Test13_sigma_16p Test13_sigma_16p(
					.clk(clk_in),			//因为是时序逻辑,所有包含时钟clk和复位res
					.res(res_in),
					.data_in(data_in),		//采样数据(输入的信号)
					.syn_in(syn_in),		//采样时钟
					.data_out(data_out),	//累加和
					.syn_out(syn_out)		//累加和同步脉冲
					);
					
					//验证方法:让输入信号连续等于正1或连续等于负1,看是否能加出来正16或负16
initial begin
					clk_in<=0;res_in<=0;
					data_in<=1;				//令输入信号为正1		//data_in:采样信号,设定其一直为1
//					data_in<=8'b1000_0001;	//令输入信号为负1				
					syn_in<=0;
		#17			res_in<=1;
		#25000		$stop;					//16点一个周期,10ns一个点,160ns一个周期,500ns够
	
end
	
always	#5			clk_in<=~clk_in;		//设置系统时钟,时钟周期为10ns
	
always	#100		syn_in<=~syn_in;		//设置采样时钟,时钟周期为200ns
	
	
endmodule

仿真波形:

1、令输入信号为持续的正1,可得到累加得到正16

【Verilog零基础入门-边看边练】学习笔记——第六讲 时序逻辑代码设计和仿真(相邻点累加)_第1张图片

 2、令输入信号为持续的负1,可得到累加得到负16

【Verilog零基础入门-边看边练】学习笔记——第六讲 时序逻辑代码设计和仿真(相邻点累加)_第2张图片

 

注意事项

1、相邻16点累加逻辑:对输入的信号进行补码运算,之后对得到的补码进行升位运算,升位之后再进行相邻的16点的累加求和并输出;

2、8位升12位的升位运算方法:正数,前面扩展4个0;负数,前面扩展4个1;即对符号位的复制;

3、相邻16点累加逻辑的验证方法:让输入信号连续等于正1或连续等于负1,看是否能加出来正16或负16;

4、在相邻16点累加逻辑的测试代码中,勿忘记既需要设置系统时钟,又需要设置采样时钟;

5、8位二进制的负1可表示为:8'b1000_0001;8位二进制的正1可表示为:1、8'b0000_0001。

原教学视频链接如下

Verilog零基础入门_哔哩哔哩_bilibili 

你可能感兴趣的:(Lattice,学习,fpga开发,硬件工程)