verilogHDL精粹.doc_第1页
verilogHDL精粹.doc_第2页
verilogHDL精粹.doc_第3页
verilogHDL精粹.doc_第4页
verilogHDL精粹.doc_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

verilogHDL精粹 2006-12-12 20:01:00 | By: 夏虫 0推荐针对C语言编程者的Verilog开发指南实例本文举例说明了如何用软件实现脉宽调制(PWM),如何将该设计转换成一个可以在FPGA中运行的逻辑块,并能利用存储器映射I/O接口通过软件完成对该逻辑块的控制。通过理解本文讨论的概念和内容,没有太多硬件知识的软件开发人员也能掌握在FPGA上开发硬件的技能。 在不远的将来,嵌入式系统设计师将能够根据哪个更有利于解决设计问题来自由选择硬件和软件方案。但直到现在,对于那些想学习硬件设计的软件工程师来说不少障碍仍然很难逾越。由于硬件描述语言和编程语言非常相似,因此最终这些障碍会消失。另外,市场上已有好几种低成本的演示板,上面包含现场可编程门阵列(FPGA)、微处理器以及相应工具,软件开发人员可以借此来学习硬件设计。 本文举例说明了一个使用FPGA的新设计流程,我们从中可以知道如何用软件实现PWM,然后如何将该设计转换成一个可以在FPGA中运行的逻辑块,并能利用存储器映射I/O接口通过软件完成对该逻辑块的控制。 软硬件划分 现在的情况与以前有所不同,软件工程师能够方便地参与到硬件设计中。不管是硬件模块还是软件模块现在都可以用编程语言进行设计。众所周知,C语言是嵌入式软件设计的通用语言。在硬件设计方面,Verilog则是流行的选择(用VHDL的人也很多)。Verilog的语法和结构与C编程语言非常相似,从本文的例子中也可以看到这一点。 同时,硬件的升级和修改也变得越来越方便。以前可以通过下载新的可执行映像文件升级软件,但对硬件却行不通。现在情况不同了。就像软件开发人员能够快速编辑、重新编译、然后将新代码下载到存储器那样,使用可编程逻辑器件的硬件设计者也能做类似的事情。可编程逻辑改变了嵌入式系统的设计方法,设计者可以像修改软件那样方便地修改硬件。换句话说,在设计和调试阶段,设计者能够灵活选择软件方式或硬件方式来作为完成任务的最佳方式。 设计者无需太多的硬件知识就可以利用FPGA供应商提供的工具轻松地开发出可编程逻辑嵌入式系统。例如,Altera公司的SOPC Builder能帮助系统设计师从已有的库中选择和配置外围电路,并增加用来创建和连接外围电路的用户逻辑。加上一些可编程逻辑和硬件知识,软件工程师就能够充分利用硬件的优势改进他们的系统。 PWM软件 PWM控制器会产生一连串脉冲。通常需要规定脉冲的周期和宽度。占空比被定义为脉冲宽度与周期的比值。PWM有着广泛的应用,大多数情况下用于控制模拟电路。因为数字信号连续变化的速率相对较快(当然取决于信号周期),因此最终会形成一个用来控制模拟设备的平均电压值。当PWM脉冲流应用于马达时,马达的转速就能正比于占空比(从0%到100%)。如果占空比增加,马达转速就会提高,反之,如果占空比减小,马达的转速随之也会降低。 用软件编写这样一个PWM控制器是相对比较容易的任务,但它有助于我们简明扼要地描述如何用Verilog设计硬件。清单1给出了PWM的C代码。 清单1:完全用软件实现的位脉冲PWM控制器。 void pwmTask(uint32_t pulse_width, uint32_t period) uint32_t time_on=pulse_width; uint32_t time_off=period-pulse_width; while (1) pwm_output=1; sleep(time_on); pwm_output=0; sleep(time_off); 根据脉宽(pulse_width)和周期(period)参数值,计算出输出为高电平和低电平的时间。接下来将输出引脚置为高电平,并等待time_on设定的时间值之后,将输出变为低电平,并等待time_off参数设定的时间值。下个周期再重复这样的过程,并无限循环下去。 Verilog模块 清单2给出了一个简单的Verilog模块,实现带异步复位功能的8位宽寄存器。寄存器的输入“in”在时钟的上升沿被赋值到输出“out”,直到clr_n复位信号的下降沿到来(此时输出将被赋值为0)。 清单2:实现带异步复位功能8位宽寄存器的Verilog编写模块。 module simple_register(in, out, clr_n, clk, a); /端口声明 input input input 7:0 input output 7:0 clr_n; clk; in; a; out; /信号声明 reg 7:0 wire out; a; /实现带异步清除的寄存器 always (posedge clk or negedge clr_n) begin if (clr_n=0) / could also be written if (!clr_n) out=0; else out=in; end /连续赋值 assign a=!out0; endmodule 粗略地看Verilog与C语言有许多相似之处。分号用于结束每个语句,注释符也是相同的(/* . */和/ 都是熟悉的),运算符“”也用来测试相等性。Verilog的if.then.else语法与C语言的也非常相似,只是Verilog用关键字begin和end代替了C的大括号。事实上,关键字begin和end对于单语句块来说是可有可无的,就与C中的大括号用法一样。Verilog和C都对大小写敏感。 当然,硬件和软件的一个重要区别是它们的“运行”方式。硬件设计中用到的许多单元都是并行工作的。一旦设备电源开启,硬件的每个单元就会一直处于运行状态。虽然根据具体的控制逻辑和数据输入,设备的一些单元可能不会改变它们的输出信号,但它们还是一直在“运行”中。 相反,在同一时刻整个软件设计中只有一小部分(即使是多软件任务也只有一个任务)在执行。如果只有一个处理器,同一时间点只能有一条指令在执行。软件的其它部分可以被认为处于休眠状态,这与硬件有很大的不同。变量可能以一个有效值而存在,但大多数时间里它们都不在使用状态。 软硬件的不同行为会直接导致硬件和软件代码编程方式的不同。软件是串行执行的,每一行代码的执行都要等到前一行代码执行完毕后才能进行(中断的非线性或操作系统的命令除外)。 /-一个Verilog模块的开头是关键字module,紧跟其后的是模块名称和端口列表,端口列表列出了该模块用到的所有输入输出名称。接下来是端口声明部分。注意:所有的输入输出既出现在模块第一行的端口列表中,也会出现在端口声明(declaration)部分中。 在Verilog中有二种类型的内部信号用得比较多,它们是reg和wire。它们具有不同的功能。所有端口都有一个名称相同且声明为wire的信号。因此连线line被声明为wire不是必要的。reg会保持上次的赋值,因此不需要每次都进行驱动。wire型信号用于异步逻辑,有时也用来连接信号。因为reg可以保持上次的值,因此输入不能被声明为reg类型。在Verilog模块中可以在任何时候异步地将输入改变为任何事件。reg和wire的主要区别是,reg类型的信号只能在过程块(后面会谈到)中赋值,而wire类型的信号只能在过程块外赋值。这两种信号类型都可以出现在过程块内部和外部的赋值运算符右边。 使用关键字reg并不一定意味着编译器会创建一个寄存器,理解这一点是非常重要的。清单2的代码中有一个reg类型8位宽的内部信号out。该模块使用寄存器源于always模块(过程块的一种)的编程方式。值得注意的是,信号a是一个wire类型,因此只能在连续赋值(continuous assignment)语句中赋值,而reg类型的out信号只能在always块中赋值。 always块是过程块的一种,仅在某种变化发生时用于更新信号。always语句圆括号里的表达式组被称为敏感列表,格式是:(表达式or表达式) 只要敏感列表中的任何一个表达式值为真,always块中的代码就会被执行。Verilog中用于上升沿和下降沿的关键字分别是posedge和negedge。这二个关键字经常被用于敏感列表。在本例中,如果clk信号的上升沿或clr_n的下降沿信号发生时,always块内部的语句就会被执行。 为了用好寄存器,输出必须在时钟的上升沿得到更新(下降沿也可以,但上升沿更常见些)。增加negedge clr_n会使寄存器在clr_n信号的下降沿复位。但并不是所有的敏感列表都会包含关键字posedge或negedge,因此在实际硬件中并不总是存在真实的寄存器。 always块内的第一条语句判断clr_n信号的上升沿有没有发生。如果有,下一行代码把out置为0。这些代码行实现了寄存器的异步复位功能。如果条件语句是:if(negedge clr_n and clk=1),那么该语句实现的就是基于时钟的异步复位。 读者可能已经注意到,always块中的赋值运算符与以关键字assign开头的连续赋值语句中用到的运算符不一样。=运算符用于非阻塞性(nonblocking)赋值,而运算符用于阻塞性(blocking)赋值。 在一组阻塞性赋值语句中,在下一个阻塞性赋值语句执行前需要计算并赋值第一个赋值语句。这一过程就象C语言中语句的顺序执行。而非阻塞语句在执行时,所有赋值语句的右边被同时计算和赋值。连续赋值语句必须使用阻塞赋值语句(否则编译器会报错)。 为了减少代码出错的概率,建议在顺序逻辑(例如希望以寄存器方式实现的逻辑)always块中的所有赋值语句使用非阻塞性赋值语句。大多数always块应该使用非阻塞性赋值语句。如果always块都是组合逻辑,那么就需要使用阻塞性赋值语句。 /-PWM硬件 编写存储器映射硬件模块的首要任务是以软件方式决定寄存器映射图。在PWM案例中,一般设计师希望能用软件设置周期和脉宽。在硬件设计中用计数器统计系统时钟周期数是非常容易的。因此要用到两个寄存器,分别命名为pulse_width和period,并且都在时钟周期内度量。表1给出了PWM的寄存器映射图。 为了确定输出信号,硬件可简单地通过将period和pulse_width寄存器内容作为运行中的计数器保持的输出。 接下来要为PWM选择端口,大多数端口可以依据总线架构而定。表2提供了通用存储器映射PWM的信号描述概要。通常为低电平有效的信号命名做法是在信号名上加“_n”,对于控制信号更是如此。表2中的write_n和clr_n信号就是低电平有效的信号(下降沿触发)。 至此我们已经定义好了硬件模块的接口,接下来就可以开始编写Verilog代码了。清单3给出了一个实现例子。 清单3:用Verilog实现的PWM硬件。 module pwm (clk, write_data, cs, write_n, addr, clr_n, read_data, pwm_out); input input 31:0 input input input input output 31:0 output clk; write_data; cs; write_n; addr; clr_n; read_data; pwm_out; reg 31:0 reg 31:0 reg 31:0 reg reg 31:0 wire period; pulse_width; counter; off; read_data; period_en, pulse_width_en; /写使能 / 定义period和pulse_width寄存器的内容 always (posedge clk or negedge clr_n) begin if (clr_n=0) begin period=32h 00000000; pulse_width=32h 00000000; end else begin if (period_en) period=write_data31:0; else period=period; if (pulse_width_en) pulse_width=write_data31:0; else pulse_width=pulse_width; end end / period和pulse_width寄存器的读访问 always (addr or period or pulse_width) if (addr = 0) read_data=period; else read_data=pulse_width; always (posedge clk or negedge clr_n) begin if (clr_n=0) counter=period-1) counter=0; else counter=counter+1; end always (posedge clk or negedge clr_n) begin if (clr_n=0) off=pulse_width) off = 1; else if (counter=0) off=0; else offperiod写入数据会设置或改变period值,向pLED-pulse_width写入数据将改变占空比,并导致LED的亮度增加或减少。如果使用的是闪烁型LED,只需把周期变长,让肉眼清晰辨别开和关的周期即可。 清单3所示的Verilog PWM实现在本例中是作为Altera的Nios处理器系统的外围电路进行测试的,可以利用前文所述的C结构通过软件对它访问。Altera的SOPC Builder创建了宏,可以使ModelSim(明导资讯公司的一个硬件仿真器)中的协同仿真。在系统执行C代码时可以利用ModelSim仿真器观察到PWM信号以及其它系统信号的行为。 清单4给出了用于产生图1所示PWM波形的C代码。C代码向PWM寄存器写入数据,创建出周期为5个时钟周期、脉宽为4个时

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论