FPGA入门——纯组合逻辑电路

1.FPGA纯组合逻辑电路

二选一选择器

1. 编写HDL描述文件
module ux2(   //所有的verilog都是从module开始的 module 模块名 (端口名1,端口名2)
  a,
  b, //端口名
  sel,
  out
);
//端口定义
  input a;
  input b;    //这里只用输入 输出端口  无inout输入输出端口
  input sel;
  output out;
//端口功能
  
  //assign out = (sel == 1)? b:a;   //assign持续赋值语句
  assign out = sel ? b:a;

endmodule

2.编写测试脚本(testbench)
`timescale  1ns/1ns   //`timescale是Verilog中的预编译指令,指定位于它后边的module的时间单位和时间精度,直到遇到新的`timescale指令或者aresetall指令ms
module ux2_tb(); 
 //定义激励源  数据类型
   reg a1;  //a     寄存器型(reg)
	reg a2;   //b的激励源
   reg a3;   //sel的
	wire   a4;   //out的   连线型(wire)
	  
	  
	
	ux2 ux2_0(  //ux2第一次例化  第一次仿真
	//端口列表
  .a(a1),  //加点表示例化 ()里加激励源
  .b(a2),    
  .sel(a3),
  .out(a4)
	
	);
 //verilog中有两种结构化的过程语句:initial语句和always语句
 initial begin
   a1=0;a2=0;a3=0;
	
	#100;
	a1=1;a2=0;a3=0;
	
	#100;
	a1=0;a2=1;a3=0;
	
	#100;
	a1=1;a2=1;a3=0;
	
	#100;
	a1=0;a2=0;a3=1;
	
	#100;
	a1=1;a2=0;a3=1;
	
	#100;
	a1=0;a2=1;a3=1;
	
	#100;
	a1=1;a2=1;a3=1;
	 
	#100
	$stop;
	
 end
 
endmodule

同步时序逻辑电路

计数器

时序逻辑电路是指电路任何时刻的稳态输出不仅取决于当前的输入,还与前一时刻输入形成的状态有关。这跟组合逻辑电路相反。时序逻辑拥有储存元件来储存信息,而组合逻辑则没有。

1.编写计数器HDL描述文件
module shixu_led_second(
  //端口列表
   Clk50M, //时钟  时序逻辑电路必须要有时钟
	 Rst_n, //复位 仿真时信号初始化信号初始值
    led //连接LED灯
);
parameter  CNT_MAX = 25'd24_999_999;  //定义参数

//端口定义
   input Clk50M;
	input Rst_n;
	output reg[3:0]led; //4个LED灯  默认为wire线性型 在always中用reg 
   reg [24:0]count;	//寄存器类型计数 25位  计数器计数25_000_000  从0开始计数到24_999_999 
	

	
	/*******************端口功能 计数器 同步时序逻辑电路用always******************/
	always@(posedge Clk50M or negedge Rst_n)  //总是关注上升沿Clk50M或者下降沿Rst_n
	if(!Rst_n)  //满足复位端为低电平就清零
	  count <= 25'd0; //非阻塞赋值方式
	  else if(count == 25'd24_999_999) //判断计数器是否计满
        count <= 25'd0;	  //25表示最大位宽 25位   25位宽 d数据进制 0数值
			 else  
			 count <= count + 1'b1;  
			
	/**************** led输出******存储状态用时序逻辑*************************/
	always@(posedge Clk50M or negedge Rst_n)
	 if(!Rst_n)
	   led <= 4'b1111;
	   else if(count == 25'd24_999_999)
        led <= ~led;		//两种取反 逻辑取反和按位取反
	    else  
		   led <= led; 

endmodule




   d 十进制   b 二进制  h 16进制    d'128=h'80=b'10000000


		  led <= 4'b1111;  逻辑取反             led <= 4'b1101; 按位取反
		  led <= !led;                                   led <= ~led;
		   led <= 0;                                      led <= 4'b0010;
		  led <= !led;
		   led <=1; 	  
2.编写计数器测试脚本

描述仿真时间精度timescale声明。
新建Verilog HDL File文件。

`timescale 1ns/1ns  //仿真时间精度
`define clock_period  20   //周期宏定义

module shixu_led_second_tb;

   reg Clk50M;
	reg Rst_n;         //激励源
	wire [3:0]led;     //输出 线性

  shixu_led_second  
  #(
  .CNT_MAX (25'd2499) //在仿真文件中定义参数
   )
  
  shixu_led_second1(   //第0号模块

   .Clk50M(Clk50M), //例化 端口
	.Rst_n(Rst_n),   //被测试模块
   .led(led) 

);
  //产生激励信号 产生50MHZ频率的周期信号
  //50MHz的方波,就是指方波的频bai率是50MHz,或者说,每秒钟范围内,有50M个方波波形。换句话说,就是大约1/50 = 0.02微秒 = 20纳秒,有一个方波
  initial Clk50M = 1;
  always #(`clock_period/2) Clk50M = ~Clk50M;
  
  //复位信号
  initial begin
    
	 Rst_n = 0;//复位端高电平清零 低电平计数
    #(`clock_period*20+1) Rst_n=1;        //上升沿后异步计数 清零后开始计数
	 #(`clock_period*25000000*6);
	 $stop;

  end

endmodule

在仿真中shixu_led_second_tb文件为顶层,参数CNT_MAX 为2499
在编译中shixu_led_second文件为顶层,参数CNT_MAX为24_999_999
在时序仿真时不支持仿真文件shixu_led_second_tb中的参数
RTL视图

查看代码综合出来的电路结构
tools>Netlist Viewers>RTL Viewer
在这里插入图片描述

移位操作

4个LED灯按照流水的方式闪烁

方式1
module shixu_led_second(
  //端口列表
   Clk50M, //时钟  时序逻辑电路必须要有时钟
	 Rst_n, //复位 仿真时信号初始化信号初始值
    led //连接LED灯
);

//端口定义
   input Clk50M;
	input Rst_n;
	output   [3:0]led; //4个LED灯  默认为wire线性型 在always中用reg 
	
   reg [24:0]count;	//寄存器类型计数 25位  计数器计数25_000_000  从0开始计数到24_999_999 
	
	parameter  CNT_MAX = 25'd24_999_999;  //定义参数
	
	//    d 十进制   b 二进制  h 16进制    d'128=h'80=b'10000000
	
	/*******************端口功能 计数器 同步时序逻辑电路用always******************/
	always@(posedge Clk50M or negedge Rst_n)  //总是关注上升沿Clk50M或者下降沿Rst_n 触发器
	if(!Rst_n)  //满足复位端为低电平就清零
	  count <= 25'd0; //非阻塞赋值方式
	  else if(count == CNT_MAX) //判断计数器是否计满
        count <= 25'd0;	  //25表示最大位宽 25位   25位宽 d数据进制 0数值
			 else  
			 count <= count + 1'b1;  	
			 		
   reg [3:0]led_r;
   
	always@(posedge Clk50M or negedge Rst_n)
	 if(!Rst_n)
	   led_r  <= 4'b0001;  
  else if(count == CNT_MAX) 	begin  //每一个 always 模块,都需要有 begin -- end 来确定起始和结束。
     if(led_r == 4'b1000)                //分支语句 if~else、case,每一个模块都需要 begin -- end 来确定起始和结束。
	    led_r <= 4'b0001;              //if中一行代码可以不用begin
		 else
		 led_r <= led_r << 1;
	end 
	else  led_r <= led_r;
	
  	assign led = ~led_r; //组合逻辑输出
		                      
		


endmodule

方式2 :位拼接
module shixu_led_second(
  //端口列表
   Clk50M, //时钟  时序逻辑电路必须要有时钟
	 Rst_n, //复位 仿真时信号初始化信号初始值
    led //连接LED灯
);

//端口定义
   input Clk50M;
	input Rst_n;
	output   [3:0]led; //4个LED灯  默认为wire线性型 在always中用reg 
	
   reg [24:0]count;	//寄存器类型计数 25位  计数器计数25_000_000  从0开始计数到24_999_999 
	
	parameter  CNT_MAX = 25'd24_999_999;  //定义参数
	
	//    d 十进制   b 二进制  h 16进制    d'128=h'80=b'10000000
	
	/*******************端口功能 计数器 同步时序逻辑电路用always******************/
	always@(posedge Clk50M or negedge Rst_n)  //总是关注上升沿Clk50M或者下降沿Rst_n 触发器
	if(!Rst_n)  //满足复位端为低电平就清零
	  count <= 25'd0; //非阻塞赋值方式
	  else if(count == CNT_MAX) //判断计数器是否计满
        count <= 25'd0;	  //25表示最大位宽 25位   25位宽 d数据进制 0数值
			 else  
			 count <= count + 1'b1;  
			
	/**************** led输出******存储状态用时序逻辑*************************/

always@(posedge Clk50M or negedge Rst_n)
	 if(!Rst_n)
	   led_r  <= 4'b0001;  
  else if(count == CNT_MAX) 	
    led_r <= {led_r[2:0],led_r[3]};  //低位移到高位,高位移到低位
	else  led_r <= led_r;
	
  	assign led = ~led_r; //组合逻辑输出
		                      
		


endmodule


4个LED灯以不同频率闪亮
module shixu_led_second(
  //端口列表
   Clk50M, //时钟  时序逻辑电路必须要有时钟
	 Rst_n, //复位 仿真时信号初始化信号初始值
    led0, //连接LED灯
	 led1,
	 led2,
	 led3
);

//端口定义
   input Clk50M;
	input Rst_n;
	//output   [3:0]led; //4个LED灯  默认为wire线性型 在always中用reg 
	
	output  reg led0;
	output  reg led1;
	output  reg led2;
	output  reg led3;
	
	
   reg [24:0]count;	//寄存器类型计数 25位  计数器计数25_000_000  从0开始计数到24_999_999 
	reg [24:0]count1;
	reg [24:0]count2;
	reg [24:0]count3;
	
	parameter  CNT_MAX =  25'd24_999_999;  //定义参数  24_999_999为500ms  12,499,999为250ms   49,999,999为1s   99,999,999为2秒
	parameter  CNT_MAX1 = 25'd12_499_999;
	parameter  CNT_MAX2 = 25'd49_999_999;
	parameter  CNT_MAX3 = 25'd99_999_999;
	
	//    d 十进制   b 二进制  h 16进制    d'128=h'80=b'10000000
	

	always@(posedge Clk50M or negedge Rst_n)  //250ms
	if(!Rst_n)
	 count1 <= 25'd0;
	  else if(count1 == CNT_MAX1)
	   count1 <= 25'd0;
		 else count1 <= count1 + 1'b1;
		 
	always@(posedge Clk50M or negedge Rst_n)  //1s
	if(!Rst_n)
	 count2 <= 25'd0;
	  else if(count2 == CNT_MAX2)
	   count2 <= 25'd0;
		 else count2 <= count2 + 1'b1;
	
	always@(posedge Clk50M or negedge Rst_n)  //2s
	if(!Rst_n)
	 count3 <= 25'd0;
	  else if(count3 == CNT_MAX3)
	   count3 <= 25'd0;
		 else count3 <= count3 + 1'b1;
	
	/*******************端口功能 计数器 同步时序逻辑电路用always******************/
	always@(posedge Clk50M or negedge Rst_n)  //总是关注上升沿Clk50M或者下降沿Rst_n 触发器  500ms
	if(!Rst_n)  //满足复位端为低电平就清零
	  count <= 25'd0; //非阻塞赋值方式
	  else if(count == CNT_MAX) //判断计数器是否计满
        count <= 25'd0;	  //25表示最大位宽 25位   25位宽 d数据进制 0数值
			 else  
			 count <= count + 1'b1;  
			
/**************** led4个同时亮******存储状态用时序逻辑*************************
	always@(posedge Clk50M or negedge Rst_n)
	 if(!Rst_n)
	   led <= 4'b1111;
	   else if(count == CNT_MAX)
        led <= ~led;		//两种取反 逻辑取反和按位取反
	    else  
		   led <= led;
***************************************************************************/ 
 //  reg [3:0]led_r;
/*******************************流水灯写法1********************************************************
	always@(posedge Clk50M or negedge Rst_n)
	 if(!Rst_n)
	   led_r  <= 4'b0001;  
  else if(count == CNT_MAX) 	begin  //每一个 always 模块,都需要有 begin -- end 来确定起始和结束。
     if(led_r == 4'b1000)                //分支语句 if~else、case,每一个模块都需要 begin -- end 来确定起始和结束。
	    led_r <= 4'b0001;  
		 else
		 led_r <= led_r << 1;
	end 
	else  led_r <= led_r;
assign led = ~led_r; //组合逻辑输出
***********************************************************************************************/
/*****************************流水灯写法2***********************************************************
always@(posedge Clk50M or negedge Rst_n)
	 if(!Rst_n)
	   led_r  <= 4'b0001;  
  else if(count == CNT_MAX) 	
    led_r <= {led_r[2:0],led_r[3]};  //低位移到高位,高位移到低位
	else  led_r <= led_r;
	
  	assign led = ~led_r; //组合逻辑输出
******************************************************************************/                   

  always@(posedge Clk50M or negedge Rst_n) //250ms
	 if(!Rst_n)
	   led0  <= 1'b1;  
  else if(count1 == CNT_MAX1) 	
      led0 <= ~led0;  //低位移到高位,高位移到低位
	else  led0 <= led0;
	
	always@(posedge Clk50M or negedge Rst_n) //500ms
	 if(!Rst_n)
	   led1  <= 1'b1;  
  else if(count == CNT_MAX) 	
      led1 <= ~led1;  //低位移到高位,高位移到低位
	else  led1 <= led1;
	
	always@(posedge Clk50M or negedge Rst_n) //1s
	 if(!Rst_n)
	   led2  <= 1'b1;  
  else if(count2 == CNT_MAX2) 	
      led2 <= ~led2;  //低位移到高位,高位移到低位
	else  led2 <= led2;
	
		always@(posedge Clk50M or negedge Rst_n) //2s
	 if(!Rst_n)
	   led3  <= 1'b1;  
  else if(count3 == CNT_MAX3) 	
      led3 <= ~led3;  //低位移到高位,高位移到低位
	else  led3 <= led3;
	
  	
		


endmodule




RTL视图

在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值