硬件:Zedboard
软件:Vivado2018.2 + Win10
本文参考了http://blog.chinaaet.com/cuter521/p/35946,原文代码有错误,已更正。
功能:PL流水灯
语言:verilog
流程:建立工程->代码编辑->功能仿真->综合、实现->生成Bitstream->烧写进板子,观察现象
功能图:
timer500ms模块:
产生2hz的时钟,为led_ctrl模块提供时钟。
led_ctrl模块:
实现循环移位,在硬件上的体现就是流水灯。输入时钟为2hz,时钟上升沿进行一次移位操作,每个led点亮0.5s。
runled_top.v
`timescale 1ns / 1ps
module runled_top(
input iClk,
input iRst_n,
output [7:0] oLed
);
wire clk2hz_sig;
timer500ms timer500ms_inst(
.iClk100mhz(iClk),
.iRst_n(~iRst_n),
.oClk2hz(clk2hz_sig)
);
led_ctrl led_ctrl_inst(
.iClk(clk2hz_sig),
.iRst_n(~iRst_n),
.oLed(oLed)
);
endmodule
timer500ms.v
`timescale 1ns / 1ps
/*
oFreq = iFreq/(2*N)
N = iFreq/(2*oFreq) = 100,000,000/(2*2) = 25,000,000 = 0x17d7840
*/
module timer500ms(
input iClk100mhz,
input iRst_n,
output reg oClk2hz // period = 1/2s
);
reg [31:0] cnt2hz;
always @(posedge iClk100mhz)
begin
if(iRst_n==1'b0)
begin
oClk2hz <= 1'b0;
cnt2hz <= 32'b0;
end
else
begin
if(cnt2hz==32'd25000000)
begin
cnt2hz <= 32'b0;
oClk2hz <= ~oClk2hz;
end
else
begin
cnt2hz <= cnt2hz + 1'b1;
oClk2hz <= oClk2hz;
end
end
end
endmodule
led_ctrl.v
`timescale 1ns / 1ps
module led_ctrl(
input iClk,
input iRst_n,
output [7:0] oLed
);
reg [7:0] led;
always @(posedge iClk)
begin
if(iRst_n == 1'b0)
led <= 8'b1;
else
//实现循环左移
led <= {led[6:0], led[7]};
end
assign oLed = led;
endmodule
vivado2018.2的界面如下所示
选择Create Project,出现如下界面
选Next
输入工程保存目录,点Next
这里选择RTL Project,并且勾选Do not specify sources at this time。这样可以跳过源文件指定步骤,在后续过程中再输入源文件。点Next
在Boards下选择ZedBoard,这样就成功创建了工程
工程创建后界面如下
点击Add Sources,出现如下界面
选择Add or create design sources,出现如下界面
选择Create File
输入runled_top,然后OK
点Finish,出现如下界面
选择OK,YES
在Sources模块的Design Sources里能看到创建的runled_top.v文件,双击该文件
将内容替换为第二部分的代码,并按照此方法创建timer500ms.v和led_ctrl.v,完成后如下图。vivado能根据代码内调用关系生成文件层级(runled_top.v内调用了timer500ms和led_ctrl模块)。至此,源文件输入完毕。
输入代码后,在综合之前,我们可以通过仿真来验证代码逻辑的正确性。
首先应该添加仿真文件,这一步依然应该选择Add Sources
这里要选择Add or create simulation sources,后面过程与添加源文件一模一样,仿真文件代码如下:
`timescale 1ns / 1ps
module simulation1(
);
reg CLK;
reg RSTn;
wire [7:0] sim_oled;
wire clk2hz_sig;
initial
begin
CLK = 0;
RSTn = 0;
#100;
RSTn = 1;
end
always
begin
#5;
CLK = ~CLK;
end
timer500ms timer500ms_inst(
.iClk100mhz(CLK),
.iRst_n(RSTn),
.oClk2hz(clk2hz_sig)
);
led_ctrl led_ctrl_inst(
.iClk(clk2hz_sig),
.iRst_n(RSTn),
.oLed(sim_oled)
);
endmodule
完成后界面如下
选择SIMULATION的RUN Simulation->Run Behavioral Simulation,界面如下,注意保证红框内的simulation1是选中的状态。
切换到timer500ms.v编辑界面
为更加明显看到timer500ms.v的分频效果,将分频系数调小。在timer500ms.v中将25000000修改为25,并保存
点击Relaunch Simulation
点击Zoom In放大波形
这样就验证了分频效果。
验证完成后将timer500ms.v中的25改回为25000000,并保存
综合之前,先添加约束文件,与添加源文件和仿真文件添加方式相同。
约束文件代码如下
#In the following the XDC constraint is matched to the origanal UCF constraint, XDC above, UCF below # Commented
set_property PACKAGE_PIN Y9 [get_ports {iClk}]
set_property IOSTANDARD LVCMOS33 [get_ports {iClk}]
#NET GCLK LOC = Y9 | IOSTANDARD=LVCMOS33; # "GCLK"
# Bank 33, Vcco = 3.3V
#set_property IOSTANDARD LVCMOS33 [get_ports -filter { IOBANK == 33 } ]
set_property PACKAGE_PIN T22 [get_ports {oLed[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[0]}]
#NET LD0 LOC = T22 | IOSTANDARD=LVCMOS33; # "LD0"
set_property PACKAGE_PIN T21 [get_ports {oLed[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[1]}]
#NET LD1 LOC = T21 | IOSTANDARD=LVCMOS33; # "LD1"
set_property PACKAGE_PIN U22 [get_ports {oLed[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[2]}]
#NET LD2 LOC = U22 | IOSTANDARD=LVCMOS33; # "LD2"
set_property PACKAGE_PIN U21 [get_ports {oLed[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[3]}]
#NET LD3 LOC = U21 | IOSTANDARD=LVCMOS33; # "LD3"
set_property PACKAGE_PIN V22 [get_ports {oLed[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[4]}]
#NET LD4 LOC = V22 | IOSTANDARD=LVCMOS33; # "LD4"
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[5]}]
set_property PACKAGE_PIN W22 [get_ports {oLed[5]}]
#NET LD5 LOC = W22 | IOSTANDARD=LVCMOS33; # "LD5"
set_property PACKAGE_PIN U19 [get_ports {oLed[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[6]}]
#NET LD6 LOC = U19 | IOSTANDARD=LVCMOS33; # "LD6"
set_property IOSTANDARD LVCMOS33 [get_ports {oLed[7]}]
set_property PACKAGE_PIN U14 [get_ports {oLed[7]}]
#NET LD7 LOC = U14 | IOSTANDARD=LVCMOS33; # "LD7"
# Bank 34, Vcco = Vadj
#set_property IOSTANDARD LVCMOS18 [get_ports -filter { IOBANK == 34 } ]
set_property IOSTANDARD LVCMOS18 [get_ports {iRst_n}]
set_property PACKAGE_PIN P16 [get_ports {iRst_n}]
#NET BTNC LOC = P16 | IOSTANDARD=LVCMOS18; # "BTNC"
点SYNTHESIS->Run Synthesis,在出现的界面上选OK,然后等待即可。
可在左下角IMPLEMENTATION选Run Implementation,也可以直接在中间界面选定Run Implementation然后选OK
过程与上一步类似,选择Generate Bitstream
右上角显示当前的状态
选Open Hardware Manager
给Zedboard上电,连上JTAG线后点击Open target的Auto Connect
软件成功识别板子后,点击Program device
Bitstream file会自动选择当前工程生成的bit文件,点Program后在板子上即可看见流水灯现象。