本节摘要

这是本学期第三节高速EDA设计课程,本节课的主要内容是进行Verilog语言的入门了解学习及上手,并实地操作的去将常见的电路模块通过老师给出的模块代码实现并验证,并在这个过程中熟悉Verilog语法。
本篇博客中代码部分大部分来自于杜老师实验教学网站。实验教学-Verilog新手上路篇

Verilog使用步骤分析

  • 设计功能的需求分析:把需要完成的电路功能明确下来,定义出电路的顶层信号端口以及各个端口的时序。
  • 设计的模块分割:把顶层的模块切分成为若干个小型的模块,同样,定义出各个小型模块的端口和时序。
  • 实现各个子模块

实例化电路模块并互联

  • Verilog代码的重要功能之一是实例化电路模块,并且对这些模块进行布线连接
  • 每个被实例化的Verilog module 就如同某个型号的芯片, 每对该module的一次实例化,就如同使用了一次该芯片。
  • 同样,把各个实例化的module的信号连接起来,就如同在电路元件之间用导线进行互联一样。

多路选择器

根据教程中2选1选择器代码,实现4选1数据选择器,实现代码:

module lianxi(IN0       ,   // input 1IN1       ,   // input 2IN2       ,   // input 3IN3       ,   // input 4SEL1      ,   // select SEL2      ,  OUT       );  // out data
parameter WL = 16;      // 输入输出数据信号位宽
input [WL-1:0] IN0, IN1,IN2,IN3;// 选择器的两个输入数据信号
input SEL1,SEL2;              // 通道选通的控制信号
output[WL-1:0] OUT;     // 选择器的输入数据信号reg   [WL-1:0] OUT;
// 生成组合逻辑的代码
always @ (IN0 or IN1 or IN2 or IN3 or SEL1 or SEL2) beginif(SEL1&&SEL2) // SEL为1 选择输入1OUT = IN3;else if((SEL1==0)&&(SEL2==0))   // SEL为0 选择输入0OUT = IN0;else if((SEL1==0)&&(SEL2==1))OUT=  IN1;else if((SEL1==1)&&(SEL2==0))OUT=IN2;end
endmodule

交叉开关

在老师给出2×2的交叉开关代码的基础上,改动一下,写出4×4的交叉开关实现代码如下:

module lianxi3(IN0       ,   // input 1IN1       ,   // input 2IN2,IN3,SEL0      ,   // select the output0 source SEL1      ,   // select the output1 source SEL2,SEL3,OUT0      ,   // output data 0OUT1      );  // output data 1
parameter WL = 16;
input [WL-1:0] IN0, IN1,IN2,IN3;
input SEL0, SEL1,SEL2,SEL3;
output[WL-1:0] OUT0, OUT1;reg   [WL-1:0] OUT0, OUT1;
// get the OUT0
always @ (IN0 or IN1 or IN2 or IN3 or SEL0 or SEL1) begincase({SEL0,SEL1})2'b 00:OUT0=IN0;2'b 01:OUT0=IN1;2'b 10:OUT0=IN2;2'b 11:OUT0=IN3;endcase
end
// get the OUT1
always @ (IN0 or IN1 or IN2 or IN3 or SEL0 or SEL1) begincase({SEL2,SEL3})2'b 00:OUT1=IN0;2'b 01:OUT1=IN1;2'b 10:OUT1=IN2;2'b 11:OUT1=IN3;endcase
end
endmodule

8输入优先编码器

在给出4输入示例的基础上,写出8输入优先编码器实现代码:

module lianxi4(IN        ,   // input  OUT       );  // output
input [7:0] IN;
output[3:0] OUT;reg   [3:0] OUT;
always @ (IN) beginif(IN[7])                     //第一优先OUT = 4'b0111;          else if(IN[6])                //第二优先OUT = 4'b0110;else if(IN[5])              //第三优先OUT = 4'b0101;else if(IN[4])              //第四优先OUT = 4'b0100;else if(IN[3])              //第五优先OUT = 4'b0011;else if(IN[2])             //第六优先OUT = 4'b0010;else if(IN[1])            //第七优先OUT = 4'b0001;else if(IN[0])           //第八优先OUT = 4'b0000;elseOUT = 4'b1111;       //输出没有结果end
endmodule

多路译码器

在已给出3-8译码器的基础上,写出4-16译码器的实现代码:

module lianxi5(IN        ,   // input  OUT       );  // output input [3:0] IN;
output[15:0] OUT;reg   [15:0] OUT;
// get the OUT
always @ (IN) begincase(IN)4'b0000: OUT = 16'b0000_0000_0000_0001;4'b0001: OUT = 16'b0000_0000_0000_0010;4'b0010: OUT = 16'b0000_0000_0000_0100;4'b0011: OUT = 16'b0000_0000_0000_1000;4'b0100: OUT = 16'b0000_0000_0001_0000;4'b0101: OUT = 16'b0000_0000_0010_0000;4'b0110: OUT = 16'b0000_0000_0100_0000;4'b0111: OUT = 16'b0000_0000_1000_0000;4'b1000: OUT = 16'b0000_0001_0000_0000;4'b1001: OUT = 16'b0000_0010_0000_0000;4'b1010: OUT = 16'b0000_0100_0000_0000;4'b1011: OUT = 16'b0000_1000_0000_0000;4'b1100: OUT = 16'b0001_0000_0000_0000;4'b1101: OUT = 16'b0010_0000_0000_0000;4'b1110: OUT = 16'b0100_0000_0000_0000;4'b1111: OUT = 16'b1000_0000_0000_0000;//  full case 不需要写default,否则一定要有defaultendcase
end
endmodule

加法器

  1. 无符号加法器
module lianxi6(IN1   ,IN2   ,OUT   );
input[3:0] IN1, IN2;
output[4:0] OUT;
reg[4:0] OUT;
always@(IN1 or IN2) begin // 生成组合逻辑的always 块OUT = IN1 + IN2;
end
endmodule
  1. 补码加法器
module lianxi7(IN1   ,IN2   ,OUT   );
input signed [3:0] IN1, IN2;
output signed [4:0] OUT;
reg signed [4:0] OUT;
always@(IN1 or IN2) begin // 生成组合逻辑的always 块OUT = IN1 + IN2;
end
endmodule
  1. 带流水线的加法器
module lianxi8(IN1   ,IN2   ,CLK   ,OUT   );
input  [3:0] IN1, IN2;
input CLK;
output  [4:0] OUT;
reg [3:0] in1_d1R, in2_d1R;
reg  [4:0] adder_out, OUT;
always@(posedge CLK) begin // 生成D触发器的always块in1_d1R <= IN1;in2_d1R <= IN2;OUT     <= adder_out;
end
always@(in1_d1R or in2_d1R) begin // 生成组合逻辑的always 块adder_out = in1_d1R + in2_d1R;
end
endmodule

乘法器

  1. 无符号的乘法器
module lianxi9(IN1   ,IN2   ,OUT   );input [3:0] IN1, IN2;output [7:0] OUT;reg [7:0] OUT;
always@(IN1 or IN2) begin // 生成组合逻辑的always 块OUT = IN1 * IN2;
end
endmodule

2.有符号的2补码乘法器

module lianxi10(IN1   ,IN2   ,OUT   );input signed[3:0] IN1, IN2;output signed [7:0] OUT;reg signed[7:0] OUT;always@(IN1 or IN2) begin // 生成组合逻辑的always 块OUT = IN1 * IN2;
end
endmodule
  1. 8位乘法器
module lianxi11(IN1,IN2,OUT
);input signed [7 : 0] IN1, IN2;output signed [15 : 0] OUT;reg signed [15 : 0] OUT; always @ (IN1 or IN2) begin OUT = IN1 * IN2;end
endmodule

计数器

计数器是最为常用的时序电路之一,计数器在数字电路里面的作用,就如C程序中的for循环一样,实现代码如下所示:

module lianxi12(RST   , // 异步复位, 高有效CLK   , // 时钟,上升沿有效EN    , // 输入的计数使能,高有效CLR   , // 输入的清零信号,高有效LOAD  , // 输入的数据加载使能信号,高有效DATA  , // 输入的加载数据信号CNTVAL, // 输出的计数值信号OV    );// 计数溢出信号,计数值为最大值时该信号为1input RST   , CLK   , EN    , CLR   , LOAD  ;
input [3:0] DATA ;
output [3:0] CNTVAL;
output OV;   reg [3:0] CNTVAL, cnt_next;
reg OV;
// 电路编译参数,最大计数值
parameter CNT_MAX_VAL = 9;// 组合逻辑,生成cnt_next
// 计数使能最优先,清零第二优先,加载第三优先
always @(EN or CLR or LOAD or DATA or CNTVAL) beginif(EN) begin    // 使能有效if(CLR) begin // 清零有效cnt_next = 0;endelse begin  // 清零无效if(LOAD) begin // 加载有效cnt_next = DATA;endelse begin     // 加载无效,正常计数// 使能有效,清零和加载都无效,根据当前计数值计算下一值if(CNTVAL < CNT_MAX_VAL) begin // 未计数到最大值, 下一值加1cnt_next = CNTVAL + 1'b1;endelse begin // 计数到最大值,下一计数值为0cnt_next = 0;endend // else LOADend  // else CLRend // if ENelse begin  // 使能无效,计数值保持不动cnt_next = CNTVAL;end // else EN
end// 时序逻辑 更新下一时钟周期的计数值
// CNTVAL 会被编译为D触发器
always @ (posedge CLK or posedge RST) beginif(RST) CNTVAL <= 0;elseCNTVAL <= cnt_next;
end// 组合逻辑,生成OV
always @ (CNTVAL) beginif(CNTVAL == CNT_MAX_VAL) OV = 1;elseOV = 0;
endendmodule

状态机

  1. 有限状态机(Finite State Machine)同样是数字电路设计中非常常用的模块,其在EDA设计中的地位等同于C语言中的If-else语句。
module lianxi6(CLK       ,   // clockRST       ,   // resetCENT1IN   ,   // input 1 cent coinTINOUT    );  // output 1 tin colainput  CLK       ;
input  RST       ;
input  CENT1IN   ;
output TINOUT    ;parameter ST_0_CENT = 0;
parameter ST_1_CENT = 1;
parameter ST_2_CENT = 2;
parameter ST_3_CENT = 3;reg [2-1:0]stateR       ;
reg [2-1:0]next_state   ;
reg        TINOUT       ;// calc next state
always @ (CENT1IN or stateR) begincase (stateR)ST_0_CENT :begin if(CENT1IN) next_state = ST_1_CENT ; else next_state = ST_0_CENT; endST_1_CENT :begin if(CENT1IN) next_state = ST_2_CENT ; else next_state = ST_1_CENT; endST_2_CENT :begin if(CENT1IN) next_state = ST_3_CENT ; else next_state = ST_2_CENT; endST_3_CENT :begin next_state = ST_0_CENT; endendcase
end// calc output
always @ (stateR) beginif(stateR == ST_3_CENT) TINOUT = 1'b1;else TINOUT = 1'b0;
end// state DFF
always @ (posedge CLK or posedge RST)beginif(RST)stateR <= ST_0_CENT;elsestateR <= next_state;
endendmodule

状态机的状态转移图和表达式如下所示:

  1. 识别2进制序列“1011”的状态机
    根据已给出的状态机实现代码,完成2进制序列“1011”的状态机,实现代码如下所示:
module lianxi6(CLK,   // clockRST,   // resetCENT1IN,   // input 1 cent coinTINOUT, EN   );  // output 1 tin colainput  CLK;
input  RST, EN;
input  CENT1IN;
output TINOUT;parameter ST_0_CENT = 0;
parameter ST_1_CENT = 1;
parameter ST_2_CENT = 2;
parameter ST_3_CENT = 3;
parameter ST_4_CENT = 4;reg [3:0] stateR;
reg [3:0] next_state;
reg         TINOUT;always @ (CENT1IN or stateR) begincase (stateR)ST_0_CENT :begin if (CENT1IN  && EN)  next_state = ST_1_CENT ; else next_state = ST_0_CENT; endST_1_CENT :begin if ((CENT1IN == 0) && EN)  next_state = ST_2_CENT ; else next_state = ST_1_CENT; endST_2_CENT :begin if (CENT1IN  && EN)  next_state = ST_3_CENT ; else next_state = ST_0_CENT; endST_3_CENT :begin if (CENT1IN  && EN)  next_state = ST_4_CENT ; else next_state = ST_2_CENT; endST_4_CENT :begin if (CENT1IN  && EN)  next_state = ST_1_CENT ; else next_state = ST_2_CENT; enddefault next_state = ST_0_CENT;endcaseend// calc output
always @ (stateR)
beginif(stateR == ST_4_CENT)TINOUT = 1'b1;else TINOUT = 1'b0;
end// state DFF
always @ (posedge CLK or posedge RST)
beginif(RST)stateR <= ST_0_CENT;elsestateR <= next_state;
endendmodule

状态转换图和关系式如下所示:

移位寄存器

module top(RST   ,   // 异步复位, 高有效CLK   ,   // 时钟,上升沿有效EN    ,   // 输入数据串行移位使能IN    ,   // 输入串行数据OUT   );  // 并行输出数据input RST, CLK, EN;
input IN;
output[3:0] OUT;
reg [3:0] shift_R;assign OUT[3:0] = shift_R[3:0];
// 时序逻辑 根据输入使能进行串行移位
// shift_R 会被编译为D触发器
always @ (posedge CLK or posedge RST) beginif(RST) shift_R[3:0] <= 0;elseif(EN) begin // 串行移位的使能有效shift_R[3:1] <= shift_R[2:0];shift_R[0]   <= IN;endelse begin // 使能无效保持不动shift_R[3:0] <= shift_R[3:0];end
end // always
endmodule

双口RAM

module lianxi6(WE      ,   // write enableWCLK    ,   // write clockRCLK    ,   // read clock   WA      ,   // write addressRA      ,   // read addressWD      ,   // write dataRD      );  // read dataparameter DATAWL    = 8;
parameter ADDRWL    = 8;
parameter C2Q       = 2;input                    WE, WCLK, RCLK;
input   [ADDRWL -1:0]    WA, RA;
input   [DATAWL -1:0]    WD;
output  [DATAWL -1:0]    RD;dpram U0_dpram(.WE      (WE      ),   // write enable.WCLK    (WCLK    ),   // write clock.RCLK    (RCLK    ),   // read clock   .WA      (WA      ),   // write address.RA      (RA      ),   // read address.WD      (WD      ),   // write data.RD      (RD      ));  // read datadefparam U0_dpram.DATAWL    = DATAWL;
defparam U0_dpram.ADDRWL    = ADDRWL;
defparam U0_dpram.C2Q       = C2Q   ;endmodule
// endmodule topmodule dpram(WE      ,   // write enableWCLK    ,   // write clockRCLK    ,   // read clock   WA      ,   // write addressRA      ,   // read addressWD      ,   // write dataRD      );  // read data
// external set param
parameter DATAWL    = 0;
parameter ADDRWL    = 0;
parameter C2Q       = 0;input                    WE, WCLK, RCLK;input   [ADDRWL -1:0]    WA, RA; input   [DATAWL -1:0]    WD;output  [DATAWL -1:0]    RD;reg[DATAWL-1:0] RD;reg[DATAWL-1:0] mem [(1 << ADDRWL)-1:0];always @ (posedge WCLK) beginif(WE)mem[WA] <= #C2Q WD;endalways @ (posedge RCLK) beginRD  <= #C2Q mem[RA];end
// ######################################
// synopsys translate_off
// ######################################
// the code below this line will NOT take part into synthesis
// they are only needed by RTL simulation// task DumpDpRAM, get the content of RAM[addr]task DumpDpRAM; input     [ADDRWL-1  :0] addr    ;output    [DATAWL-1 :0]  content ;begincontent = mem[addr];end       // task beginendtask   // task DumpDpRAM// task RAMInit, initialize the RAM contenttask RAMInit;integer i;reg[DATAWL-1:0] initData;begininitData = 'hAAAA;// initData = (1 << DATAWL) - 1;for( i = 0; i < (1 << ADDRWL); i = i + 1)mem[i] = initData;endendtaskinitial beginRAMInit();$display("module dpram().RAMInit()called @ %0d", $time);end
// ######################################
// synopsys translate_on
// ######################################
// the code below this line will take part in synthesis
endmodule   // module dptbram()

ROM

module top(CLK   ,        // clockRA    ,        // read addressRD    );       // read data
input          CLK;
input  [6  :0] RA;
output [12 :0] RD;
reg    [12 :0] RD;
always @ (posedge CLK)case(RA)7 'd 0     : RD = #1 13'd 0     ; // 0x0      7 'd 1     : RD = #1 13'd 101   ; // 0x65     7 'd 2     : RD = #1 13'd 201   ; // 0xC9     7 'd 3     : RD = #1 13'd 301   ; // 0x12D    ... ... ...7 'd 123   : RD = #1 13'd 8176  ; // 0x1FF0   7 'd 124   : RD = #1 13'd 8181  ; // 0x1FF5   7 'd 125   : RD = #1 13'd 8185  ; // 0x1FF9   7 'd 126   : RD = #1 13'd 8189  ; // 0x1FFD   7 'd 127   : RD = #1 13'd 8190  ; // 0x1FFE   endcase
endmodule

总结

至此,本节课所有的实验任务基本都做完了,通过这节课的学习,我们通过理解复现老师给出的一些电路基础结构的Verilog代码,掌握了一些Verilog的基本语法,并能通过示例实现一些简单的变换。
实验时间:2019.10.20
报告时间:2019.11.5

高速EDA设计课程报告(二)相关推荐

  1. 基于C#+unity的3D平衡球游戏设计 课程报告+展示PPT+项目源码

    资源下载地址:https://download.csdn.net/download/sheziqiong/85705538 资源下载地址:https://download.csdn.net/downl ...

  2. 基于C#的自动生成视频和海报营销号助手软件设计 课程报告+展示PPT+项目源码

    目录 营销号"助手"软件 1 需求分析与概要设计 1 项目说明 1 1.1. 项目目标: 2 1.2. 软硬件环境需求 2 1.3. 使用的关键技术: 2 需求分析 3 2.1. ...

  3. 基于C#+unity的2D跑酷闯关对战冒险游戏设计 课程报告+答辩PPT+源码

    目录 项目说明 1 1.1. 项目目标 1 1.2. 软硬件环境需求 2 1.3. 使用的关键技术 2 需求分析 2 2.1. 系统用例 2 2.2. 业务流程 3 概要设计 4 3.1. 功能模块设 ...

  4. c语言做一个小程序报告,《C语言程序设计实践》课程报告30个小程序组合成一个大程序.doc...

    北方民族大学 课 程 报 告 课 程 名 称: 程序设计实践 专 业 班 级 : 软件工程(2)班 学 生 姓 名 : 李思良 学 号 : 任 课 教 师 : 王晓锋 学 期 : 2015-2016学 ...

  5. 商品管理系统c语言功能模板,C语言课程报告图书馆管理系统可做模板套用.doc

    课 程 报 告 课 程 名 称: 程序设计实践 专 业 班 级 : 学 生 姓 名 : 学 号 : 任 课 教 师 : 学 期 :2010-2011学年第二学期 课程报告任务书 题 目 图书信息管理系 ...

  6. 2019春第二次课程设计实验报告

    2019春第二次课程设计实验报告 一.实验项目名称: 贪吃蛇游戏编写: 二.实验项目功能描述: 这个实验主要是实现游戏的正常运行,实现的目标是对小蛇移动的控制, 同时对小蛇数据的保存,如何实现转弯的效 ...

  7. 20165219王彦博《基于Cortex-M4的虚拟机制作与测试》课程设计个人报告

    20165219王彦博<基于Cortex-M4的虚拟机制作与测试>课程设计个人报告 一.个人贡献 参与课设题目讨论及完成全过程: 资料收集: 负责环境搭建,代码运行下载: 撰写小组结题报告 ...

  8. 2109春第一次课程设计实验报告

    2019春第一次课程设计实验报告 一.实验项目名称: 飞机游戏的编写 二.实验项目功能描述: 这个实验主要是实现游戏的正常运行,实现控制飞机的移动功能,增加其实用度, 同时还实现发射子弹和出现敌机的操 ...

  9. 2019春第一次课程设计实验报告

    2019春第一次课程设计实验报告 一.实验项目名称 反弹球消砖块 二 .实验项目功能描述 用c语言编写一个反弹球小游戏,可以自己改变游戏的各项数据,可以通过键盘的 "a",&quo ...

  10. 2019 课程设计个人报告

    课程设计个人报告 20165310 徐雯 一.个人贡献 设计整体框架,整理所需实现功能 根据计划进行程序设计 实现程序设计所需代码,并进行调试 寻找实现功能过程中所需参考资料并进行学习 二.设计问题与 ...

最新文章

  1. iphone实现下拉列表(iOS开发 )
  2. Sklearn 损失函数如何应用到_15 分钟带你入门 sklearn 与机器学习(分类算法篇)...
  3. python自带的url提取器
  4. IT部门的服务工作方式、工作内容有了彻底的改变——安徽移动通信有限责任公司...
  5. boost::geometry::is_convex用法的测试程序
  6. windows安装python2
  7. ICCV 2021 oral 重构+预测,双管齐下提升视频异常检测性能
  8. 最长回文子串manacher算法模板
  9. 如果计算机正执行屏幕保护程序 当用户,计算机一级考试参考试题(含答案)讲节一.doc...
  10. 读react.js小书 01
  11. CDLINUX——minidwep-gtk
  12. 中英文数据库检索策略对比
  13. Data Masking安装和使用指南
  14. adb调试android设备
  15. python数据挖掘需要学的内容
  16. 家园系统服务器,梦幻西游手游家园系统外观全面升级
  17. 【比赛回顾】广工2020程序设计初赛C-秋夜hard
  18. 十个经典Android开源APP项目
  19. VMware 黑苹果开机失败 磁盘修复
  20. Linux下*.tar.gz文件解压缩命令

热门文章

  1. 移动边缘计算(MEC)
  2. php怎么设置div圆角,不用图片的DIV圆角(兼容各浏览器)
  3. 项目经理(甲方)推行ERP,需要做些什么?
  4. Java核心编程总结(九、File文件类),王道训练营Java百度云盘
  5. 深鸿会深大小组学习笔记:第一周,从零开发鸿蒙小游戏2048app(上)
  6. webservice接口开发学习笔记(一)
  7. cad布局怎么用_【CAD】CAD布局怎么用?
  8. 虚拟机以及Linux CentOS 7安装
  9. Hololens Holographic Remoting
  10. 利用 pyspider 框架抓取猫途鹰酒店信息