FPGA学习入门1
1. 初始化与时序控制
编写下面的代码控制clk_i和rst_n_i寄存器
其中#20表示延时20ns,20ns相当于模拟对应50MHZ的晶振
module tb_test();
reg clk_i;
reg rst_n_i;
wire[4:0]result1_o,result2_o;
unblock unblcok_inst
(
.clk_i(clk_i),
.rst_n_i(rst_n_i),
.result_o(result1_o)
);
block blcok_inst
(
.clk_i(clk_i),
.rst_n_i(rst_n_i),
.result_o(result2_o)
);
initial begin
clk_i =0;
rst_n_i =0;
#20;
rst_n_i =1;
#20;
end
always #10 clk_i = ~clk_i;
endmodule
2. 赋值 block or unblock
2.1 非阻塞赋值《=
module unblock(
input clk_i,
input rst_n_i,
output reg [4:0]result_o);
reg [3:0]A;
reg [3:0]B;
reg [4:0]C;
always @(posedge clk_i ) //上升沿触发
if(!rst_n_i)
begin
#2
A <= 4'd4;
B <= 4'd12;
C <= 5'd0;
result_o = 5'd0;
end
else begin
#2
C <= A + B;
result_o <= (C >> 1);
//由于上两行是并行处理的(可以交换位置),c值赋为16时,对result_o 而言c还是0,所以result_o 还要延后20ns
end
endmodule
2.2 阻塞赋值 =
module block(
input clk_i,
input rst_n_i,
output reg [4:0]result_o
);
reg [3:0]A;
reg [3:0]B;
reg [4:0]C;
always @(posedge clk_i) //上升沿触发
if(!rst_n_i)
begin
#2 A = 4'd4;
#0.2 B = 4'd12;
#0.2 C = 5'd0;
#0.2 result_o = 5'd0;
end
else begin
#2 C = A + B;
#0.2 result_o = (C >> 1);
//上两行是串行处理的(不可以交换位置),c值赋为16时,对result_o 而言c已经是16
end
endmodule
result1_o及上面的ABC是unblock,result2_o是block
3. 流水灯实验介绍
LED相关的GPIO口
c0作为寄存器用于计数使用,CLK_i来源于ZYNQ-MZ702P的时钟,RSTn_i属于上电置1。
module run_led(
input CLK_i,
input RSTn_i,
output reg [3:0]LED_o
);
reg [31:0]C0;
always @(posedge CLK_i)
if(!RSTn_i)
begin
LED_o <= 4'b1;
C0 <= 32'h0;
end
else
begin
if(C0 == 32'd50_000_000)
begin
C0 <= 32'h0;
if(LED_o == 4'b1000)
LED_o <= 4'b1;
else LED_o <= LED_o << 1;
end
else
begin
C0 <= C0 + 1'b1;
LED_o <= LED_o;
end
end
endmodule
4. 按键消抖实验
下图SW0,SW1,SW2,SW3是FPGA MZ702P的四个按键:
对应原理图如下:
按钮按下导通,置0,松开为1。
下面两段程序是约束文件下配置管脚,指明了M16用于复位,K16用于按键。
set_property IOSTANDARD LVCMOS33 [get_ports key_i]
set_property PACKAGE_PIN K16 [get_ports key_i]
set_property PACKAGE_PIN M16 [get_ports rst_n_i]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n_i]
下面这段程序实现了本实验的功能
module Key_Jitter(
input clk_i,
input rst_n_i,
input key_i,
output [3:0] led_o
);
(*mark_debug = "true"*) reg [3:0] led_o;
(*mark_debug = "true"*) wire key_cap;
always @(posedge clk_i)begin
if(!rst_n_i)begin //此处SW1可以控制全亮,按下SW1,rst_n_i置0,四个LED都变为0,LED都导通
led_o <= 4'b0000;
end
else if(key_cap)begin //一旦检测到按过按钮SW2,key_cap置为1,具体定义在key #中
led_o <= ~led_o; //由key#控制,所有led翻转
end
end
key#
(
.CLK_FREQ(100000000)
)
key0
(
.clk_i(clk_i),
.key_i(key_i),
.key_cap(key_cap)
);
endmodule
下面这段程序定义了key #模块
module key #
(
parameter CLK_FREQ = 100000000
)
(
input clk_i,
input key_i,
output key_cap
);
//10ms
parameter CNT_10MS = (CLK_FREQ/100 - 1'b1); //分屏10ms?
parameter KEY_S0 = 2'd0;
parameter KEY_S1 = 2'd1;
parameter KEY_S2 = 2'd2;
parameter KEY_S3 = 2'd3;
reg [24:0] cnt10ms = 25'd0;
(*mark_debug = "true"*) reg [1:0] key_s = 2'b0;
(*mark_debug = "true"*) reg [1:0] key_s_r = 2'b0;
(*mark_debug = "true"*) wire en_10ms ;
assign en_10ms = (cnt10ms == CNT_10MS);
assign key_cap = (key_s==KEY_S2)&&(key_s_r==KEY_S1); //说明按键按下又松开,算一次按按键
always @(posedge clk_i)begin
if(cnt10ms < CNT_10MS)
cnt10ms <= cnt10ms + 1'b1;
else
cnt10ms <= 25'd0;
end
always @(posedge clk_i)begin
key_s_r <= key_s;
end
always @(posedge clk_i)begin
if(en_10ms)begin
case(key_s)
KEY_S0:begin
if(!key_i)
key_s <= KEY_S1;
end
KEY_S1:begin
if(!key_i)
key_s <= KEY_S2;
else
key_s <= KEY_S0;
end
KEY_S2:begin
if(key_i)
key_s <= KEY_S3;
end
KEY_S3:begin
if(key_i)
key_s <= KEY_S0;
else
key_s <= KEY_S2;
end
endcase
end
end
endmodule
本文来自博客园,作者:静候佳茵,转载请注明原文链接:https://www.cnblogs.com/hitwherznchjy/p/16754293.html