原创 数码管动态扫描--时钟

2010-11-12 16:44 2188 4 4 分类: FPGA/CPLD
最近为了找工作一直奔波,但结果还是很悲剧。以至于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.当代码到了一定长度后,发现要写个测试文件很难,所以学习编程测试脚本是有必要的,可以节省很多时间
请求:
希望各位高手斧正,提供更加规范的代码!
最近为了找工作一直奔波,但结果还是很悲剧。以至于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.当代码到了一定长度后,发现要写个测试文件很难,所以学习编程测试脚本是有必要的,可以节省很多时间
请求:
希望各位高手斧正,提供更加规范的代码!
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
4
关闭 站长推荐上一条 /3 下一条