zoukankan      html  css  js  c++  java
  • 简单ALU(算术逻辑单元)的verilog实现

    2013-06-14 21:39:56

    简单ALU(算术逻辑单元)的verilog实现,可实现两数相加、相减,或一个数的加1、减1操作。

    小结:

    • 要学会看RTL图,能够根据RTL图大致判断功能的正确性

    代码:

      1 module alu_add_sub(
      2                         rst_n,
      3                         clk,
      4                         oper_cmd,
      5                         oper_data,
      6                         dout
      7                              );
      8                              
      9 parameter DATA_SIZE = 4'd8;    //操作数宽度                         
     10 
     11 input rst_n;
     12 input clk;
     13 
     14 input [1:0] oper_cmd;
     15 input [2*DATA_SIZE - 1:0] oper_data;
     16 
     17 output [DATA_SIZE:0] dout;
     18 
     19 reg [1:0] oper_cmd_r;
     20 reg [2*DATA_SIZE - 1:0] oper_data_r;
     21 
     22 wire  [2*DATA_SIZE:0] add_sub_oper;
     23 
     24 reg [DATA_SIZE:0] dout_tmp;
     25 reg [DATA_SIZE:0] dout;
     26 
     27 //输入数据打一拍
     28 always@(posedge clk)
     29     if(!rst_n)
     30         begin
     31             oper_cmd_r <= 8'd0;
     32             oper_data_r <= 16'd0;
     33         end
     34     else
     35         begin
     36             oper_cmd_r <= oper_cmd;
     37             oper_data_r <= oper_data;
     38         end    
     39 
     40 //根据输入数据,求操作码,相当于指令译码
     41 assign add_sub_oper = add_sub_func(oper_cmd_r,oper_data_r);
     42 
     43 //根据译码结果,求输出
     44 always@(posedge clk)
     45 if(!rst_n)
     46     begin
     47         dout_tmp <= 9'd0;
     48     end
     49 else
     50     begin
     51         if(add_sub_oper[2*DATA_SIZE])
     52             dout_tmp <= add_sub_oper[2*DATA_SIZE-1 : DATA_SIZE] + add_sub_oper[DATA_SIZE-1 : 0];
     53         else
     54             dout_tmp <= add_sub_oper[2*DATA_SIZE-1 : DATA_SIZE] - add_sub_oper[DATA_SIZE-1 : 0];
     55     end
     56 
     57 //输出数据打一拍
     58 always@(posedge clk)
     59     if(!rst_n)
     60             dout <= 9'd0;
     61     else
     62         dout <= dout_tmp;
     63 
     64 //指令译码函数
     65 function [2*DATA_SIZE:0] add_sub_func;  //关键字function标志函数开始
     66     input [1:0] oper_cmd;
     67     input [2*DATA_SIZE - 1:0] oper_data;
     68 
     69     reg [1:0] mode;
     70     reg [DATA_SIZE - 1:0] oper1;
     71     reg [DATA_SIZE - 1:0] oper2;
     72 
     73     //always@(oper_cmd or oper_data)
     74     begin     //函数体须在过程块中
     75         case(oper_cmd)
     76             2'b00 :         //两数相加
     77                 begin
     78                     mode = 1;
     79                     oper1 = oper_data[2*DATA_SIZE - 1:DATA_SIZE];
     80                     oper2 = oper_data[DATA_SIZE - 1:0];
     81                 end
     82             2'b01 :     //加1
     83                 begin
     84                     mode = 1;
     85                     oper1 = oper_data[2*DATA_SIZE - 1:DATA_SIZE];
     86                     oper2 = 1'b1;
     87                 end
     88             2'b10 :         //两数相减
     89                 begin
     90                     mode = 0;
     91                     oper1 = oper_data[2*DATA_SIZE - 1:DATA_SIZE];
     92                     oper2 = oper_data[DATA_SIZE - 1:0];
     93                 end
     94             default :     //减1
     95                 begin
     96                     mode = 0;
     97                     oper1 = oper_data[2*DATA_SIZE - 1:DATA_SIZE];
     98                     oper2 = 1'b1;
     99                 end    
    100         endcase    
    101         add_sub_func = {mode,oper1,oper2};
    102     end
    103 
    104 endfunction  //关键字endfunction标志函数结束
    105 
    106 endmodule

    testbench:

     1 module alu_add_sub_tb;
     2 
     3     // Inputs
     4     reg rst_n;
     5     reg clk;
     6     reg [1:0] oper_cmd;
     7     reg [15:0] oper_data;
     8 
     9     // Outputs
    10     wire [8:0] dout;
    11 
    12     // Instantiate the Unit Under Test (UUT)
    13     alu_add_sub uut (
    14         .rst_n(rst_n), 
    15         .clk(clk), 
    16         .oper_cmd(oper_cmd), 
    17         .oper_data(oper_data), 
    18         .dout(dout)
    19     );
    20     
    21     parameter CLK_PERIOD = 10;
    22 
    23     initial begin
    24         rst_n = 0;
    25         clk = 1;
    26         oper_cmd = 0;
    27         //oper_data = 0;
    28 
    29         #100;
    30         rst_n = 1;
    31         
    32         # (10*CLK_PERIOD) oper_cmd = 2'b00;  //两数相加测试
    33         
    34         # (10*CLK_PERIOD) oper_cmd = 2'b01;     //加1测试
    35         
    36         # (10*CLK_PERIOD) oper_cmd = 2'b10;     //两数相减测试
    37         
    38             # (10*CLK_PERIOD) oper_cmd = 2'b11;    //减1测试
    39  
    40     end
    41     
    42     always #(CLK_PERIOD/2) clk = ~clk;
    43     
    44     always@(posedge clk)
    45     if(!rst_n)
    46         begin
    47             oper_data[15:8] = 0;
    48             oper_data[7:0] = 0;
    49         end
    50     else
    51         begin
    52             oper_data[15:8] = oper_data[15:8] + 1;
    53             oper_data[7:0] = oper_data[7:0] + 1;
    54         end
    55       
    56 endmodule

    分析仿真结果,代码满足所需功能。

    综合RTL图:

    (xilinx的RTL图很底层,不太容易看懂)

  • 相关阅读:
    Flutter 布局类组件:简介
    Flutter 基础组件:进度指示器
    Flutter 基础组件:单选框和复选框
    Flutter 基础组件:图片和Icon
    Flutter 基础组件:按钮
    Flutter 基础组件:文本、字体样式
    Flutter 基础组件:状态管理
    Flutter 基础组件:Widget简介
    网络编程之TCP
    入门多线程
  • 原文地址:https://www.cnblogs.com/youngforever/p/3136800.html
Copyright © 2011-2022 走看看