打印

verilog 处>女做,第一次学写verilog程序

[复制链接]
5979|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangkj|  楼主 | 2008-9-12 15:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
*
7段数码管测试实验1:以动态扫描方式在4位数码管,显示32计数器的高16位值 hex码
实验的目的是向用户介绍多个数码管动态显示的方法。
动态显示的方法是,按一定的频率轮流向各个数码管的COM端送出低电平,同时送出对应的数据给各段。
    -- segment encoding 
    --      0 
    --     ---  
    --  5 |   | 1
    --     ---   <- 6
    --  4 |   | 2
    --     ---  
    --      3
COM is GND
*/


module seg71(clk,dataout,en);

input clk;
output[7:0] dataout;
output[3:0] en;//COM使能输出
reg[7:0] dataout;//各段数据输出
reg[3:0] en;

reg[31:0] cnt_scan=0;//扫描频率计数器 10M/2^32=0.02Hz 429.5S 
reg[4:0] dataout_buf;

always@(posedge clk )
begin
    cnt_scan<=cnt_scan+1;
end

//频率 10M/65535 = 152 Hz
always @(cnt_scan)
begin
   case(cnt_scan[15:14])
       3'b00 :
          en = 4'b1110;
          dataout_buf=cnt_scan[31:28];  
       3'b01 :
          en = 4'b1101;
          dataout_buf=cnt_scan[27:24];  
       3'b10 :
          en = 4'b1011;
          dataout_buf=cnt_scan[23:20];  
       3'b11 :
          en = 4'b0111;
          dataout_buf=cnt_scan[19:16];  
       default :
          en = 4'b1111;
          dataout_buf=0;  
    endcase
end

always@(dataout_buf)
begin
    case(dataout_buf)
        4'b0000:
            dataout=8'b0000_0011;
        4'b0001:
            dataout=8'b1001_1111;
        4'b0010:
            dataout=8'b0010_0101;
        4'b0011:
            dataout=8'b0000_1101;
        4'b0100:
            dataout=8'b1001_1001;
        4'b0101:
            dataout=8'b0100_1001;
        4'b0110:
            dataout=8'b0100_0001;
        4'b0111:
            dataout=8'b0001_1111;
        4'b1000:
            dataout=8'b0000_0001;
        4'b1001:
            dataout=8'b0001_1001;
        4'b1010:
            dataout=8'b0001_0001;
        4'b1011:
            dataout=8'b1100_0001;
        4'b1100:
            dataout=8'b0110_0011;
        4'b1101:
            dataout=8'b1000_0101;
        4'b1110:
            dataout=8'b0110_0001;
        4'b1111:
            dataout=8'b0111_0001;
     endcase
end

endmodule 

相关帖子

沙发
yuxyoo| | 2008-9-12 17:20 | 只看该作者

很好

写的很好 继续努力哈

使用特权

评论回复
板凳
wangkj|  楼主 | 2008-9-12 17:39 | 只看该作者

最终的程序,注意开发板的错误

发现开发板一个错误:时钟晶振用的102(1k)电阻,太大,换成0欧姆的才能正常。


/*
7段数码管测试实验1:以动态扫描方式在4位数码管,显示32计数器的高16位值 hex码
实验的目的是向用户介绍多个数码管动态显示的方法。
动态显示的方法是,按一定的频率轮流向各个数码管的COM端送出低电平,同时送出对应的数据给各段。
    -- segment encoding 
    --      0 
    --     ---  
    --  5 |   | 1
    --     ---   <- 6
    --  4 |   | 2
    --     ---  
    --      3
COM is GND
*/


module seg71(clk,dataout,en,led);

input clk;
output[7:0] dataout;
output[3:0] en;//COM使能输出
output led;
reg led;
reg[7:0] dataout;//各段数据输出
reg[3:0] en;

reg[31:0] cnt_scan=0;//扫描频率计数器 10M/2^32=0.02Hz 429.5S 
reg[3:0] dataout_buf;

always@(posedge clk )
begin
    cnt_scan<=cnt_scan+1;
end

always@(posedge clk )
begin
    led<=cnt_scan[23];
end


//频率 10M/65535 = 152 Hz
always @(cnt_scan)
begin
   case(cnt_scan[15:14])
       2'b00 :
         begin
            en = 4'b1110;
            dataout_buf[3:0]= cnt_scan[31:28];
         end
       2'b01 :
         begin
          en = 4'b1101;
          dataout_buf[3:0]=cnt_scan[27:24];  
         end
       2'b10 :
         begin
          en = 4'b1011;
          dataout_buf[3:0]=cnt_scan[23:20];  
         end
       2'b11 :
         begin
          en = 4'b0111;
          dataout_buf[3:0]=cnt_scan[19:16];  
         end
       default :
         begin
          en = 4'b1111;
          dataout_buf[3:0]=4'b1111;  
         end
    endcase
end

always@(dataout_buf)
begin
    case(dataout_buf)
        4'b0000:
            dataout[7:0]=8'b00111111; //0
        4'b0001:
            dataout[7:0]=8'b00000110; //1
        4'b0010:
            dataout[7:0]=8'b01011011; //2
        4'b0011:
            dataout[7:0]=8'b01001111; //3
        4'b0100:
            dataout[7:0]=8'b01100110; //4
        4'b0101:
            dataout[7:0]=8'b01101101; //5
        4'b0110:
            dataout[7:0]=8'b01111101; //6
        4'b0111:
            dataout[7:0]=8'b00000111; //7
        4'b1000:
            dataout[7:0]=8'b01111111; //8
        4'b1001:
            dataout[7:0]=8'b01101111; //9
        4'b1010:
            dataout[7:0]=8'b11110111; //A
        4'b1011:
            dataout[7:0]=8'b11111100; //b
        4'b1100:
            dataout[7:0]=8'b10111001; //c
        4'b1101:
            dataout[7:0]=8'b11011110; //d
        4'b1110:
            dataout[7:0]=8'b11111001; //E
        4'b1111:
            dataout[7:0]=8'b11110001; //F
        default:
            dataout[7:0]=8'b00000000; //         
     endcase
end

endmodule 

使用特权

评论回复
地板
老狼| | 2008-9-17 13:18 | 只看该作者

哈哈,老王也开始FPGA了!

使用特权

评论回复
5
wangkj|  楼主 | 2008-9-18 12:29 | 只看该作者

今天把电子琴调出来啦

使用特权

评论回复
6
钻研的鱼| | 2008-9-18 17:32 | 只看该作者

不错

fpga现在可是用的很广,学习verilog,说明跟上时代潮流

使用特权

评论回复
7
xusn| | 2008-9-22 16:04 | 只看该作者

一开始就要养成好的CODING STYLE

module 里最好每个信号都占一行,
使用parameter来定义各个状态...

使用特权

评论回复
8
wangkj|  楼主 | 2008-9-22 23:52 | 只看该作者

把 扫描键盘(支持组合键) 电子琴 复杂流水灯 都加上了

把 扫描键盘(支持组合键) 电子琴 复杂流水灯 都加上了,感兴趣的看看吧。

串口有点问题没调好也不想调试了,以后再说

顺便改正了开发板的两个bug
1. 蜂鸣器换成交流的,而且,加上了限流电阻
2. 行列扫描线加上上拉电阻

真想自己做个cpld开发板,可是,做完了,也没啥意思 verilog算是基本会用了。

*
7段数码管测试实验1:以动态扫描方式在4位数码管,显示32计数器的高16位值 hex码
实验的目的是向用户介绍多个数码管动态显示的方法。
动态显示的方法是,按一定的频率轮流向各个数码管的COM端送出低电平,同时送出对应的数据给各段。
    -- segment encoding
    --      0
    --     ---  
    --  5 |   | 1
    --     ---   <- 6
    --  4 |   | 2
    --     ---  
    --      3
COM is GND
*/


module seg71(clk,dataout,en,led,row,col,reset,beep,txd,ds);

input clk;
output[7:0] dataout;
output[3:0] en;//COM使能输出
output[7:0] led;
input reset;
reg[7:0] led;
reg[7:0] dataout;//各段数据输出
reg[3:0] en;

inout[3:0] row;
inout[3:0] col;
wire[3:0] row;
wire[3:0] col;
reg[7:0] key;
reg COL_ZERO;
reg ROW_ZERO;

output reg beep;
reg playing;
reg[19:0] counter,counter_end;

assign col[3:0]=COL_ZERO?4'b0000:4'bzzzz;
assign row[3:0]=ROW_ZERO?4'b0000:4'bzzzz;
reg[31:0] cnt_scan;//扫描频率计数器 10M/2^32=0.02Hz 429.5S
reg[3:0]  dataout_buf;

output txd;
reg txd;
output ds;
reg ds;
reg txd_end=0;
reg txd_flag=1;
reg[7:0] txd_clk;
reg[3:0] txd_counter;
reg[7:0] sbuf=8'h33;//first out data
reg[19:0] i=0;

always@(posedge clk)
begin
   cnt_scan=cnt_scan+1;
    //////////////////////////txd///////////////////////////////
    if (txd_flag) //txd_flag=1表示用数据需要发送
    begin
      if (txd_clk==8'd86) //10000000/115200.0=86.805555555555557
      begin
          txd_clk=0;
      end
      if (txd_clk==0) //
         begin
           case (txd_counter) //传送时,数据的低位在前,高位在后
             4'h0:
             begin
              txd=0; //start bit 0
              txd_end=0;
             end
             4'h1:
              txd=sbuf[0];
             4'h2:
              txd=sbuf[1];
             4'h3:
              txd=sbuf[2];
             4'h4:
              txd=sbuf[3];
             4'h5:
              txd=sbuf[4];
             4'h6:
              txd=sbuf[5];
             4'h7:
              txd=sbuf[6];
             4'h8:
              txd=sbuf[7];
             4'h9:
              txd=1;  //stop bit 1
              default:
              txd=1;
           endcase
           if (txd_counter==4'ha)
              begin
                txd_counter=0;
                txd_end=1;  //add stop bit 1
              end
           txd_counter=txd_counter+4'h1;
         end
      txd_clk=txd_clk+4'h1;
    end
    else//if (txd_flag) //txd_flag=1表示用数据需要发送
    begin
    end
    /////////////////////rxd////////////////////////
/*    if(rxd==0 && rxd_start==0)
    begin
       rxd_clk=rxd_clk+1;
       if (rxd_clk==87) //10000000/115200.0=86.805555555555557
          rxd_clk=0;
       if(rxd_clk=43)//中点取样
       begin
       end;
    end
*/
end

always@(posedge clk)
begin
  i=i+20'h1;
  if (txd_end)
     txd_flag=0;
  if (i==20'hfff)  //10M/1M = 0.1/256 s 发送一个数据
  begin
    ds=~ds;
    i=0;
    if (!txd_flag)
    begin
      sbuf[7:0]=8'h01;
      txd_flag=1;
    end
  end
end
always@(posedge cnt_scan[19])// or negedge reset)
begin
//    if (led[7:0]==0)
//      led[7:0]=8'b1111_1111;
//    led[7:0]=led[7:0]<<1;
   // temp = led[7];
//   if (!reset)
//      led[7:0]=8'b1111_1110;
//   else
//     led[7:0]={led[6:0],led[7]};
//    begin
      //led[7:1]<=led[6:0];
      //led[0]<=led[7];
//      led[7:4]=~{key[4],key[5],key[6],key[7]};
//      led[3:0]=~{key[0],key[1],key[2],key[3]};
//    end
   // led[0]=~led[0];
   // led[7:0]=cnt_scan[17:10];
   case (led[7:0])
        8'b1111_1111: led[7:0]= 8'b1111_1110;
        8'b1111_1110: led[7:0]= 8'b1111_1101;
        8'b1111_1101: led[7:0]= 8'b1111_1011;
        8'b1111_1011: led[7:0]= 8'b1111_0111;
        8'b1111_0111: led[7:0]= 8'b1110_1111;
        8'b1110_1111: led[7:0]= 8'b1101_1111;
        8'b1101_1111: led[7:0]= 8'b1011_1111;
        8'b1011_1111: led[7:0]= 8'b0111_1111;
        8'b0111_1111: led[7:0]= 8'b0011_1111;

        8'b0011_1111: led[7:0]= 8'b1001_1111;
        8'b1001_1111: led[7:0]= 8'b1100_1111;
        8'b1100_1111: led[7:0]= 8'b1110_0111;
        8'b1110_0111: led[7:0]= 8'b1111_0011;
        8'b1111_0011: led[7:0]= 8'b1111_1001;
        8'b1111_1001: led[7:0]= 8'b1111_1100;
        8'b1111_1100: led[7:0]= 8'b1111_1110;
        default:led[7:0]= 8'b1111_1111;
    endcase

end


//频率 10M/65535 = 152 Hz
always @(cnt_scan or row or col or key or COL_ZERO or ROW_ZERO)
begin
   case(cnt_scan[15:14])
       2'b00 :
         begin
          en = 4'b1110;
          dataout_buf[3:0]= cnt_scan[31:28];
          COL_ZERO=1;//col 输出0
          ROW_ZERO=0;//row zzzz
         end
       2'b01 :
         begin
          en = 4'b1101;
          dataout_buf[3:0]=cnt_scan[27:24];
          key[3:0]=row[3:0];
         end
       2'b10 :
         begin
          en = 4'b1011;
          dataout_buf[3:0]=key[3:0];
          COL_ZERO=0; //col zzzzzzzz
          ROW_ZERO=1;
        end
       2'b11 :
         begin
          en = 4'b0111;
          key[7:4]=col[3:0];
          dataout_buf[3:0]=key[7:4];

         end
       default :
         begin
          en = 4'b1111;
          dataout_buf[3:0]=4'b1111;  

         end
    endcase
end

always@(dataout_buf)
begin
    case(dataout_buf)
        4'b0000:
            dataout[7:0]=8'b00111111; //0
        4'b0001:
            dataout[7:0]=8'b00000110; //1
        4'b0010:
            dataout[7:0]=8'b01011011; //2
        4'b0011:
            dataout[7:0]=8'b01001111; //3
        4'b0100:
            dataout[7:0]=8'b01100110; //4
        4'b0101:
            dataout[7:0]=8'b01101101; //5
        4'b0110:
            dataout[7:0]=8'b01111101; //6
        4'b0111:
            dataout[7:0]=8'b00000111; //7
        4'b1000:
            dataout[7:0]=8'b01111111; //8
        4'b1001:
            dataout[7:0]=8'b01101111; //9
        4'b1010:
            dataout[7:0]=8'b11110111; //A
        4'b1011:
            dataout[7:0]=8'b11111100; //b
        4'b1100:
            dataout[7:0]=8'b10111001; //C
        4'b1101:
            dataout[7:0]=8'b11011110; //d
        4'b1110:
            dataout[7:0]=8'b11111001; //E
        4'b1111:
            dataout[7:0]=8'b11110001; //F
        default:
            dataout[7:0]=8'b00000000; //         
     endcase
end

always@(posedge clk)
begin
   if ((playing))
   begin
     counter=counter+20'd1;
     if (counter[19:0]==counter_end[19:0])
     begin
         counter=0;
         beep=~beep;
     end
   end
   else
   begin
     beep=0;
   end
end

always@(key or reset)
begin
   if (!reset)
   begin
     counter_end=5000;
     playing=1;
   end
   else
    case(key)
        8'h77:
        begin
              counter_end<=19111;//低音1  5000000/261.63    
              playing<=1;
        end        
        8'hb7:
        begin
              counter_end<=17026;//低音2  293.67    
              playing<=1;
        end        
        8'hd7:
        begin
              counter_end<=15169;//低音3    5000000/329.63  15168.522282559234
              playing<=1;
        end        
        8'he7:
        begin
              counter_end<=14317;//低音4  5000000/349.23        
              playing<=1;
        end        
        8'h7b:
        begin
              counter_end<=12778;//低音5  5000000/391.39 12774.98147627686
              playing<=1;
        end        
        8'hbb:
        begin
              counter_end<=11364;//低音6     5000000/440.0 11363.636363636364    
              playing=1;
        end        
        8'hdb:
        begin
              counter_end=10124;//低音7     5000000/493.88 10123.916740908722    
              playing=1;
        end        
        8'heb:
        begin
              counter_end=9556;//中音1     5000000/523.25 9555.6617295747728    
              playing=1;
        end        
        8'h7d:
        begin
              counter_end=8513;//中音2   5000000/587.33        8513.1016634600637              playing:=1;
              playing=1;
        end        
        8'hbd:
        begin
              counter_end=7584;//中音3   5000000/659.25  7584.3761850587789
              playing=1;
        end        
        8'hdd:
        begin
              counter_end=7159;//中音4   45000000/698.46  7158.6060762248371
              playing=1;
        end        
        8'hed:
        begin
              counter_end=6378;//中音5   55000000/783.99  6377.6323677597929
              playing=1;
        end        
        8'h7e:
        begin
              counter_end=5682;//中音6   5000000/880.0 5681.818181818182
              playing=1;
        end        
        8'hbe:
        begin
              counter_end=5062;//中音7   75000000/987.76   5061.9583704543611
              playing=1;
        end        
        8'hde:
        begin
              counter_end=4778;//高音1   5000000/1046.50   4777.8308647873864
              playing=1;
        end        
        8'hee:
        begin
              counter_end=4257;//高音2   5000000/1174.66   4256.5508317300319
              playing=1;
        end        
        8'h6e:
        begin
              counter_end=3792;//高音3   5000000/1318.51   3792.1593313664666
              playing=1;
        end        
        8'hae:
        begin
              counter_end=3579;//高音4   5000000/1396.92   3579.3030381124186
              playing=1;
        end        
        8'hce:
        begin
              counter_end=3189;//高音5   5000000/1567.98  3188.8161838798965
              playing=1;
        end        
        8'hec:
        begin
              counter_end=2841;//高音6   5000000/1760.0 2840.909090909091
              playing=1;
        end        
        8'hea:
        begin
              counter_end=2531;//高音7   5000000/1975.52   2530.9791852271806
              playing=1;
        end        
        8'hff:
        begin
              //counter_end=20'hx_xxxx;//静音
              playing=0;
        end        
        default:
        begin
              //counter_end[19:12]=1000;//key test                        
              playing=0;
        end        
     endcase
end


endmodule 

使用特权

评论回复
9
钻研的鱼| | 2008-9-23 08:20 | 只看该作者

提个建议

always@(posedge cnt_scan[19])// 
看到这个模块,能够推测你程序里不是全同步设计,即用同一个时钟,这样设计出来的程序的时序很难控制。例外,你的程序里很多是异步设计,注意冒险。

使用特权

评论回复
10
wangkj|  楼主 | 2008-9-23 08:43 | 只看该作者

cnt_scan[19] 是clk的2^19次分频

所有的时钟控制都是靠的clk信号,只不过用的其分频信号。

使用特权

评论回复
11
钻研的鱼| | 2008-9-24 08:34 | 只看该作者

不要这样做.

在fpga里面这叫做行波信号,不要这样做.
应该用cnt_scan[19]作为触发器的使能信号,而不是时钟信号!只要有沿触发,所有的always里面都用同一源,否则fpga内部的setup/hold时间很难分析

使用特权

评论回复
12
dragon_hn| | 2008-11-3 15:00 | 只看该作者

同意10楼

同意10楼
即使分频时钟,反向时钟最好也不要用,除非你非常肯定时钟边沿或门电路延迟与其他接口没任何关系.
对分频时钟可以拿它当D触发的使能端,效果是一样的.
---------------------------------------------------------------
不过我觉得对CMOS芯片设计,采用全同步设计可能会导致功耗增加,要想做到功耗最低,有些地方还是应该同步与异步相结合.

使用特权

评论回复
13
pnono| | 2008-11-3 15:14 | 只看该作者

异步

异步控制的时候有很多未知因素
建议还是用同步的好
FPGA我不太懂
只是学过一点点verilog

使用特权

评论回复
14
zjf0000| | 2008-11-18 11:43 | 只看该作者

应该这样做吧

//频率 10M/65535 = 152 Hz
always @(cnt_scan)
/////////////////
always @(clk)
begin
   case(cnt_scan[15:14])

使用特权

评论回复
15
wang6895| | 2008-11-20 10:26 | 只看该作者

回复主题:verilog 处>女做,第一次学写verilog程序

第一次就做这么好
继续加油啊

使用特权

评论回复
16
sheshichu| | 2009-10-16 16:58 | 只看该作者
学习了。我也一直这么写程序的。开发板提供的程序也这样。。。
以为只要同一时钟驱动就行呢:L

使用特权

评论回复
17
ma9453| | 2009-10-22 22:00 | 只看该作者
学习学习~~

使用特权

评论回复
18
李冬发| | 2009-10-26 00:56 | 只看该作者
千万别把verilog语言写的东西叫做程序。这东西与程序是不一样的。

使用特权

评论回复
19
white5502| | 2009-11-30 13:41 | 只看该作者
原来分频信号也要用的谨慎,学习了

使用特权

评论回复
20
wangkj|  楼主 | 2009-12-1 08:33 | 只看该作者
看到老帖子很亲切,现在,俺已经搞到verilog写出vga cpld单片机显卡啦。在diy板块。
一年苦力呀。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

581

主题

9976

帖子

24

粉丝