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