Verilog语言“加减可控任意进制计数器”及“占空比50%的任意整数分频器”设计

Verilog语言“加减可控任意进制计数器”及“占空比50%的任意整数分频器”设计

今天(2017年12月28)考EDA实验,考的真是惊险刺激,最后实现了四分之三的功能。
今天的使用时设计一个可以实现使用指定拨码开关控制加减计数、使能、清零的13进制计数器,并且是由两位数码管显示结果,在加法计数器中,加法加到最大值12时需要点亮一盏LED,加法计数器中减到最小值0时也需要点亮一盏LED。下面是我的程序:

  counter13.v文件:
  /*
CLK位时钟输入,CLR为1异步清零,A_S_CTRL为加减控制端
*/
module counter12 (CLK, CLR,EN,A_S_CTRL,SHOW1,SHOW2,LED1,LED2);
    input CLK,EN,CLR,A_S_CTRL;//时钟,使能,清零,加减控制
    output LED1,LED2;//最大值进位,最小值借位,用来满足题目对LED点亮的要求
    wire[3:0] DISP1,DISP2;//中间变量,数码管要显示的数字
    output[6:0] SHOW1,SHOW2;//输出变量,数码管的段码
    reg[3:0] DOUT;//计数器计数输出,此处不需要输出,仅作为中间变量
    reg LED1,LED2;
    assign DISP1 = (DOUT < 10) ? DOUT : (DOUT - 10);//小于10则,直接显示,大于10则减去10,只显示个位
    assign DISP2 = (DOUT >= 10) ? 1 : 0;//大于等于10,则十位为1,否则十位为0
    always@(posedge CLK or negedge CLR)
        begin
            if(!CLR)//asynchronous reset,low level actve
                DOUT = 0;
            else if(EN)//synchronous enable,high level actve
                begin
                    if(A_S_CTRL == 1 & DOUT == 12)
                        begin
                        DOUT = 0;
                        LED1 = 1;
                        end
                    else if(A_S_CTRL == 0 & DOUT == 0)
                        begin
                        DOUT = 12;
                        LED2 = 1;
                        end
                    else if(A_S_CTRL == 1)// up counter加法计数
                        begin
                        DOUT = DOUT + 1;
                        LED1 = 0;
                        end
                    else if(A_S_CTRL == 0)// down counter接法计数
                        begin
                        DOUT = DOUT - 1;
                        LED2 = 0;
                        end
                end
        end
    display U1(.datain(DISP1),.sm_db(SHOW1));//例化语句调用显示模块
    display U2(.datain(DISP2),.sm_db(SHOW2));
endmodule
display.v文件:
/*显示0到9的数字,数码管译码器*/
module display(datain,sm_db);
    input[3:0] datain;
    output[6:0]sm_db;
    reg[6:0]sm_db;
    always@(datain)
        begin
            case(datain)
                4'h0:sm_db <= 7'b0111111;
                4'h1:sm_db <= 7'b0000110;
                4'h2:sm_db <= 7'b1011011;
                4'h3:sm_db <= 7'b1001111;
                4'h4:sm_db <= 7'b1100110;
                4'h5:sm_db <= 7'b1101101;
                4'h6:sm_db <= 7'b1111101;
                4'h7:sm_db <= 7'b0000111;
                4'h8:sm_db <= 7'b1111111;
                4'h9:sm_db <= 7'b1101111;
                4'ha:sm_db <= 7'b1110111;
                4'hb:sm_db <= 7'b1111100;
                4'hc:sm_db <= 7'b0111001;
                4'hd:sm_db <= 7'b1011110;
                4'he:sm_db <= 7'b1111001;
                4'hf:sm_db <= 7'b1110001;
                default:;
            endcase
        end
endmodule 

以上程序实现了这个功能。
以上程序是由一个加减可控的可预置的十进制计数器修改而成的,通过修改几个参数,既可以构成任意进制的计数器:

counter10.h文件:
module counter10 (DIN,CLK, CLR,EN,LOAD,A_S_CTRL,COUT,DOUT);
    input [3:0] DIN;
    input CLK,EN,CLR,LOAD,A_S_CTRL;
    output[3:0] DOUT;
    output COUT;
    reg[3:0] DOUT;
    reg COUT;

    always@(posedge CLK or negedge CLR or negedge LOAD)
        begin
            if(!CLR)//asynchronous reset,low level actve
                DOUT = 0;
            else if(!LOAD)//asynchronous load,low level actve
                DOUT = DIN;
            else if(EN)//synchronous enable,high level actve
                begin
                    if(A_S_CTRL == 1 & DOUT ==9)
                        begin
                        COUT = 1;
                        DOUT = 0;
                        end
                    else if(A_S_CTRL == 0 & DOUT ==0)
                        begin
                        COUT = 1;
                        DOUT = 9;
                        end
                    else if(A_S_CTRL == 1)// up counter
                        begin
                        COUT = 0;
                        DOUT = DOUT + 1;
                        end
                    else if(A_S_CTRL == 0)// down counter
                        begin
                        COUT = 0;
                        DOUT = DOUT - 1;
                        end
                end
        end
endmodule

以下是我修改的一个6进制计数器,可以对比看一下,只修改了很少的东西:

module counter6 (DIN, CLK, CLR, EN, LOAD, A_S_CTRL, COUT, DOUT);
    input [3:0] DIN;
    input CLK,EN,CLR,LOAD,A_S_CTRL;
    output[3:0] DOUT;
    output COUT;
    reg[3:0] DOUT;
    reg COUT;

    always@(posedge CLK or negedge CLR or negedge LOAD)
        begin
            if(!CLR)//asynchronous reset,low level actve
                DOUT = 0;
            else if(!LOAD)//asynchronous load,low level actve
                DOUT = DIN;
            else if(EN)//synchronous enable,high level actve
                begin
                    if(A_S_CTRL == 1 & DOUT == 5)
                        begin
                        COUT = 1;
                        DOUT = 0;
                        end
                    else if(A_S_CTRL == 0 & DOUT == 0)
                        begin
                        COUT = 1;
                        DOUT = 5;
                        end
                    else if(A_S_CTRL == 1)// up counter
                        begin
                        COUT = 0;
                        DOUT = DOUT + 1;
                        end
                    else if(A_S_CTRL == 0)// down counter
                        begin
                        COUT = 0;
                        DOUT = DOUT - 1;
                        end
                end
        end
endmodule

接下来设占空比为百分之50的任意整数分频器:
顶层文件:

module FrqDivder (fin,fout,m);//分频输入,偶分频输出,奇分频输出,分频系数
input fin;
output fout;
input[3:0] m;
wire foute,fouto;
EvenFrqDiv U1(.fin(fin),.fout(foute),.m(m));
OddFrqDiv U2(.fin(fin),.fout(fouto),.m(m));
mux21(.fin1(fouto), .fin2(foute), .ctrl(m), .fout(fout));

endmodule

偶数分频器:

EvenFrqDiv.v文件:
module EvenFrqDiv (fin,fout,m);//输入,输出,分频系数
input fin;
input[3:0] m;
wire[3:0] n;
assign n = m/2;
output fout;
reg fout;
reg [3:0] q1;
always @ (posedge fin)
    begin
      q1=q1+1;
      if(q1 >= n)
        begin
           q1=0;
           fout=~fout;
        end
    end
endmodule

奇数分频器:

module OddFrqDiv (fin,fout,m);//输入,输出,分频系数
input fin;
input[3:0] m;
wire[3:0] n;
output fout;
reg fout1,fout2;
reg [3:0] q1,q2;
assign n = (m+1) >> 1;
always @ (posedge fin)
    begin
      q1=q1+1;
      if(q1 == n)
      begin
          fout1=~fout1;
      end
      else if(q1 == m)
      begin
           q1=0;
           fout1=~fout1;
      end
    end 
always @ (negedge fin)
    begin
      q2=q2+1;
      if(q2 == n)
      begin
          fout2=~fout2;
      end
      else if(q2 == m)
      begin
           q2=0;
           fout2=~fout2;
      end
    end 
assign fout = fout1 | fout2;
endmodule

二选一多路选择器:

module mux21(fin1,fin2,ctrl,fout);
    input fin1,fin2;
    input [3:0] ctrl;
    output fout;
    assign fout = ctrl[0] ? fin1 : fin2;
endmodule

RTL图:
Verilog语言“加减可控任意进制计数器”及“占空比50%的任意整数分频器”设计_第1张图片
工程结构图:
Verilog语言“加减可控任意进制计数器”及“占空比50%的任意整数分频器”设计_第2张图片

今天(2017年12月28)考EDA实验,考的真是惊险刺激,最后实现了四分之三的功能。
这个过程中我做的很认真,自认为设计思路也是很好,但刚开始的方案不可行,后来改了一种方案,编译没有错。然后一步步的修改完善,把所有的功能一步一步往上加,把多余的功能一定一定删掉,使得整个程序简洁直观。最后的仿真很完美,然后准备下载。可是正当下载进去准备见证奇迹的时候,却发现毫无反应。时间已经到达最后关头,我还心里提醒自己:镇静,冷静找一下错误,仿真那么完美,不可能有错的,可能只是一个小错误。找了一会儿,还是没找出来,哎,先写报告吧,等老师验收的时候问一下老师吧。好来老师到了,我把情况说明了,老师也没马上找出原因。我说老师,我申请换一台实验箱,老师说那你换一下吧,可是换了实验箱仍然没有什么用。哎,为什么,老师突然说,你是不是绑定完引脚没有重新编译啊。我突然想起,是啊,平常在电脑上一直使用仿真,从来没有下载进去,好久没下载了,都忘记了绑定引脚要编译,唉,该死。重新编译下载进去后终于好了,数码管亮了,然后我略有慌乱的拨弄了控制开关,终于后面三个功能都实现了。
还剩第一个分频器,那个题目其实感觉很简单,因为我之前花了不少时间研究分频器,只是没实现那么高频率的分频。思路很清晰,20MHZ分频成1Hz,使用一个25位的计数器,2的25次方等于(33,554,432),计数到10乘以10的6次翻转一次电平就可以了,然后达到20兆分频了。我说老师,那个分频器窝可以在做一下吗,我改两个参数应该就可以了。老师说不行,没时间了。那好吧,老师对我也算仁至义尽了。于是我就坐在倒数第二排把没写完的报告写完。
过后的那种感觉真的很奇妙,就是有些事情你真的用心去做 了,努力了,你会真的很在乎它,你绝对不会吧失败看的风轻云淡,至少要有一些成果。遗憾也常常是有的,就是那种差一点就成功了,却不能够成功。但最终事后还是开心的,因为你问心无愧。真的努力过,结果一般都会有一些,可能只是没有达到期望的而已。
这让我想起了今年夏天的电赛,我的队长,他真的是很在乎这个比赛,他说他想去西安,参加国赛。他说这话的时候,很认真,他的话让我心里有些不安,因为我知道,我撑不起他的梦想,我太菜了。电赛期间,他经常通宵到半夜两三点,当然通宵也算他的一种习惯吧。后来实现了前面三项功能。在省赛区验收的时候,由于我们的电路板的工艺的问题,调试时实现的功能,有的没实现,而且偏差很大。队长很紧张,我可以看出来,他一直在咽口水,调试的手也在发抖。最终被封箱了,留作下一步评审,后来得了个省级二等奖。队长很不甘心,他说心里真不是滋味。但对于我这种菜鸡来说,已经挺不错的了。事后队长说,他调试那时候,紧张到肚子疼。现在我觉得我可以理解这种感觉了。唉,无奈,有时我也替队长惋惜,他选队友怎么会选我这种菜鸡,我真的是拖队长的后腿了。但是通过暑假电赛,说真的,我学到了很多,收获了很多,还认识了不少人,还沾队长和另一位队友的光得了个小奖(可是这也是我目前科技方面大学得的最高奖了,由此知道我有多菜了吧)。大家有没有发现我老是一口一个队长队长的,我的队长并不是有多突出,技术不是说有多厉害,是因为我感谢他,心里面敬重他,他可以说是我动手实践入门的“导师”。通过这次暑假电赛,我觉的我和队长也结下了不解的友缘,我觉的我的队长很真诚,乐于助人,不虚伪,没有那种很多人有的自以为是的盲目傲慢,我们也很熟了,我觉得队长真的算我大学里的一个朋友了。在此写了这么多,也表示对队长的感谢。
突然肚子咕噜一响,好像还没吃晚饭呢,哇,已经11点多了,该休息了。约到后面越写的不详细,改天在更吧,希望对大家有所帮助。

你可能感兴趣的:(FPGA)