【FPGA】3,先从简单的例子出发,38译码器,LED,流水灯

1,38译码器  http://www.stepfpga.com/doc/altera_3ymq

这样可以跟着学一些语法,比如always

module decode38 (sw,led);
 
	input [2:0] sw;							//开关输入信号,利用了其中3个开关作为3-8译码器的输入
	output [7:0] led;						//输出信号控制特定LED
 
        reg [7:0] led;                                                  //定义led为reg型变量,在always过程块中只能对reg型变量赋值
 
        //always过程块,括号中sw为敏感变量,当sw变化一次执行一次always中所有语句,否则保持不变
	always @ (sw)
	begin
		case(sw)                                                   //case语句,一定要跟default语句
			3'b000:	led=8'b0111_1111;                         //条件跳转,其中“_”下划线只是为了阅读方便,无实际意义  
			3'b001:	led=8'b1011_1111;                         //位宽'进制+数值是Verilog里常数的表达方法,进制可以是b、o、d、h(二、八、十、十六进制)
			3'b010:	led=8'b1101_1111;
			3'b011:	led=8'b1110_1111;
			3'b100:	led=8'b1111_0111;
			3'b101:	led=8'b1111_1011;
			3'b110: led=8'b1111_1101;
			3'b111:	led=8'b1111_1110;
			default: ;
		endcase
	end
 
endmodule
2,数码管显示http://www.stepfpga.com/doc/altera_4seg
了解数组reg [8:0] seg [9:0]; 

module segment (seg_data_1,seg_data_2,seg_led_1,seg_led_2);
 
	input [3:0] seg_data_1;						//数码管需要显示0~9十个数字,所以最少需要4位输入做译码
	input [3:0] seg_data_2;						//小脚丫上第二个数码管
	output [8:0] seg_led_1;						//在小脚丫上控制一个数码管需要9个信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、A
	output [8:0] seg_led_2;						//在小脚丫上第二个数码管的控制信号  MSB~LSB=DIG、DP、G、F、E、D、C、B、A
 
        reg [8:0] seg [9:0];                                            //定义了一个reg型的数组变量,相当于一个10*9的存储器,存储器一共有10个数,每个数有9位宽
 
        initial                                                         //在过程块中只能给reg型变量赋值,Verilog中有两种过程块always和initial
                                                                        //initial和always不同,其中语句只执行一次
	    begin
              seg[0] = 9'h3f;                                           //对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字  0
	      seg[1] = 9'h06;                                           //7段显示数字  1
	      seg[2] = 9'h5b;                                           //7段显示数字  2
	      seg[3] = 9'h4f;                                           //7段显示数字  3
	      seg[4] = 9'h66;                                           //7段显示数字  4
	      seg[5] = 9'h6d;                                           //7段显示数字  5
	      seg[6] = 9'h7d;                                           //7段显示数字  6
	      seg[7] = 9'h07;                                           //7段显示数字  7
	      seg[8] = 9'h7f;                                           //7段显示数字  8
	      seg[9] = 9'h6f;                                           //7段显示数字  9
            end
 
        assign seg_led_1 = seg[seg_data_1];                         //连续赋值,这样输入不同四位数,就能输出对于译码的9位输出
        assign seg_led_2 = seg[seg_data_2];
 
endmodule

3,时钟分频  http://www.stepfpga.com/doc/altera_5clk

https://www.cnblogs.com/halflife/archive/2010/09/26/1836251.html

module divide (	clk,rst_n,clkout);
 
        input 	clk,rst_n;                       //输入信号,其中clk连接到FPGA的C1脚,频率为12MHz
        output	clkout;                          //输出信号,可以连接到LED观察分频的时钟
 
        //parameter是verilog里常数语句
	parameter	WIDTH	= 3;             //计数器的位数,计数的最大值为 2**WIDTH-1
	parameter	N	= 5;             //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出 
 //
N < 2**WIDTH-1=2^3-1=7
reg [ WIDTH - 1 : 0 ] cnt_p , cnt_n ; //cnt_p为上升沿触发时的计数器,cnt_n为下降沿触发时的计数器 reg clk_p , clk_n ; //clk_p为上升沿触发时分频时钟,clk_n为下降沿触发时分频时钟   //上升沿触发时计数器的控制 always @ ( posedge clk or negedge rst_n ) //posedge和negedge是verilog表示信号上升沿和下降沿 //当clk上升沿来临或者rst_n变低的时候执行一次always里的语句 begin if ( ! rst_n ) cnt_p <= 0 ; else if ( cnt_p == ( N - 1 ) ) cnt_p <= 0 ;                //来一次posedge,cnt_p就加1次,这几个always过程块是同时触发的 else cnt_p <= cnt_p + 1 ; //计数器一直计数,当计数到N-1的时候清零,这是一个模N的计数器 end   //上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50% always @ ( posedge clk or negedge rst_n ) begin if ( ! rst_n ) clk_p <= 0 ; else if ( cnt_p < ( N >> 1 ) ) //N>>1表示右移一位,相当于除以2去掉余数。有点意思,以前没注意到这种操作
//注意cnt_p这里是0-N/2时输出低电平,在N/2~N-1时输出高电平
				clk_p<=0;
			else 
				clk_p<=1;               //得到的分频时钟正周期比负周期多一个clk时钟
		end
 
        //下降沿触发时计数器的控制        	
	always @ (negedge clk or negedge rst_n)
		begin
			if(!rst_n)
				cnt_n<=0;
			else if (cnt_n==(N-1))
				cnt_n<=0;
			else cnt_n<=cnt_n+1;
		end
 
        //下降沿触发的分频时钟输出,和clk_p相差半个时钟
	always @ (negedge clk)
		begin
			if(!rst_n)
				clk_n<=0;
			else if (cnt_n<(N>>1))  
				clk_n<=0;
			else 
				clk_n<=1;                //得到的分频时钟正周期比负周期多一个clk时钟
		end
 
        assign clkout = (N==1)?clk:(N[0])?(clk_p&clk_n):clk_p;      //条件判断表达式
                                                                    //当N=1时,直接输出clk
                                                                    //当N为偶数也就是N的最低位为0,N(0)=0,输出clk_p
                                                                    //当N为奇数也就是N最低位为1,N(0)=1,输出clk_p&clk_n。正周期多所以是相与
endmodule     
assign clk_out = (F_DIV == 1) ? clock : (F_DIV[0] ? (clk_p_r & clk_n_r) : clk_p_r); 
相当于
if (F_DIV == 1)
clk_out = clock;
else
{

if(F_DIV[0] == 1)
clk_out = clk_p_r & clk_n_r;
else
clk_out =clk_p_r;
}
 
 

4,http://www.stepfpga.com/doc/6._led%E6%B5%81%E6%B0%B4%E7%81%AF

module flashled (clk,rst,led);
 
	input clk,rst;						
	output [7:0] led;				
 
        wire clk1h;                                     //定义一个中间变量,表示分频得到的时钟,用作计数器的触发        
 
        //例化分频器模块,产生一个1Hz时钟信号		
        divide #(.WIDTH(32),.N(12000000)) u2 (         //传递参数
			.clk(clk),
			.rst_n(rst),                   //例化的端口信号都连接到定义好的信号
			.clkout(clk1h)
			);                             
 
        //1Hz时钟上升沿触发循环赋值
        reg [7:0] led;	
        always@(posedge clk1h or negedge rst)
	begin
		if(!rst)//在最开始的20ns左右,已经完成对LED赋初值,即led <= 8'b11111110;

			led <= 8'b11111110;            // <=为非阻塞赋值
		else 
			led <= {led[0],led[7:1]};      //当时钟上升沿来一次,执行一次赋值,赋值内容是led[0]与led[7:1]重新拼接成8位赋给led,相当于循环右移
	end	
 

verilog 大括号{}作用

  http://blog.sina.com.cn/s/blog_81a6d1330101c1bj.html

猜你喜欢

转载自blog.csdn.net/qq_40662854/article/details/80693972