博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简单ALU(算术逻辑单元)的verilog实现
阅读量:6682 次
发布时间:2019-06-25

本文共 4385 字,大约阅读时间需要 14 分钟。

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     end103 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     // Outputs10     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 begin24         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     end41     42     always #(CLK_PERIOD/2) clk = ~clk;43     44     always@(posedge clk)45     if(!rst_n)46         begin47             oper_data[15:8] = 0;48             oper_data[7:0] = 0;49         end50     else51         begin52             oper_data[15:8] = oper_data[15:8] + 1;53             oper_data[7:0] = oper_data[7:0] + 1;54         end55       56 endmodule

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

综合RTL图:

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

 

 

转载地址:http://jbxao.baihongyu.com/

你可能感兴趣的文章
ORACLE expdp导出远程库指定用户数据到本地数据库
查看>>
Oracle10g RAC 单独关闭一个节点(维护)
查看>>
CentOS7怎么保存退出vi编辑
查看>>
上海一日游记
查看>>
ArchLinux上卸载高版本的jdk安装低版本的jdk
查看>>
进程间通信
查看>>
CIO需要消除八个大数据神话
查看>>
分布式系统之CAP理论
查看>>
注释方式汇总
查看>>
突破吞吐限制,多NAS性能聚合方案,数据上传及读写
查看>>
Flume 1.5.0简单部署试用
查看>>
lastlog
查看>>
计算机专业常用英语
查看>>
HBase源码分析之Region上Spilt流程
查看>>
青年之锋——文学之家
查看>>
不管你信不信 大数据正在遭遇尴尬!
查看>>
Android 反编译[持续更新]
查看>>
130行代码写一个模板引擎
查看>>
计算机编码
查看>>
Redis应用-位图
查看>>