Modelsim软件进行HDL程序设计开发——电子表

一、目的

1、熟悉Modelsim 软件

2、掌握Modelsim软件的编译、仿真方法

3、熟练运用Modelsim软件进行HDL程序设计开发

4、电子表的设计,包括正常计时模块,LED显示模块,定时报警模块,校时模块,秒表模块。

二、原理与方法:

应用Verilog 语言编写频率可调的四种波形发生的程序,加深了解Verilog 的编程以及用modlesim进行波形仿真的能力,并通过QUARTUS II进行时序仿真回顾QUARTUE II 的操作,加强对这两种软件的实际应用操作能力,同时将这门实验课的理论基础和实践联系起来,培养学生的实践能力和应用能力。

Verilog是一种硬件描述语言:用程序设计语言来描述数字电路的功能,提高设计效率。早期数字电路设计是基于原理图输入的,类似电路板的PCB原理图设计。电子表的设计包括正常计时模块,LED显示模块,定时报警模块,校时模块,秒表模块。

Verilog语法:

可综合描述:综合tool能够把verilog描述转化(compile)成基本的数字电路底层cell(与或非gate,寄存器等)的描述。

不可综合描述:综合tool不能把verilog描述转换为基本的数字电路底层cell的描述。

verilog设计仿真与实现:通过EDA tool,可以在计算机上对verilog设计的功能进行仿真。

常用的仿真工具(所有verilog描述):Modelsim/Questasim(Mentor)通过模块module的层次化设计,实现一个复杂的数字逻辑功能。

标识符:

用于定义code中的各种名字,比如:信号,module,define,parameter;

标识符由:字符,数字,下划线组成;

首字母必须是字母或者下划线;

标识符是区分大小写的;

信号名字建议与信号功能相对应:rstn,clk_core,mem_cs,mem_we,mem_dout,mem_din,mem_addr;

数据物理类型:

线性数据:用于连续赋值语句(assign)描述组合逻辑或者module间的信号连接线。

1. Verilog HDL程序是由模块构成的。每个模块嵌套在module和endmodule声明语句中。

2 每个Verilog HDL源文件中只有一个顶层模块,其他为子模块。可以每个模块写一个文件。

3.每个模块要进行端口定义,并说明输入输出端口,然后对模块的功能进行行为逻辑描述。

4.模块中的时序逻辑部分在always块的内部,在always块中只能对寄存器变量赋值。

5.模块中对端口或其他wire型变量的赋值,必须在always块的外部使用assign语句,通常是将寄存器的值送出

6.程序书写格式自由,一行可以写几个语句,一个语句也可以分多行写。

7. 除了endmodule语句、begin_end语句和fork_join语句外,每个语句和数据定义的最后都要加分号

8.可用/*.....*/和//...对程序的任何部分作注释。加上必要的注释,可以增强程序的可读性

时钟生成模块

这里需要注意的一个地方,通常我们见到的时间都是十进制的,但是我们用计数器计数之后输出的数据通常为16进制数。

十进制数显示的范围为0~9;

十六进制数显示的范围为0~f;我们需要的数只有0到9,所以当数超过9时对于我们的电子表来说是多余的。因此我们需要对十六进制数进行转换,让输出的数(也就是数码管上显示的数)为十进制。

其转换原理为:

对应十进制数大于9时,进行加6操作;

对应十进制数大于19时,进行加12操作;

对应十进制数大约29时,进行加18操作;

以此类推···

其转换的核心思想是将二进制数转化为BCD码

计数器部分中包含有三个主要计数部分,分别是十进制、六进制以及二十四进制,其中六进制和十进制共同组成六十进制,即实现分和秒的计数,之所以将其分开是便于分别显示个位和十位,通过编写计数器,来计数信号的数量,从而实现时分秒按各自的进制正常计数,同时,将前一时钟单位的进位信号作为下一时钟单位的clk,即从后向前驱动,这样便实现了时钟的正常运转。

二、内容:

(1)正常计时模块clock

module clock(clk,rst,clock_en,second,minute,hour);

input clk,rst,clock_en;

output[5:0]second,minute,hour;

reg[5:0]second,minute,hour;

always@(posedge clk or negedge rst or posedge clock_en)

if(!rst)

begin

second<=0;  minute<=0;  hour<=0;

end

else if(clock_en)

begin

if(second==59)

   begin

   minute<=minute+1;

   second<=0;

   end

else if(minute==59)

   begin

   hour<=hour+1;

   minute<=0;

    end

else if(hour==23)

   hour<=0;

else

second<=second+1;

end

endmodule

(2)LED显示模块LED_display

module LED_display(data,high,low);

input[5:0]data;

output[7:0]high,low;

reg[7:0]high,low;

reg[3:0]out_h,out_l;

always@(data)

begin

out_h<=data/10;

out_l<=data;

end

always@(out_l)

    case(out_l)

          4'b0000:low<=8'b00000000;

          4'b0001:low<=8'b01100000;

          4'b0010:low<=8'b11011010;

          4'b0011:low<=8'b11110010;

          4'b0100:low<=8'b01100110;

          4'b0101:low<=8'b10110110;

          4'b0110:low<=8'b10111110;

          4'b0111:low<=8'b11100000;

          4'b1000:low<=8'b11111110;

          4'b1001:low<=8'b11110110;

          default:low<=8'b00000000;

     endcase



     always@(out_h)

     case(out_h)

          4'b0000:high<=8'b00000000;

          4'b0001:high<=8'b01100000;

          4'b0010:high<=8'b11011010;

          4'b0011:high<=8'b11110010;

          4'b0100:high<=8'b01100110;

          4'b0101:high<=8'b10110110;

          4'b0110:high<=8'b10111110;

          4'b0111:high<=8'b11100000;

          4'b1000:high<=8'b11111110;

          4'b1001:high<=8'b11110110;

          default:high<=8'b00000000;

     endcase

 endmodule

(3)定时模块timing和报警模块alarm

module timing(rst,timing_en,hour,minute,hour,location_adjust,timing_adjust,hour_timing,minute_timing,secong_timing,out);

input rst,timing_en,location_adjust;

input[5:0]minute,hour,second;

output[5:0]second_timing,minute_timing,hour_timing;

reg[5:0]second_timing,minute_timing,hour_timing;

output out;

reg[1:0]location

always@(negedge rst or posedge timing_en or posedge location_adjust)

if(!rst)

begin

second_timing<=0; minute_timing<=0; hour_timing<=0;location<=0;

end

else if(location_adjust==1)

  begin

    if(location==2'b10)

      location<=2'b00;

    else

      location<=location+1;

  end

else if(timing_en==1)

begin

  if(location==2'b00)

    hour_timing<=hour_timing+1;

  else if(location==2'b01)

    minute_timing<=minute_timing+1;

  else if(location==2'b10)

    second_timing<=second_timing+1;

  else

    begin

      second_timing<=second_timing;

      minute_timing<=minute_timing;

      hour_timing<=hour_timing;

    end

end

assign out=(hour_timing==hour && minute_timing==minute && second_timing==second)?1:0;

endmodule



//报警模块alarm

module alarm(clk,rst,alarm_en,alarm_out);

input clk,rst,alarm_en;

output alarm_out;

reg alarm_out;

reg[4:0] count;

always@(posedge clk or negedge rst)

if(!rst)

begin

  alarm_out<=0;

  count<=0;

end

else if(alarm_en==1)

begin

   if(count==29)

       begin

        count<=0;

        alarm_out<=0;

      end

   else

     begin

      count<=count+1;

      alarm_out<=1;

     end

end

else

  begin

   count<=0;

  alarm_out<=0;

  end

endmodule

(4)校时模块adjust_time

module adjust_time(rst,adjust_en,location_adjust,second,minute,hour,second_adjust,minute_adjust,hour_adjust);

input rst,adjust_en,location_adjust;

input[5:0]second,minute,hour;

output[5:0]second_adjust,minute_adjust,hour_adjust;

reg[5:0]second_adjust,minute_adjust,hour_adjust;

reg[1:0]location



always@(posedge adjust_en or location_adjust or negedge rst)

if(!rst)

  begin

   second_adjust<=0;minute_adjust<=0;hour_adjust<=0;location<=0;

  end

else if(location_adjust)

       begin

       if(location==2'b10)

       location<=2'b00;

       else

       location<=location+1;

       end

else if(adjust_en==1)

     begin

     case(location)

     2'b00:  hour_adjust<=hour_adjust+1;

     2'b01:  minute_adjust<=minute_adjust+1;

     2'b10:  second_adjust<=second_adjust+1;

     default:

            begin

             hour_adjust<=0;

             minute_adjust<=0;

             second_adjust<=0;

             end

    endcase

end

endmodule

//(5)秒表模块second_watch

module second_watch(clk,rst,watch_en,stop,minute,second);

input clk,rst,watch_en,stop;

output[5:0]minute,second;

reg[9:0]dout;

always(posedge clk or negedge rst)

if(!rst)

dout<=0;

else if(watch_en)

    begin

    if(stop==1)

     dout<=dout;

    else if(dout==999&&stop==1)

         dout<=0;

    else

      dout<=dout+1;

      end

assign minute=dout/60;

assign second=dout`;

endmodule

// (6)计时,报警,校时,秒表状态的转换

 module state(clk,rst,c0,c1,c2,c3,clock_en,timing_en,adjust_en,watch_en);



input clk,rst,c0,c1,c2,c3;

output clock_en,timing_en,adjust_en,watch_en;

reg clock_en,timing_en,adjust_en,watch_en;

reg[3:0]state,next_state;

parameter s0=4'b0000,s1=4'b0001,s2=4'b0010,s3=4'b0011;



    always@(posedge clk)

    if(!rst)

    state<=s0;

    else

    state<=next_state;



    always@(state or rst or c0 or c1 or c2 or c3)

    begin

        if(!rst)

        next_state<=s0;

        else

        begin

            case(state)

                s0:  begin

                       if(c1)

                       next_state<=s1;

                       else if(c2)

                       next_state<=s2;

                       else if(c3)

                       next_state<=s3;

                       else

                       next_state<=s0;

                     end

                 s1: begin

                     if(c1)

                     next_state<=s1;

                     else if(c2)

                     next_state<=s2;

                     else if(c3)

                     next_state<=s3;

                     else

                     next_state<=s0;

                     end

                s2: begin

                    if(c1)

                    next_state<=s1;

                    else if(c2)

                    next_state<=s2;

                    else if(c3)

                    next_state<=s3;

                    else

                    next_state<=s0;

                    end

                s3: begin

                    if(c1)

                    next_state<=s1;

                    else if(c2)

                    next_state<=s2;

                    else if(c3)

                    next_state<=s3;

                    else

                    next_state<=s0;

                    end

                default:next_state<=s0;

          endcase

      end

  end



  always@(state)

  begin

      case(state)

          s0: begin  (计时)

              clock_en<=1;

              timing_en<=0;

              adjust_en<=0;

              watch_en<=0;

              end

          s1: begin(定时报警)

              clock_en<=1;

              timing_en<=1;

              adjust_en<=0;

              watch_en<=0;

              end

          s2: begin(校时)

              clock_en<=0;

              timing_en<=0;

              adjust_en<=1;

              watch_en<=0;

              end

          s3: begin(秒表)

              clock_en<=1;

              timing_en<=0;

              adjust_en<=0;

              watch_en<=1;

              end

          default:begin

                  clock_en<=1;

                  timing_en<=0;

                  adjust_en<=0;

                  watch_en<=0;

                  end

          endcase

      end

  endmodule

 // (7)电子表顶层模块dianzibiao_top

//`include"adjust_time.v"

//`include"alarm.v"

//`include"clock.v"

//`include"LED_display.v"

//`include"second_watch.v"

//`include"state.v"

//`include"timing.v"

//`include"top.v"

module dianzibiao_top( clk,rst,c0,c1,c2,c3,stop,location,hour_h,hour_l,minute_h,minute_l,second_h,second_l,alarm_out);



input clk,rst,c0,c1,c2,c3,stop,location;

output[7:0]hour_h,hour_l,minute_h,minute_l,second_h,second_l;

output alarm_out;

wire[5:0]second,minute,hour,second_clock,minute_clock,hour_clock,hour_LED,minute_LED,second_LED,sec_timing,min_timing,hour_timing,sec_adjust,min_adjust,hour_adjust,minute_adjust,second_adjust;

wire clock_en,alarm_en,timing_en,adjust_en,watch_en;

wire[5:0]minute_w,second_w;



clock clock1(.second(second_clock),.minute(minute_clock),.hour(hour_clock),.clock_en(clock_en),.clk(clk),.rst(rst));



LED_display LED_display1(.data(hour_LED),.high(hour_h),.low(hour_l));

LED_display LED_display2(.data(minute_LED),.high(minute_h),.low(minute_l));

LED_display LED_display3(.data(second_LED),.high(second_h),.low(second_l));



alarm alarm1(.alarm_out(alarm_out),.alarm_en(alarm_en),.clk(clk),.rst(rst));



timing timing1(.rst(rst),.timing_en(timing_en),.location_adjust(location),.hour(hour_clock),.minute(minute_clock),.second(second_clock),.second_timing(sec_timing),.minute_timing(min_timing),.hour_timing(hour_timing),.out(alarm_en));



adjust_time adjust_time1(.rst(rst),.adjust_en(adjust_en),.location_adjust(location),.hour(hour_clock),.minute(minute_clock),.second(second_clock),.second_adjust(sec_adjust),.minute_adjust(min_adjust),.hour_adjust(hour_adjust));



second_watch second_watch1(.watch_en(watch_en),.clk(clk),.rst(rst),.stop(stop),.minute(minute_w),.second(second_w));



state state1(.clk(clk),.rst(rst),.c0(c0),.c1(c1),.c2(c2),.c3(c3),.clock_en(clock_en),.timing_en(timing_en),.adjust_en(adjust_en),.watch_en(watch_en));



assign hour=c1?hour_timing:hour_clock;

assign minute=c1?min_timing:minute_clock;

assign second=c1?sec_timing:second_clock;

assign minute=c3?minute_w:minute_clock;

assign second=c3?second_w:second_clock;

assign hour=c2?hour_adjust:hour_clock;

assign minute=c2?min_adjust:minute_clock;

assign second=c2?sec_adjust:second_clock;

assign hour_LED=hour;

assign minute_LED=minute;

assign second_LED=second;



endmodule

运行结果:

秒分进位:

时分进位:

整点报时:

Testbench

1.编写各个模块的VHDL代码并进行编译与波形仿真,仿真无误后生成元件符号。

2.设计数字钟电路的顶层文件,在顶层文件中调入第一步中生成的元件符号,并根据连接关系将它们连接在一起。

3.引脚分配,为顶层设计文件中的各个输入输出端口分配芯片相应的引脚。4.下载程序到芯片,观看实验现象是否为预想的那样。同时使用清零按键看能否实现清零,时间正常走动情况下通过按键能否实现校时。

下载成功后,拨动开关 DP4至高电平,使六个数码管复位清零;拨动开关 DP4至低电平,数字钟开始自动计,此过程中可以通过1键设置小时数,2键设置分钟数。当秒数满60则进一位,分钟数满60进一位,当显示为23:59:59 时,秒数在加一则显示 00:00:00,同时指示一天结束的LED灯亮 10秒,之后从新计时。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值