首页 > 名字 > 游戏名字 正文
修炼计算器——梦幻西游修炼计算器…

时间:2023-07-30 作者:佚名

本文为明德扬原创及录用文章,转载请注明出处!


1.1 总体设计
1.1.1 概述

计算器是近代人发明的可以进行数字运算的机器。现代的电子计算器能进行数学运算的手持电子机器,拥有集成电路芯片,但结构比电脑简单得多,可以说是第一代的电子计算机,且功能也较弱,但较为方便与廉价,可广泛运用于商业交易中,是必备的办公用品之一。除显示计算结果外,还常有溢出指示、错误指示等。计算器电源采用交流转换器或电池。为了节省电能,计算器都采用CMOS工艺制作的大规模集成电路。


计算器一般由运算器、控制器、存储器、键盘、显示器、电源和一些可选外围设备及电子配件,通过人工或机器设备组成,抵挡计算器的运算器、控制器由数字逻辑电路实现简单的串行运算

计算器是最早的计算工具,例如:古代印加人利用许多颜色的绳结来计数或者记录历史,还有古希腊人的安提凯希拉装置,中国的算盘等。中国古代最早采用的一种计算工具叫筹策,又被叫做算筹。


1.1.2 设计目标

简易计算器支持简单的四则运算(支持负数),在此基础上,添加了连续运算功能。计算器面板如下:


1、 计算器通过矩阵键盘模拟按键输入,并通过数码管显示。

2、 计算器有“0、1、2、3、4、5、6、7、8、9、+、-、*、/、C、=”共16个按键。

3、 计算器不支持输入负数,运算结果支持负数但不支持小数。

4、 运算数1、运算数2以及运算结果最大支持8位。其中,运算数1和运算结果的位数包括符号位“-”。

5、 运算数1和运算数2的默认值为0.

6、 计算器支持连续运算,允许在输入运算数2后按下运算符,或者得出运算结果后按下运算符。

7、 当运算结果溢出时,数码管显示8个F。

8、 当操作数1或者操作数2的长度溢出时,蜂鸣器会响。


1.1.3 系统结构框图

系统结构框图如下所示:

图一


1.1.4模块功能

键盘扫描模块实现功能

1、将外来异步信号打两拍处理,将异步信号同步化。

2、实现20ms按键消抖功能。

3、实现矩阵键盘的按键检测功能,并输出有效按键信号。


工作状态选择模块实现功能

1、 根据接收的不同的按键信号,判断和决定计算器的工作状态。共有5种状态:输入运算数1(OP_1)、运算符(OPER)、输入运算数2(OP_2)、输出结果(RESULT)、结果错误(ERROR)

  • 运算数1模块实现功能

1、 当计算器处于运算数1状态下,任何连续输入的数字(不超过8位)都将存放在该模块中,作为运算数1.

2、 当运算数已经到达8位时,此时无论输入任何数字,运算数1不变。

3、 当计算器经过一次运算后(按下等号或者在运算数2状态下按下运算符),运算数去存放结果result。

  • 运算符模块实现功能

1、 保存最新按下的运算符。

  • 运算数2模块实现功能

1、 当计算器处于运算数2状态下,任何连续输入的数字(不超过8位)都将存放在该模块中,作为运算数2,默认值为0。

2、 当运算数2已经到达8(包括符号位“-”),此时无论输入任何数字,运算数2不变。

  • 运算单元模块实现功能

1、 当计算器处于运算数2状态下按下运算符或者在任何状态下按下等号时,该模块根据此时运算数1、运算数2以及运算符的值,进行运算。

2、 若运算结果溢出,或者长度大于8位(包括符号位“-”)或者除数为0时,输出8个F。

3、 最多保留运算结果整数部分的8个有效数字,不保留任何小数。

  • 显示对象选择模块实现功能

1、 该模块的作用是根据当前计算器的工作状态来选择数码管的显示内容。

  • 数码管显示模块实现功能

1、 该模块的作用是对显示对象选择模块的显示数据输出信号进行数码管显示。

  • 蜂鸣器模块实现功能

1、 该模块的作用是对各种错误输入或输出进行响铃警告。


1.1.5顶层信号




1.1.6参考代码

module  calc_project(     clk     ,     rst_n   ,     key_col ,     key_row ,     seg_sel ,     segment ,     beep        );     parameter   KEY_WID     =   4   ;     parameter   STATE_WID   =   5   ;     parameter   NUM_WID     =   27  ;     parameter   SEG_NUM     =   8   ;     parameter   SEG_WID     =   8   ;     input                       clk         ;     input                       rst_n       ;     input   [KEY_WID-1:0]       key_col     ;     output  [KEY_WID-1:0]       key_row     ;     output  [SEG_NUM-1:0]       seg_sel     ;     output  [SEG_WID-1:0]       segment     ;     output                      beep        ;     wire    [KEY_WID-1:0]       key_num     ;     wire                        key_vld     ;     wire    [KEY_WID-1:0]       key_num_out ;     wire    [KEY_WID-1:0]       key_vld_out ;     wire    [STATE_WID-1:0]     state_c     ;     wire    [NUM_WID-1:0]       op_1        ;     wire                        op_1_err    ;     wire    [KEY_WID-1:0]       oper        ;     wire    [NUM_WID-1:0]       op_2        ;     wire                        op_2_err    ;     wire    [NUM_WID-1:0]       result      ;     wire                        result_err  ;     wire                        result_neg  ;        wire    [SEG_NUM*4-1:0]     display     ;     wire                        display_vld ;     key_scan   key_scan_prj(                             .clk        (clk    )   ,                             .rst_n      (rst_n  )   ,                             .key_col    (key_col)   ,                             .key_row    (key_row)   ,                             .key_out    (key_num)   ,                             .key_vld    (key_vld)                             );     work_state  work_state_prj(                                 .clk        (clk        )   ,                                 .rst_n      (rst_n      )   ,                                 .key_num    (key_num    )   ,                                 .key_vld    (key_vld    )   ,                                 .result_err (result_err )   ,                                 .key_num_out(key_num_out)   ,                                 .key_vld_out(key_vld_out)   ,                                 .state_c    (state_c    )                                 );     op_1    op_1_prj(                         .clk        (clk        )   ,                         .rst_n      (rst_n      )   ,                         .key_num    (key_num_out)   ,                         .key_vld    (key_vld_out)   ,                         .state_c    (state_c    )   ,                         .result     (result     )   ,                         .op_1       (op_1       )   ,                         .op_1_err   (op_1_err   )                     );     oper    oper_prj(                         .clk        (clk        )   ,                         .rst_n      (rst_n      )   ,                         .key_num    (key_num_out)   ,                         .key_vld    (key_vld_out)   ,                         .state_c    (state_c    )   ,                         .oper       (oper       )                     );         op_2    op_2_prj(                         .clk        (clk        )   ,                         .rst_n      (rst_n      )   ,                         .key_num    (key_num_out)   ,                         .key_vld    (key_vld_out)   ,                         .state_c    (state_c    )   ,                         .op_2       (op_2       )   ,                         .op_2_err   (op_2_err   )                     );     result  result_prj(                         .clk        (clk        )   ,                         .rst_n      (rst_n      )   ,                         .key_num    (key_num_out)   ,                         .key_vld    (key_vld_out)   ,                         .state_c    (state_c    )   ,                         .op_1       (op_1       )   ,                         .oper       (oper       )   ,                         .op_2       (op_2       )   ,                         .result     (result     )   ,                         .result_err (result_err )   ,                         .result_neg (result_neg )                     );     display_sel  display_sel_prj(                                 .clk        (clk        )   ,                                 .rst_n      (rst_n      )   ,                                 .state_c    (state_c    )   ,                                 .op_1       (op_1       )   ,                                 .op_2       (op_2       )   ,                                 .result_neg (result_neg )   ,                                 .display    (display    )   ,                                 .display_vld(display_vld)                                 );     segment  segment_prj(                             .rst_n      (rst_n      )   ,                             .clk        (clk        )   ,                             .display    (display    )   ,                             .display_vld(display_vld)   ,                             .seg_sel    (seg_sel    )   ,                             .segment    (segment    )                           );     beep    beep_prj(                         .clk        (clk        )   ,                         .rst_n      (rst_n      )   ,                         .op_1_err   (op_1_err   )   ,                         .op_2_err   (op_2_err   )   ,                         .result_err (result_err )   ,                         .beep       (beep       )                     ); endmodule



1.2 键盘扫描模块设计

1.2.1接口信号




1.2.2 设计思路

在前面的案例中已经有矩阵键盘的介绍,所以这里不在过多介绍,详细介绍请看下方链接:

;tid=310


1.2.3参考代码

always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         key_col_ff0 <= 4'b1111;         key_col_ff1 <= 4'b1111;     end     else begin         key_col_ff0 <= key_col    ;         key_col_ff1 <= key_col_ff0;     end end always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin         shake_cnt <= 0;     end     else if(add_shake_cnt) begin         if(end_shake_cnt)             shake_cnt <= 0;         else             shake_cnt <= shake_cnt+1 ;    end end assign add_shake_cnt = key_col_ff1!=4'hf; assign end_shake_cnt = add_shake_cnt  && shake_cnt == TIME_20MS-1 ; always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         state_c <= CHK_COL;     end     else begin         state_c <= state_n;     end end always  @(*)begin     case(state_c)         CHK_COL: begin                      if(col2row_start )begin                          state_n = CHK_ROW;                      end                      else begin                          state_n = CHK_COL;                      end                  end         CHK_ROW: begin                      if(row2del_start)begin                          state_n = DELAY;                      end                      else begin                          state_n = CHK_ROW;                      end                  end         DELAY :  begin                      if(del2wait_start)begin                          state_n = WAIT_END;                      end                      else begin                          state_n = DELAY;                      end                  end         WAIT_END: begin                      if(wait2col_start)begin                          state_n = CHK_COL;                      end                      else begin                          state_n = WAIT_END;                      end                   end        default: state_n = CHK_COL;     endcase end assign col2row_start = state_c==CHK_COL  && end_shake_cnt; assign row2del_start = state_c==CHK_ROW  && row_index==3 && end_row_cnt; assign del2wait_start= state_c==DELAY    && end_row_cnt; assign wait2col_start= state_c==WAIT_END && key_col_ff1==4'hf; always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         key_row <= 4'b0;     end     else if(state_c==CHK_ROW)begin         key_row <= ~(1'b1 << row_index);     end     else begin         key_row <= 4'b0;     end end always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin         row_index <= 0;     end     else if(add_row_index) begin         if(end_row_index)             row_index <= 0;         else             row_index <= row_index+1 ;    end    else if(state_c!=CHK_ROW)begin        row_index <= 0;    end end assign add_row_index = state_c==CHK_ROW && end_row_cnt; assign end_row_index = add_row_index  && row_index == 4-1 ; always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin         row_cnt <= 0;     end     else if(add_row_cnt) begin         if(end_row_cnt)             row_cnt <= 0;         else             row_cnt <= row_cnt+1 ;    end end assign add_row_cnt = state_c==CHK_ROW || state_c==DELAY; assign end_row_cnt = add_row_cnt  && row_cnt == 16-1 ; always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         key_col_get <= 0;     end     else if(state_c==CHK_COL && end_shake_cnt ) begin         if(key_col_ff1==4'b1110)             key_col_get <= 0;         else if(key_col_ff1==4'b1101)             key_col_get <= 1;         else if(key_col_ff1==4'b1011)             key_col_get <= 2;         else             key_col_get <= 3;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         key_out <= 0;     end     else if(state_c==CHK_ROW && end_row_cnt)begin         key_out <= {row_index,key_col_get};     end     else begin         key_out <= 0;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         key_vld <= 1'b0;     end     else if(state_c==CHK_ROW && end_row_cnt && key_col_ff1[key_col_get]==1'b0)begin         key_vld <= 1'b1;     end     else begin         key_vld <= 1'b0;     end end


1.3 工作状态选择模块设计

1.3.1接口信号



1.3.2设计思路

该模块的主要功能是根据按下的按键进行不同来判断和决定计算器的工作状态。一条等式可以写成:运算数1+操作符+运算数2+等号+结果的形式。考虑到结果错误的情况,我将本模块的状态划分为5个,分别是:输入运算数1(OP_1)、运算符(OPER)、输入运算数2(OP_2)、输出结果(RESULT)、结果错误(ERROR)。


下图为本模块的状态跳转图:



复位后,状态机进入OP_1状态,即初始状态为OP_1;


在OP_1状态下:

A. 按下等号,跳到RESULT状态;

B. 按下运算符,跳到OPER状态;

在OPER状态下:

A. 按下数字,跳到OP_2状态;

B. 按下等号,跳到RESULT状态;

在OP_2状态下:

A. 按下等号,跳到RESULT状态;

B. 按下运算符,跳到OPER状态;

在RESULT状态下:

A. 按下数字,跳到OP_1状态;

B. 按下运算符,跳到OPER状态;

C. 按下等号,停留在RESULT状态;

在ERROR状态下:

A. 按下数字,跳到OP_1状态;

B. 按下其他按键,停留在ERROR状态;

无论当前处于什么状态,只要检测到运算结果错误指示信号有效,即可跳转到ERROR状态。


1.3.3参考代码

使用GVIM,在命令模式下输入如下内容,即可生成本模块所需要的状态机代码。


使用明德扬的状态机模板,可以很快速的写出此模块代码。

always  @(*)begin     case(key_num)         4'd0   :key_num_chg = 4'd7   ;         4'd1   :key_num_chg = 4'd8   ;         4'd2   :key_num_chg = 4'd9   ;         4'd3   :key_num_chg = 4'd10  ;         4'd7   :key_num_chg = 4'd11  ;         4'd8   :key_num_chg = 4'd1   ;         4'd9   :key_num_chg = 4'd2   ;         4'd10  :key_num_chg = 4'd3   ;         4'd11  :key_num_chg = 4'd14  ;         4'd12  :key_num_chg = 4'd0   ;         4'd13  :key_num_chg = 4'd12  ;         4'd14  :key_num_chg = 4'd13  ;         default:key_num_chg = key_num;     endcase end assign  key_num_en = (key_num_chg==0 || key_num_chg==1 || key_num_chg==2 || key_num_chg==3 || key_num_chg==4 || key_num_chg==5 || key_num_chg==6 || key_num_chg==7 || key_num_chg==8 || key_num_chg==9) && key_vld==1; assign  key_op_en = (key_num_chg==10 || key_num_chg==11 || key_num_chg==12 || key_num_chg==13) && key_vld==1; assign  key_cal_en = key_num_chg==15 && key_vld==1; assign  key_back_en = key_num_chg==14 && key_vld==1; always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin         state_c <= OP_1 ;     end     else begin         state_c <= state_n;    end end always @(*) begin     if(result_err)begin        state_n = ERROR;    end    else begin        case(state_c)           OP_1 :begin             if(op_12oper_start)                 state_n = OPER ;             else if(op_12result_start)                 state_n = RESULT ;             else                 state_n = state_c ;         end         OPER :begin             if(oper2op_2_start)                 state_n = OP_2 ;             else if(oper2result_start)                 state_n = RESULT ;             else                 state_n = state_c ;         end         OP_2 :begin             if(op_22oper_start)                 state_n = OPER ;             else if(op_22result_start)                 state_n = RESULT ;             else                 state_n = state_c ;         end         RESULT :begin             if(result2op_1_start)                 state_n = OP_1 ;             else if(result2oper_start)                 state_n = OPER ;             else                 state_n = state_c ;         end         ERROR :begin             if(error2op_1_start)                 state_n = OP_1 ;             else                 state_n = state_c ;         end         default : state_n = OP_1 ;     endcase end end assign op_12oper_start   = state_c==OP_1   && key_op_en ; assign op_12result_start = state_c==OP_1   && key_cal_en; assign oper2op_2_start   = state_c==OPER   && key_num_en; assign oper2result_start = state_c==OPER   && key_cal_en; assign op_22oper_start   = state_c==OP_2   && key_op_en ; assign op_22result_start = state_c==OP_2   && key_cal_en; assign result2op_1_start = state_c==RESULT && key_num_en; assign result2oper_start = state_c==RESULT && key_op_en ; assign error2op_1_start  = state_c==ERROR  && key_num_en; always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         key_num_out <= 0;     end     else begin         key_num_out <= key_num_chg;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         key_vld_out <= 0;     end     else begin         key_vld_out <= key_vld;     end end


1.4 运算数1模块设计

1.4.1接口信号



1.4.2设计思路

该模块主要的作用是根据当前状态和输入的按键,来决定运算数1要输出的结果。由于本工程需要实现连续运算的功能,所以在这个模块中要区分是否已经得出了运算结果。


下面是计算完成指示信号flag_calc的设计思路:

1、 该信号为高时,表示完成一次计算过程得到了结果。初始状态为低电平;

2、 当输入操作数2后又按下了等号或者其他操作符的时候,变为高电平,所以变高的条件为(state_c_ff==OP_2 && state_c==OPER) || state_c==RESULT;

3、 当处在操作数1状态时,为低电平,所以变低的条件为state_c==OP_1。其他情况保持不变。


下面是运算数1输出信号op_1的设计思路:

1、 该信号表示运算数1要输出的值。初始状态为0;

2、 在结果错误状态的时候,给一个不超过范围的任意值,此代码中给的10;

3、 在得到计算结果或者计算结果错误的时候,输入数字,输出为按下按键的对应值(key_num_out);

4、 在输入操作数1之后,按下退格键,op_1输出的值除以10进行取整;

5、 在输入操作数1状态下通过键盘输入数字,需要判断是否超过显示范围,如果没有超过的话就需要将当前op_1的值乘以10,然后加上按下的数字的值,进行输出;

6、 当计算完成时,即flag_calc==1,操作数1输出计算的结果result;

7、 其他时候操作数1保持不变。


下面是运算数1溢出信号op_1_err的设计思路:

1、 初始状态为0,表示没有溢出。

2、 当一直处于操作数1状态,按下键盘输入数字之后,操作数1的值溢出了,则将运算数1溢出信号拉高。

3、 其他时刻保持为低电平。

assign  key_num_en = (key_num==0 || key_num==1 || key_num==2 || key_num==3 || key_num==4 || key_num==5 || key_num==6 || key_num==7 || key_num==8 || key_num==9) && key_vld==1; assign  key_op_en = (key_num==10 || key_num==11 || key_num==12 || key_num==13) && key_vld==1; assign  key_cal_en = key_num==15 && key_vld==1; assign  key_back_en = key_num==14 && key_vld==1; always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         state_c_ff <= 0;     end     else begin         state_c_ff <= state_c;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         op_2 <= 0;     end     else if(state_c==OPER)begin         op_2 <= 0;     end     else if(state_c_ff==OPER && state_c==OP_2)begin         op_2 <= key_num;     end     else if(state_c==OP_2 && key_back_en==1)begin         op_2 <= op_2 / 10;     end     else if(state_c==OP_2 && key_num_en==1)begin         op_2 <= (op_2>9999999) ? op_2 : (op_2*10+key_num);     end     else begin         op_2 <= op_2;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         op_2_err <= 0;     end     else if(state_c==OP_2 && key_num_en==1 && op_2>9999999)begin         op_2_err <= 1'b1;     end     else begin         op_2_err <= 1'b0;     end end endmodule

1.4.3参考代码
1.5 运算符模块设计

1.5.1接口信号




1.5.2设计思路

本模块的设计思路比较简单,只需要判断哪些按键是运算符,然后在这些运算符被按下的时候,将他们对应的值输出就可以了。

下面是运算符指示信号设计思路:

1、 当“加”“减”“乘”“除”四个按键的任意一个被按下之后,该信号置为高电平;

2、 当“加”“减”“乘”“除”四个按键没有一个被按下的时候,该信号置为低电平。

下面是运算符输出信号oper设计思路:

初始状态,该信号输出0;

1、 当处于操作数1状态时,输出0;

2、 当“加”“减”“乘”“除”任意按键被按下之后,输出该按键对应的值;

3、 其他时候保持不变;


1.5.3参考代码

assign  key_op_en = (key_num==10 || key_num==11 || key_num==12 || key_num==13) && key_vld==1; always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         oper <= 0;     end     else if(state_c==OP_1)begin         oper <= 0;     end     else if(key_op_en==1)begin         oper <= key_num;     end     else begin         oper <= oper;     end end


1.6 运算数2模块设计

1.6.1接口信号

信号 接口方向定义clk输入系统时钟rst_n输入低电平复位信号Key_num_out输入计算器按下位置输出信号,key_vld_out有效时,该信号有效。Key_vld_out输入计算器按键按下有效指示信号,高电平有效。State_c输入计算器工作状态指示信号Op_2输出运算数2输出信号Op_2_err输出运算数2溢出信号


1.6.2设计思路

该模块主要的作用是根据当前状态和输入的按键,来决定运算数2要输出的结果。

下面是运算数2输出信号op_2的设计思路:


1、 该信号表示运算数2要输出的值。初始状态为0;

2、 在运算符状态下,此时数码管不显示运算数2的值,让它输出0;

3、 输入运算符之后,之后再输入的就是运算数2的值,此时运算数2就等于按下按键所对应的数值。

4、 在输入运算数2之后,按下退格键,运算数2的值除以10进行取整;

5、 在输入运算数2状态下通过键盘输入数字,需要判断是否超过显示范围,如果没有超过的话就需要将当前运算数2的值乘以10,然后加上按下的数字的值,进行输出;

6、 其他时候运算数2保持不变。


下面是运算数2溢出信号op_2_err的设计思路:


1、 初始状态为0,表示没有溢出。

2、 当一直处于运算数2状态,按下键盘输入数字之后,运算数2的值溢出了,则将运算数2溢出信号拉高。

3、 其他时刻保持为低电平。


1.6.3参考代码

assign  key_num_en = (key_num==0 || key_num==1 || key_num==2 || key_num==3 || key_num==4 || key_num==5 || key_num==6 || key_num==7 || key_num==8 || key_num==9) && key_vld==1; assign  key_op_en = (key_num==10 || key_num==11 || key_num==12 || key_num==13) && key_vld==1; assign  key_cal_en = key_num==15 && key_vld==1; assign  key_back_en = key_num==14 && key_vld==1; always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         state_c_ff <= 0;     end     else begin         state_c_ff <= state_c;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         flag_calc <= 0;     end     else if(state_c==OP_1)begin         flag_calc <= 1'b0;     end     else if(state_c_ff==OP_2 && state_c==OPER || state_c==RESULT)begin         flag_calc <= 1'b1;     end     else begin         flag_calc <= flag_calc;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         op_1 <= 0;     end     else if(state_c==ERROR)begin         op_1 <= 10;     end     else if((state_c_ff==RESULT || state_c_ff==ERROR) && state_c==OP_1)begin         op_1 <= key_num;     end     else if(state_c==OP_1 && key_back_en==1)begin         op_1 <= op_1 / 10;     end     else if(state_c==OP_1 && key_num_en==1)begin         op_1 <= (op_1>9999999) ? op_1 : (op_1*10+key_num);     end     else if(flag_calc==1)begin         op_1 <= result;     end     else begin         op_1 <= op_1;     end end always  @(posedge clk or negedge rst_n)begin     if(rst_n==1'b0)begin         op_1_err <= 0;     end     else if(state_c==OP_1  && key_num_en==1 && op_1>9999999)begin         op_1_err <= 1'b1;     end     else begin         op_1_err <= 1'b0;     end end

由于篇幅限制,本文分为(一)(二)两篇;请接着学习(二)。

本案例提供教学视频和工程源代码,需要的同学请到明德扬论坛进行学习。







感兴趣的朋友也可以访问明德扬论坛()进行FPGA相关工程设计学习,也可以看一下我们往期的文章:


《基于FPGA的密码锁设计》

《波形相位频率可调DDS信号发生器》

《基于FPGA的曼彻斯特编码解码设计》

《基于FPGA的出租车计费系统》

《数电基础与Verilog设计》

《基于FPGA的频率、电压测量》

《基于FPGA的汉明码编码解码设计》

《关于锁存器问题的讨论》

《阻塞赋值与非阻塞赋值》

《参数例化时自动计算位宽的解决办法》


明德扬是一家专注于FPGA领域的专业性公司,公司主要业务包括开发板、教育培训、项目承接、人才服务等多个方向。点拨开发板——学习FPGA的入门之选。
MP801开发板——千兆网、ADDA、大容量SDRAM等,学习和项目需求一步到位。网络培训班——不管时间和空间,明德扬随时在你身边,助你快速学习FPGA。周末培训班——明天的你会感激现在的努力进取,升职加薪明德扬来助你。就业培训班——七大企业级项目实训,获得丰富的项目经验,高薪就业。专题课程——高手修炼课:提升设计能力;实用调试技巧课:提升定位和解决问题能力;FIFO架构设计课:助你快速成为架构设计师;时序约束、数字信号处理、PCIE、综合项目实践课等你来选。项目承接——承接企业FPGA研发项目。人才服务——提供人才推荐、人才代培、人才派遣等服务。

本文信息为网友自行发布旨在分享与大家阅读学习,文中的观点和立场与本站无关,如对文中内容有异议请联系处理。

本文链接:https://www.paituo.cc/ming/yx/1152462.html

  • 小编推荐

    修炼计算器 倩女幽魂手游修炼计算器…

    修炼计算器,倩女幽魂手游修炼计算器,梦幻西游修炼计算器相关介绍,学友小课堂 学无止境 1.喜欢你 999+9858763 999+9858786 68+9989 68+9989 2.纸短情长 1123323321 5535 56788888 767635 5685

    csol下载、csol下载完安装不了…

    csol下载,csol下载完安装不了,csol下载手机版相关介绍,7月17日,《反恐精英Online》将迎来暑期新版本。传奇级武器星际仲裁正式入驻密码箱,召唤星灵随你一同战斗,你们准备好了吗?精英悬赏第三季度正式开启,海量全新限定道具上线,让我们一起来好好了解一番吧

    『边锋网络游戏』边锋网络游戏世界百科…

    边锋网络游戏,边锋网络游戏世界百科,边锋网络游戏手机版相关介绍,7月12日,中国互联网协会、工业和信息化部信息中心在北京联合发布2016年“中国互联网企业100强”排行榜。阿里巴巴、腾讯、百度、京东、奇虎360、搜狐、网易、携程、唯品会、苏宁云商位列前十位。 榜单

    ‘雷神之锤2’雷神之锤游戏

    雷神之锤2,雷神之锤游戏,雷神之锤2武器相关介绍,早期苦大仇深的索尔并不是漫威英雄中非常受欢迎的一个。 后来的《雷神3》让索尔换了个欢乐沙雕的风格,一下就获得了粉丝的喜爱,《复联3》《复联4》更是加深了这种印象。 在Inverse的一场采访中,塑造前

    〈小苏达〉小苏达的化学名称??

    小苏达,小苏达的化学名称?,小苏达的功效与作用相关介绍,大家好,我是大磊,食用碱和小苏打,都是我们生活中经常见到的厨房用品,特别是做面食的时候一般都会用得到,但是也不能随便用,很多人到现在还没搞懂,看完真是涨知识了。 因为小苏打和食用碱,从外观上看着差不多

    美少女万华镜2下载—美少女万华镜2下载公众号?

    美少女万华镜2下载,美少女万华镜2下载公众号,美少女万华镜2下载安卓ons相关介绍,高人气Galgame系列《美少女万华镜》公布了最新作品《美少女万华镜:理と迷宮の少女》,系列核心画师八宝备仁也在官方推特上公开了本次作品的封面视觉图。本次视觉图已经剧透了新作的主角为贯穿系列的莲花,这

    (生化危机2修改器)生化危机2修改器报错

    生化危机2修改器,生化危机2修改器报错,野比大雄的生化危机2修改器相关介绍,《生化危机2:重制版》发售之后获得了玩家们的一致好评,很多人在体验过正经的游戏剧情和其它内容之后,就想着发掘一些别的有趣的内容。近日,国外玩家“Shesez”发布了一段视频,调节摄像机视角之后发现了另

    穿越火线客户端下载—穿越火线客户端下载好了怎么玩不了?

    穿越火线客户端下载,穿越火线客户端下载好了怎么玩不了,穿越火线客户端下载打不开相关介绍,CF手游在12月3日要开启不限号测试了,本次为大家带来CF手游下载地址,小伙伴们提取下载好安装包,在12月3日更新后,就可以体验了手机版CF带来的乐趣了。 下载地址: 【穿越火线-枪战王者】 《穿越火