最近为了找工作一直奔波,但结果还是很悲剧。以至于FPGA的学习进程也停滞很久! 尤其在群里那些牛人聊到工作的时候,个个刚毕业月薪都是W级别的,想了很久,算了一切顺其自然吧,人家是211,我是草根大学,比不起,还是收拾心情实实在在的学些东西好! 琢磨了一个星期,终于搞懂数码管动态扫描,(在此再次由衷感谢亚峰师兄) 附上一段代码,请各位高手斧正! module smg_show(clk,rst_n, smg_wei_ctl,smg_duan_led); input clk,rst_n;//晶振,复位按键 //input key;复位按键 output [3:0]smg_wei_ctl;//4 wei smg位选控制 output [7:0]smg_duan_led;// smg_8_led show段选控制 reg [24:0]counter;// second counter always @(posedge clk or negedge rst_n) if(!rst_n) counter <= 0;//异步清零 else counter <= counter +1'b1; //显示数据分离 reg [6:0]second;//秒计数寄存器 reg [6:0]minutes;//分计数寄存器 always @(posedge clk or negedge rst_n) if(!rst_n) begin second<=0; minutes<=0;end else if(counter == 24'hff_ffff ) second = second+1'b1;//1秒钟到 else if(second[3:0] == 4'b1010) //秒显示个位计数到十 begin second[3:0] = 0; second[6:4] = second[6:4]+1'b1; //秒显示十位加1 end else if(second[6:4] == 3'b110) //秒显示十位计数到六, begin second[6:4]=0;///秒显示十位清零 minutes = minutes +1'b1; //分显示个位加1 end else if(minutes[3:0] == 4'b1010 ) //分显示个位计数到十 begin minutes[3:0]=0;//分显示个位清零 minutes[6:4]= minutes[6:4]+1'b1; //分显示十位加1 end else if(minutes[6:4] == 3'b110) minutes[6:4]=0;//分显示十位计数到六,清零 //位扫描控制,进行段选BCD编码,然后利用查表法显示数字 reg [3:0]smg_bcd_ctl;// 段选BCD编码寄存器 reg [3:0]smg_wei_ctl;//位选控制寄存器 always @(counter[17:16] or second or minutes) //定义显示数据触发事件//每20ms位扫描一次 case(counter[17:16]) //选择数码管显示位 2'b00:begin smg_wei_ctl<=4'b1110; smg_bcd_ctl <= second[3:0];end //选择数码管--》显示秒 个 位 2'b01:begin smg_wei_ctl<=4'b1101; smg_bcd_ctl <= second[6:4];end //选择数码管--》显示秒 十 位 2'b10:begin smg_wei_ctl<=4'b1011; smg_bcd_ctl <= minutes[3:0];end//选择数码管--》显示分 个 位 2'b11:begin smg_wei_ctl<=4'b0111; smg_bcd_ctl <= minutes[6:4];end//选择数码管--》显示分 十 位 endcase /* 共阴极 :不带小数点 ;0, 1, 2, 3, 4, 5, 6, 7, db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h ;8, 9, a, b, c, d, e, f , 灭 db 7fh,6fh,77h,7ch,39h,5eh,79h,71h,00h */ parameter smg0 = 8'h3f, smg1 = 8'h06, smg2 = 8'h5b, smg3 = 8'h4f, smg4 = 8'h66, smg5 = 8'h6d, smg6 = 8'h7d, smg7 = 8'h07, smg8 = 8'h7f, smg9 = 8'h6f, smga = 8'h77, smgb = 8'h7c, smgc = 8'h39, smgd = 8'h5e, smge = 8'h79, smgf = 8'h71; //段选显示数字,通过BCD码查表显示数字 reg [7:0]smg_duan_led;// 段选控制寄存器 always @(smg_bcd_ctl) case(smg_bcd_ctl) 4'h0:smg_duan_led <= smg0; 4'h1:smg_duan_led <= smg1; 4'h2:smg_duan_led <= smg2; 4'h3:smg_duan_led <= smg3; 4'h4:smg_duan_led <= smg4; 4'h5:smg_duan_led <= smg5; 4'h6:smg_duan_led <= smg6; 4'h7:smg_duan_led <= smg7; 4'h8:smg_duan_led <= smg8; 4'h9:smg_duan_led <= smg9; 4'ha:smg_duan_led <= smga; 4'hb:smg_duan_led <= smgb; 4'hc:smg_duan_led <= smgc; 4'hd:smg_duan_led <= smgd; 4'he:smg_duan_led <= smge; 4'hf:smg_duan_led <= smgf; default :; endcase endmodule 个人总结主要注意以下几点 1.每个显示位须给一个寄存器,这寄存器是用来存储要显示的值 2.通过BCD编码,可以方便后面显示的时候可以通过查表法显示 3.一个寄存器可以多用,比如代码中counter,我截取counter【17:16】作为20ms位扫描的触发信号,而counter又还担当秒计数的功能,所以一个寄存器完全可以多用 疑惑: 1.在处理数据显示分离的时候,发现无论 非阻塞“<=” 阻塞“=”赋值在最后实验现象中并没有明显的不同,所以下一步还要更深入的了解非阻塞跟阻塞的区别 2.发现现在很多市面的学习板都只是考虑自身布线容易与否,这样造成后面数码编码的时候就出现很多麻烦,其实是否应该寻找一种电路可以统一的编码,应用自如,这就让我想到如果代码可以参数化就好了,比如亚峰师兄按键的例程。 3.当代码到了一定长度后,发现要写个测试文件很难,所以学习编程测试脚本是有必要的,可以节省很多时间请求: 希望各位高手斧正,提供更加规范的代码! |
最近为了找工作一直奔波,但结果还是很悲剧。以至于FPGA的学习进程也停滞很久! 尤其在群里那些牛人聊到工作的时候,个个刚毕业月薪都是W级别的,想了很久,算了一切顺其自然吧,人家是211,我是草根大学,比不起,还是收拾心情实实在在的学些东西好! 琢磨了一个星期,终于搞懂数码管动态扫描,(在此再次由衷感谢亚峰师兄) 附上一段代码,请各位高手斧正! module smg_show(clk,rst_n, smg_wei_ctl,smg_duan_led); input clk,rst_n;//晶振,复位按键 //input key;复位按键 output [3:0]smg_wei_ctl;//4 wei smg位选控制 output [7:0]smg_duan_led;// smg_8_led show段选控制 reg [24:0]counter;// second counter always @(posedge clk or negedge rst_n) if(!rst_n) counter <= 0;//异步清零 else counter <= counter +1'b1; //显示数据分离 reg [6:0]second;//秒计数寄存器 reg [6:0]minutes;//分计数寄存器 always @(posedge clk or negedge rst_n) if(!rst_n) begin second<=0; minutes<=0;end else if(counter == 24'hff_ffff ) second = second+1'b1;//1秒钟到 else if(second[3:0] == 4'b1010) //秒显示个位计数到十 begin second[3:0] = 0; second[6:4] = second[6:4]+1'b1; //秒显示十位加1 end else if(second[6:4] == 3'b110) //秒显示十位计数到六, begin second[6:4]=0;///秒显示十位清零 minutes = minutes +1'b1; //分显示个位加1 end else if(minutes[3:0] == 4'b1010 ) //分显示个位计数到十 begin minutes[3:0]=0;//分显示个位清零 minutes[6:4]= minutes[6:4]+1'b1; //分显示十位加1 end else if(minutes[6:4] == 3'b110) minutes[6:4]=0;//分显示十位计数到六,清零 //位扫描控制,进行段选BCD编码,然后利用查表法显示数字 reg [3:0]smg_bcd_ctl;// 段选BCD编码寄存器 reg [3:0]smg_wei_ctl;//位选控制寄存器 always @(counter[17:16] or second or minutes) //定义显示数据触发事件//每20ms位扫描一次 case(counter[17:16]) //选择数码管显示位 2'b00:begin smg_wei_ctl<=4'b1110; smg_bcd_ctl <= second[3:0];end //选择数码管--》显示秒 个 位 2'b01:begin smg_wei_ctl<=4'b1101; smg_bcd_ctl <= second[6:4];end //选择数码管--》显示秒 十 位 2'b10:begin smg_wei_ctl<=4'b1011; smg_bcd_ctl <= minutes[3:0];end//选择数码管--》显示分 个 位 2'b11:begin smg_wei_ctl<=4'b0111; smg_bcd_ctl <= minutes[6:4];end//选择数码管--》显示分 十 位 endcase /* 共阴极 :不带小数点 ;0, 1, 2, 3, 4, 5, 6, 7, db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h ;8, 9, a, b, c, d, e, f , 灭 db 7fh,6fh,77h,7ch,39h,5eh,79h,71h,00h */ parameter smg0 = 8'h3f, smg1 = 8'h06, smg2 = 8'h5b, smg3 = 8'h4f, smg4 = 8'h66, smg5 = 8'h6d, smg6 = 8'h7d, smg7 = 8'h07, smg8 = 8'h7f, smg9 = 8'h6f, smga = 8'h77, smgb = 8'h7c, smgc = 8'h39, smgd = 8'h5e, smge = 8'h79, smgf = 8'h71; //段选显示数字,通过BCD码查表显示数字 reg [7:0]smg_duan_led;// 段选控制寄存器 always @(smg_bcd_ctl) case(smg_bcd_ctl) 4'h0:smg_duan_led <= smg0; 4'h1:smg_duan_led <= smg1; 4'h2:smg_duan_led <= smg2; 4'h3:smg_duan_led <= smg3; 4'h4:smg_duan_led <= smg4; 4'h5:smg_duan_led <= smg5; 4'h6:smg_duan_led <= smg6; 4'h7:smg_duan_led <= smg7; 4'h8:smg_duan_led <= smg8; 4'h9:smg_duan_led <= smg9; 4'ha:smg_duan_led <= smga; 4'hb:smg_duan_led <= smgb; 4'hc:smg_duan_led <= smgc; 4'hd:smg_duan_led <= smgd; 4'he:smg_duan_led <= smge; 4'hf:smg_duan_led <= smgf; default :; endcase endmodule 个人总结主要注意以下几点 1.每个显示位须给一个寄存器,这寄存器是用来存储要显示的值 2.通过BCD编码,可以方便后面显示的时候可以通过查表法显示 3.一个寄存器可以多用,比如代码中counter,我截取counter【17:16】作为20ms位扫描的触发信号,而counter又还担当秒计数的功能,所以一个寄存器完全可以多用 疑惑: 1.在处理数据显示分离的时候,发现无论 非阻塞“<=” 阻塞“=”赋值在最后实验现象中并没有明显的不同,所以下一步还要更深入的了解非阻塞跟阻塞的区别 2.发现现在很多市面的学习板都只是考虑自身布线容易与否,这样造成后面数码编码的时候就出现很多麻烦,其实是否应该寻找一种电路可以统一的编码,应用自如,这就让我想到如果代码可以参数化就好了,比如亚峰师兄按键的例程。 3.当代码到了一定长度后,发现要写个测试文件很难,所以学习编程测试脚本是有必要的,可以节省很多时间请求: 希望各位高手斧正,提供更加规范的代码! |
文章评论(0条评论)
登录后参与讨论