前言
从这节开始算是正式接触代码了,像创建工程等重复性操作就不再写上来了。
流水灯
创建代码文件
- 添加源文件
- 选择create file,并为文件命名,然后finish,OK
编写代码
- 确定输入输出
module led(
input sys_clk , //系统时钟
input sys_rst_n, //系统复位,低电平有效
output [2:0] rgb_led //三色的LED灯
);
- 确定其他参数
确定参数的时候要注意位宽。其中,时钟频率为50Mhz,则意味着计数器的位宽需要能容纳 5 ∗ 1 0 7 5*10^7 5∗107次的计数,那么位宽为26位。
而颜色有3钟,那么位宽为3位。
reg [25:0] cnt ; //定时计数器
reg [2:0] led_count;//led切换
reg [2:0] temp_rgb_led;//暂存变量
- 确定时钟计数模块
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) //下降沿复位
cnt <= 26'd0; //时钟清零
else if(cnt < 26'd5000_0000) //计数器在0~5000_000之间进行计数
cnt <= cnt + 1'b1;
else
cnt <= 26'd0;
end
- 确定三色灯模块
always@(posedge sys_clk or negedge sys_rst_n) begin //注意三色灯是共阳极接法
if(!sys_rst_n)
temp_rgb_led <= 3'b111;
else begin
case(led_count) //切换三色灯颜色
3'd0: temp_rgb_led <= 3'b110;
3'd1: temp_rgb_led <= 3'b101;
3'd2: temp_rgb_led <= 3'b011;
3'd3: temp_rgb_led <= 3'b000;
default : temp_rgb_led <= 3'b111;
endcase
end
end
- 将暂变量赋值
assign rgb_led = temp_rgb_led;
设置IO口约束
-
点击Open Elaborated Design
-
生成网表文件,可以查看RTL图
-
点出latout的IO planning
-
分配IO口,改变IO std
-
保存约束文件,并命名
-
连接开发板,生成比特流文件
-
比特文件生成后,打开硬件调试
-
Open target
-
-
编译文件,大功告成
呼吸灯
PWM模块
- 确定参数
其中占空比14位是因为1.2KHZ,而时钟为12MHZ,12M/1.2K=10000,转为2进制则14位
reg [13:0] period_cnt;//1.2khz,占空比周期
reg [13:0] duty_cycle;//占空比
reg inc_dec_flag;//0由暗到亮,1由亮到暗
- PWM计数
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) //下降沿复位
period_cnt <= 14'd0;
else if(period_cnt < 14'd1_0000) //计数器在0~10000之间进行计数,在数字中间加入下划线不影响数值本身,只是方便阅读
period_cnt <= period_cnt + 1'b1;
else
period_cnt <= 14'd0;
end
- PWM模块
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin//下降沿复位
duty_cycle <= 14'b0;
inc_dec_flag <= 1'b0;
end
else begin
if(period_cnt == 14'd1_0000) begin
if(!inc_dec_flag) begin
if(duty_cycle == 14'd1_0000) begin
inc_dec_flag <= 1'b1;
end
else begin
duty_cycle <= duty_cycle + 14'd100;//呼吸灯变化速度为1%
end
end
else begin
if(duty_cycle == 14'd0) begin
inc_dec_flag <= 1'b0;
end
else begin
duty_cycle <= duty_cycle - 14'd100;//呼吸灯变化速度为1%
end
end
end
end
end
-整体代码
module breath_led(
input sys_clk, //12mhz时钟
input sys_rst_n,
output reg [2:0] rgb_led
);
reg [13:0] period_cnt;//1.2khz,占空比周期
reg [13:0] duty_cycle;//占空比
reg inc_dec_flag;//0由暗到亮,1由亮到暗
reg [23:0] cnt;
reg [2:0] led_count;//led切换
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) //下降沿复位
cnt <= 24'd0; //时钟清零
else if(cnt < 24'd1200_0000) //计数器在0~1200000之间进行计数,在数字中间加入下划线不影响数值本身,只是方便阅读
cnt <= cnt + 1'b1;
else
cnt <= 24'd0;
end
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) //下降沿复位
period_cnt <= 14'd0;
else if(period_cnt < 14'd1_0000) //计数器在0~10000之间进行计数,在数字中间加入下划线不影响数值本身,只是方便阅读
period_cnt <= period_cnt + 1'b1;
else
period_cnt <= 14'd0;
end
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) begin//下降沿复位
duty_cycle <= 14'b0;
inc_dec_flag <= 1'b0;
end
else begin
if(period_cnt == 14'd1_0000) begin
if(!inc_dec_flag) begin
if(duty_cycle == 14'd1_0000) begin
inc_dec_flag <= 1'b1;
end
else begin
duty_cycle <= duty_cycle + 14'd100;//呼吸灯变化速度为1%
end
end
else begin
if(duty_cycle == 14'd0) begin
inc_dec_flag <= 1'b0;
end
else begin
duty_cycle <= duty_cycle - 14'd100;//呼吸灯变化速度为1%
end
end
end
end
end
always@(posedge sys_clk or negedge sys_rst_n) begin //控制三色灯颜色转换
if(!sys_rst_n)
led_count <= 3'd0;
else if(cnt==24'd1200_0000) //一秒切换一次
led_count <= led_count + 1'b1;
else if(led_count==3'd4)
led_count <= 3'd0;
end
always@(posedge sys_clk or negedge sys_rst_n) begin //注意三色灯是共阳极接法
if(!sys_rst_n) begin
rgb_led <= 3'b111;
end
else begin
if(period_cnt >= duty_cycle) begin
case(led_count) //切换三色灯颜色
3'd0: rgb_led <= 3'b110;
3'd1: rgb_led <= 3'b101;
3'd2: rgb_led <= 3'b011;
3'd3: rgb_led <= 3'b000;
default : rgb_led <= 3'b111;
endcase
end
else begin
rgb_led <= 3'b111;
end
end
end
endmodule
剩下的IO约束和生成比特流代码就不再重复赘述了。