FPGA期末考试复习总结
2021年下学年可编程逻辑器件(FPGA)期末复习总结,仅供参考
判断题
- 关于端口定义:一般有输入(input)、输出(output)、双向端口(inout)。
- Verilog HDL是一种硬件描述语言一般用于设计数字电路核数字逻辑系统,可对算法级、门级、开关级等多种抽象设计层次进行建模。
- 阻塞赋值与非阻塞赋值:
1)阻塞赋值(=)–组合电路
变量=赋值表达式 ;// c = a&b ;
赋值语句结束后块才结束;a或者b的值改变,c会随之立即改变;在时序逻辑中用阻塞赋值会造成意向不到的后果。
2)非阻塞赋值(<=)–时序电路
变量 <=赋值表达式 ;// c <= a&b ;
块结束后才能完成赋值操作, a或者b的值改变,C不会随之立即变化。
3)阻塞赋值与非阻塞赋值的差别
always@(posedge clk) always@(posedge clk)
begin begin
b <= a ; b = a ;
c <= b ; c = b ;
end end
- 关于assign语句:不支持对reg 数据类型的assign或deassign进行综合,支持对wire数据类型的assign或deassign进行综合。
- 分支语句:case 语句是一种多路条件分支的形式,可以解决 if 语句中有多个条件选项时使用不方便的问题
case 语句支持嵌套使用、case 语句中的条件选项表单式不必都是常量,也可以是 x 值或 z 值
case 语句执行时,如果 condition1 为真,则执行 true_statement1 ; 如果 condition1 为假,condition2 为真,则执行 true_statement2;依次类推。如果各个 condition 都不为真,则执行 default_statement 语句。
default 语句是可选的,且在一个 case 语句中不能有多个 default 语句。 - IP核种类:软核、硬核、固核。
- 模块调用:在一个模块中引用另一个模块,对其端口进行相关连接,叫做模块例化。模块例化建立了描述的层次。信号端口可以通过位置或名称关联,端口连接也必须遵循一些规则。
命名端口连接、顺序端口连接、端口连接规则、位宽匹配、端口连续信号类型。 - 可综合电路与不可综合电路
一般可综合电路用于设计;不可综合电路用于仿真和测试。
填空题
1.有关移位操作
移位操作符是把操作数向左或向右移若干位。移位操作符有两种:<<(左移)、>>(右移)。
移位操作符有两个操作数,右侧操作数表示的是左侧操作数所移动的位数。它是一个逻辑移位,空闲位添0补位。如果右侧操作数的值为x或z,则移位操作的结果为x。
4’b10x0 >> 1 = 4’b010x
4’b1010 <<2 = 4’b1000
2.字符拼接与复制
连接操作是将多组信号用大括号括起来,拼接成一组新信号。其表示形式如下:
{expr1, expr2, …, exprN}
例:a=3’b101 b=4’b1010 {a,b}=7’b1011010
{a,a}= {2{a}}=6’b101101
3. 端口
模块的端口定义声明了模块的所有输入\输出端口,格式如下:
module 模块名 (端口1,端口2,端口3,·······);
模块的端口包含模块与外部联系的全部输入输出信号,端口之间用“,”隔开;
4.always
always 块的综合可以分为至少两类电路:1、组合逻辑电路 2、时序逻辑电路
5.循环语句
forever、while、repeat、for (其中前三类只能用于仿真)
6.数据类型
Verilog共有19种数据类型,reg、wire、parameter、integer是最常用的四种数据类型。
7.FPGA开发流程
FPGA开发流程是自上而下(Top-Down)的设计方法。优化后的FPGA开发流程如图所示。
需求分析、模块划分、代码设计、综合优化、实现、板级调试
程序设计题
1.数码管动态扫描
下面展示一些 内联代码片
。
// 数码管动态扫描
//6个数码管显示123456,动态扫描
// An highlighted block
module smg(
input clk,
input rst_n,
output reg [5:0] sel, //数码管选择输出引脚
output reg [7:0] seg //数码管段输出引脚
);
reg[3:0] data; //定义显示数据寄存器
reg[24:0]count; //定义计数寄存器
//秒信号产生部分
always @(posedge clk or negedge rst_n) //定义clk上升沿触发
begin
if(!rst_n)
count<=0;
else if(count == 25'd250000) //0.5S到了吗?
count = 25'd0; //计数器清零
else
count = count + 1'b1;
end
//数码管动态扫描显示部分
always @(posedge clk or negedge rst_n) //count[17:15]大约1ms改变一次
begin
if(!rst_n)
data<=0;
else
case(count[15:13]) //选择扫描显示数据
3'd0:data<= 1; //个位
3'd1:data<= 2; //十位
3'd2:data<= 3; //百位
3'd3:data<= 4; //千位
3'd4:data <= 5; //万位
3'd5:data<= 6; //十万位
endcase
end
always @(posedge clk) //count[17:15]大约1ms改变一次
begin
case(count[15:13]) //选择扫描显示数据
3'd0:sel<= 6'b111110; //选择第一个数码管显示
3'd1:sel<= 6'b111101; //选择第二个数码管显示
3'd2:sel<= 6'b111011; //选择第三个数码管显示
3'd3:sel<= 6'b110111; //选择第四个数码管显示
3'd4:sel<= 6'b101111; //选择第五个数码管显示
3'd5:sel<= 6'b011111; //选择第六个数码管显示
endcase
end
always @(posedge clk)
begin
case(data)
4'h0:seg<= 8'hc0; //显示0
4'h1:seg<= 8'hf9; //显示1
4'h2:seg <= 8'ha4; //显示2
4'h3:seg <= 8'hb0; //显示3
4'h4:seg <= 8'h99; //显示4
4'h5:seg <= 8'h92; //显示5
4'h6:seg <= 8'h82; //显示6
4'h7:seg <= 8'hf8; //显示7
4'h8:seg <= 8'h80; //显示8
4'h9:seg <= 8'h90; //显示9
4'ha:seg <= 8'hbf; //显示-
default:sm_seg <= 8'hff; //不显示
endcase
end
endmodule
2.分频
下面展示一些 内联代码片
。
// 分频
//根据修改m的值实现任意分频
//此处产生1Hz的clk
// An highlighted block
module demo_1(clk,rst_n,clk_div);
input clk,rst_n;
output clk_div;
reg clk_div;
//---------------------分频开始-----------------------
parameter m=49999999;
integer div_cnt=0;
always@(posedge clk or negedge rst_n)
if(!rst_n)
div_cnt<=1’b0;
else
begin
if(div_cnt==m)
begin
clk_div<=1'b1;
div_cnt<=0;
end
else
begin
clk_div<=1'b0;
div_cnt<=div_cnt+1;
end
end
//---------------------分频结束-----------------------
endmodule
3.按键消抖(盲猜会考)
下面展示一些 内联代码片
。
// 按键消抖
// An highlighted block
module key_scan(clk ,rst_n ,key);
input clk ;
input rst_n ;
input [3:0] key ;
reg[19:0]count;
reg[3:0]key_scan;//扫描按键值
//---------------------------------------------
//采样按键值,20ms扫描一次,采样频率小于按键毛刺频率,相当于滤除掉了高频毛刺信号。
//---------------------------------------------
always @(posedge clk or negedge rst_n)//检测时钟的上升沿和复位的下降沿
begin
if(rst_n==1'b0)
count<=20'd0;//先将计数清零
else
begin
if(count==20'd999_999)//20ms 扫描一次按键,20ms 计数(50M/50-1=999_999)
begin
count<=20'd0; //计数器计到 20ms,计数器清零
key_scan<=key;//采样按键输入电ping
end
else
count<=count+20'b1;//计数器加1
end
end
//----------------------------------------------------
// 按键信号锁存一个时钟节拍
//----------------------------------------------------
reg [3:0] key_scan_r;
always @(posedge clk)
key_scan_r <= key_scan;
wire [3:0] flag_key = key_scan_r[3:0] & (~key_scan[3:0]); //当检测到按键有下降沿变化时,代表该按键被按下,按键有效
endmodule
4.组合逻辑电路
此处仅放两个作为参考
下面展示一些 内联代码片
。
// 四位全加器
module adder4(cout,sum,ina,inb,cin);
output[3:0] sum;
output cout;
input[3:0] ina,inb;
input cin;
assign sum=ina^inb^cin;
assign cout=(ina^inb)&cin|ina&inb;
endmodule
下面展示一些 内联代码片
。
// 四选一数据选择器
module mux4_1(out,in0,in1,in2,in3,sel);
output out;
input in0,in1,in2,in3;
input[1:0] sel;
reg out;
always @(in0 or in1 or in2 or in3 or sel) //敏感信号列表
case(sel)
2'b00: out=in0;
2'b01: out=in1;
2'b10: out=in2;
2'b11: out=in3;
default: out=2'bx;
endcase
endmodule
程序填空
有关状态机——以三段式为例
下面通过实例来说明状态机的原理与设计方法。如设计一个110报警检测器,当检测到报警电话110时则输出报警信号。
下面展示一些 内联代码片
。
//状态机
module state_detec(clk,rst_n,num,result);
input clk , rst_n ;//输入信号
input num ;//
output result ;//输出信号
reg result ;//
reg [3:0] cstate ;//中间信号
reg [3:0] nstate ;//中间信号
parameter idle = 4’b0001 ; //状态机参数定义
parameter S1 = 4’b0010 ;
parameter S2 = 4’b0100 ;
parameter S3 = 4’b1000 ;
always@(posedge clk)
if(!rst_n)
cstate <= idle ;
else
cstate <= nstate ;
always@(*)
case(cstate)
idle:if(num)
nstate = S1 ;
else
nstate = idle ;
S1:if(num)
nstate = S2 ;
else
nstate = idle ;
S2:if(num)
nstate = S2 ;
else
nstate = S3 ;
S3:if(num)
nstate = S1 ;
else
nstate = idle ;
default: nstate = idle ;
endcase
always@(posedge clk)
if(!rst_n)
result <= 1’b0 ;
else if(nstate == S3)
result <= 1’b1 ;
else
result <= 1’b0 ;
endmodule
内容很长,感谢阅读,希望对你有帮助!