本帖最后由 wsdymg 于 2013-8-11 16:22 编辑
为响应“原创征集第二波——快乐设计大本营”号召,将近期学习Verilog中遇到的问题跟大家分享下:
本着“天下难事必作于易,天下大事必作于细”的思路指导,开始了我轰轰烈烈的CPLD开发板的学习,最经典的程序莫过于流水灯的程序了,因为以前有一些C语言的基础,想来VERILOG也不是什么难事,可是天不遂人愿,今早整整一天,我被流水灯程序虐的体无完肤啊,真捉急啊,真捉急啊,程序虐我千百遍,我待程序如初恋,不断实践,不断探索,终于皇天不负有心人啊:
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
本来最初的想法很简单,实现的功能无外乎:D4灯狂闪,D1、D2、D3灯实现流水灯的效果。
就是这个简简单单的愿望跟想法,却屡遭罹难,遇到的问题主要有:
1、D4闪烁效果无法实现,一直是暗的;流水灯效果正常。
2、大家看我贴的程序,会看到我注释掉了两条语句,不注释掉的话,流水灯的效果也无法实现,D1灯常亮,D2、D3灯常灭;
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
实验最初的程序如下:
module mix_module (sys_clk,sys_rstn,led_out);
input sys_clk,sys_rstn;
output led_out;
reg [3:0] led_out;
parameter T48M=26'd48_000_000;
reg [25:0] Count;
reg[1:0] i;
reg led;
always@(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
Count<=26'b0;
else
if(Count==T48M)
Count<=26'b0;
else
Count<=Count+1'b1;
end
always@(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
i<=2'b00;
else
begin
if(Count==T48M)
i<=i+1'b1;
else
i<=i;
if(i==2'b11)
i<=2'b00;
//else
//i<=i;
end
end
always@(i)
begin
led=~led;
if(i==2'b00)
led_out={led,3'b110};
else if(i==2'b01)
led_out={led,3'b101};
else
led_out={led,3'b011};
end
endmodule
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
后来经过想网友@6-shark1234567,@KDY的请教跟学习,终于解决了问题:
修改后的程序如下:
版本一:
module mix_module (sys_clk,sys_rstn,led_out);
input sys_clk,sys_rstn;
output led_out;
reg [3:0] led_out;
parameter T48M=27'd48000_000;
reg [26:0] Count;
reg[1:0] i;
reg led;
initial led = 1'b1;
always@(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
Count<=27'b0;
else
if(Count==T48M)
Count<=27'b0;
else
Count<=Count+1'b1;
end
always@(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
i<=2'b00;
else
begin
if(Count==T48M)
i<=i+1'b1;
else
i<=i;
if(i==2'b11)
i<=2'b00;
end
end
always@(posedge sys_clk)
begin
if(Count==T48M)
led=~led;
if(i==2'b00)
led_out={led,3'b110};
else if(i==2'b01)
led_out={led,3'b101};
else
led_out={led,3'b011};
end
endmodule
版本二:
module mix_moduile (sys_clk,sys_rstn,led_out);
input sys_clk,sys_rstn;
output led_out;
reg [3:0] led_out;
parameter T48M=26'd48_000_000;
reg [25:0] Count;
reg[1:0] i;
reg led=1;
always@(posedge sys_clk or negedge sys_rstn)
if(!sys_rstn)
Count<=26'b0;
else
if(Count==T48M)
Count<=26'b0;
else
Count<=Count+1'b1;
always@(posedge sys_clk or negedge sys_rstn)
if(!sys_rstn)
led_out<=4'b0110;
else
if(Count==T48M)
begin
led_out[3]<=~led_out[3];
led_out[2:0]<={led_out[1],led_out[0],led_out[2]};
end
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
以上两个程序都很好的解决了我的问题,版本一来自于@KDY,版本二来自于@6-shark1234567,与我的程序相比,两位老师的程序都很好的采用了,同
步时序电路,而我采用的是always(i)异步触发的方式,虽然经过仿真的测试,时序图正确,但经过综合后却总是出错,所以在此向跟我一样,处在学习FPGA初级阶段的各位提个建议,那就是少用always()的异步电路,往往综合器比较坑!
在此将 KDY给我的建议列在下面,愿大家共同学习,共同进步!
|