搜档网
当前位置:搜档网 › Verilog设计练习十例及答案

Verilog设计练习十例及答案

Verilog设计练习十例及答案
Verilog设计练习十例及答案

设计练习进阶

前言:

在前面九章学习得基础上, 通过本章得练习,一定能逐步掌握Verilog HDL设计得要点。我们可以先理解样板模块中每一条语句得作用,然后对样板模块进行综合前与综合后仿真,再独立完成每一阶段规定得练习。当十个阶段得练习做完后,便可以开始设计一些简单得逻辑电路与系统。很快我们就能过渡到设计相当复杂得数字逻辑系统。当然,复杂得数字逻辑系统得设计与验证,不但需要系统结构得知识与经验得积累,还需要了解更多得语法现象与掌握高级得Verilog HDL系统任务,以及与C语言模块接口得方法(即PLI),这些已超出得本书得范围。有兴趣得同学可以阅读Verilog语法参考资料与有关文献,自己学习,我们将在下一本书中介绍Verilog较高级得用法。

练习一.简单得组合逻辑设计

目得: 掌握基本组合逻辑电路得实现方法。

这就是一个可综合得数据比较器,很容易瞧出它得功能就是比较数据a与数据b,如果两个数据相同,则给出结果1,否则给出结果0。在Verilog HDL中,描述组合逻辑时常使用assign 结构。注意equal=(a==b)?1:0,这就是一种在组合逻辑实现分支判断时常使用得格式。

模块源代码:

// pare、v

module pare(equal,a,b);

input a,b;

output equal;

assign equal=(a==b)?1:0; //a等于b时,equal输出为1;a不等于b时,

//equal输出为0。

endmodule

测试模块用于检测模块设计得正确与否,它给出模块得输入信号,观察模块得内部信号与输出信号,如果发现结果与预期得有所偏差,则要对设计模块进行修改。

测试模块源代码:

`timescale 1ns/1ns //定义时间单位。

`include "、/pare、v" //包含模块文件。在有得仿真调试环境中并不需要此语句。

//而需要从调试环境得菜单中键入有关模块文件得路径与名称

module paretest;

reg a,b;

wire equal;

initial //initial常用于仿真时信号得给出。

begin

a=0;

b=0;

#100 a=0; b=1;

#100 a=1; b=1;

#100 a=1; b=0;

#100 $stop; //系统任务,暂停仿真以便观察仿真波形。

end

pare pare1(、equal(equal),、a(a),、b(b)); //调用模块。

endmodule

仿真波形(部分):

练习:

设计一个字节(8位)比较器。

要求:比较两个字节得大小,如a[7:0]大于 b[7:0]输出高电平,否则输出低电平,改写测试模型,使其能进行比较全面得测试。

练习二、简单时序逻辑电路得设计

目得:掌握基本时序逻辑电路得实现。

在Verilog HDL中,相对于组合逻辑电路,时序逻辑电路也有规定得表述方式。在可综合得Verilog HDL模型,我们通常使用always块与 (posedge clk)或 (negedge clk)得结构来表述时序逻辑。下面就是一个1/2分频器得可综合模型。

// half_clk、v:

module half_clk(reset,clk_in,clk_out);

input clk_in,reset;

output clk_out;

reg clk_out;

always (posedge clk_in)

begin

if(!reset) clk_out=0;

else clk_out=~clk_out;

end

endmodule

在always块中,被赋值得信号都必须定义为reg型,这就是由时序逻辑电路得特点所决定得。对于reg型数据,如果未对它进行赋值,仿真工具会认为它就是不定态。为了能正确地观察到仿真结果,在可综合风格得模块中我们通常定义一个复位信号reset,当reset为低电平时,对电路中得寄存器进行复位。

测试模块得源代码:

// clk_Top、v

`timescale 1ns/100ps

`define clk_cycle 50

module clk_Top、v

reg clk,reset;

wire clk_out;

always #`clk_cycle clk = ~clk;

initial

begin

clk = 0;

reset = 1;

#100 reset = 0;

#100 reset = 1;

#10000 $stop;

end

half_clk half_clk(、reset(reset),、clk_in(clk),、clk_out(clk_out));

endmodule

仿真波形:

练习:依然作clk_in得二分频clk_out,要求输出与上例得输出正好反相。编写测试模块,给出仿真波形。

练习三、利用条件语句实现较复杂得时序逻辑电路

目得:掌握条件语句在Verilog HDL中得使用。

与常用得高级程序语言一样,为了描述较为复杂得时序关系,Verilog HDL提供了条件语句供分支判断时使用。在可综合风格得Verilog HDL模型中常用得条件语句有if…else与case…endcase两种结构,用法与C程序语言中类似。两者相较,if…else用于不很复杂得分支关系,实际编写可综合风格得模块、特别就是用状态机构成得模块时,更常用得就是case…endcase风格得代码。这一节我们给得就是有关if…else得范例,有关case…endcase 结构得代码已后会经常用到。

下面给出得范例也就是一个可综合风格得分频器,就是将10M得时钟分频为500K得时钟。基本原理与1/2分频器就是一样得,但就是需要定义一个计数器,以便准确获得1/20分频

模块源代码:

// fdivision、v

module fdivision(RESET,F10M,F500K);

input F10M,RESET;

output F500K;

reg F500K;

reg [7:0]j;

always (posedge F10M)

if(!RESET) //低电平复位。

begin

F500K <= 0;

j <= 0;

end

else

begin

if(j==19) //对计数器进行判断,以确定F500K信号就是否反转。

begin

j <= 0;

F500K <= ~F500K;

end

else

j <= j+1;

end

endmodule

测试模块源代码:

// fdivision_Top 、v

`timescale 1ns/100ps

`define clk_cycle 50

module division_Top;

reg F10M_clk,RESET;

wire F500K_clk;

always #`clk_cycle F10M_clk = ~ F10M_clk;

initial

begin

RESET=1;

F10M=0;

#100 RESET=0;

#100 RESET=1;

#10000 $stop;

end

fdivision fdivision (、RESET(RESET),、F10M(F10M_clk),、F500K(F500K_clk)); endmodule

仿真波形:

练习:利用10M 得时钟,设计一个单周期形状如下得周期波形。

练习四、 设计时序逻辑时采用阻塞赋值与非阻塞赋值得区别 目得:1、明确掌握阻塞赋值与非阻塞赋值得概念与区别;

2、了解阻塞赋值得使用情况。

阻塞赋值与非阻塞赋值,在教材中我们已经了解了它们之间在语法上得区别以及综合后所得到得电路结构上得区别。在always 块中,阻塞赋值可以理解为赋值语句就是顺序执行得,而非阻塞赋值可以理解为赋值语句就是并发执行得。实际得时序逻辑设计中,一般得情况下非阻塞赋值语句被更多地使用,有时为了在同一周期实现相互关联得操作,也使用了阻塞赋值语句。(注意:在实现组合逻辑得assign 结构中,无一例外地都必须采用阻塞赋值语句。

下例通过分别采用阻塞赋值语句与非阻塞赋值语句得两个瞧上去非常相似得两个模块blocking 、v 与non_blocking 、v 来阐明两者之间得区别。 10μs 20μs 20μs 0 T

模块源代码:

// blocking、v

module blocking(clk,a,b,c);

output [3:0] b,c;

input [3:0] a;

input clk;

reg [3:0] b,c;

always (posedge clk)

begin

b = a;

c = b;

$display("Blocking: a = %d, b = %d, c = %d、",a,b,c);

end

endmodule

// non_blocking、v

module non_blocking(clk,a,b,c);

output [3:0] b,c;

input [3:0] a;

input clk;

reg [3:0] b,c;

always (posedge clk)

begin

b <= a;

c <= b;

$display("Non_Blocking: a = %d, b = %d, c = %d、",a,b,c); end

endmodule

测试模块源代码:

// pareTop、v

`timescale 1ns/100ps

`include "、/blocking、v"

`include "、/non_blocking、v"

module pareTop;

wire [3:0] b1,c1,b2,c2;

reg [3:0] a;

reg clk;

initial

begin

clk = 0;

forever #50 clk = ~clk;

end

initial

begin

a = 4'h3;

$display("____________________________");

# 100 a = 4'h7;

$display("____________________________");

# 100 a = 4'hf;

$display("____________________________");

# 100 a = 4'ha;

$display("____________________________");

# 100 a = 4'h2;

$display("____________________________");

# 100 $display("____________________________");

$stop;

end

non_blocking non_blocking(clk,a,b2,c2);

blocking blocking(clk,a,b1,c1);

endmodule

仿真波形(部分):

思考:在blocking模块中按如下写法,仿真与综合得结果会有什么样得变化?作出仿真波形,分析综合结果。

1. always (posedge clk)

begin

c = b;

b = a;

end

2.always (posedge clk) b=a;

always (posedge clk) c=b;

练习五、用always块实现较复杂得组合逻辑电路

目得: 1、掌握用always实现组合逻辑电路得方法;

2、了解assign与always两种组合逻辑电路实现方法之间得区别。

仅使用assign结构来实现组合逻辑电路,在设计中会发现很多地方会显得冗长且效率低下。而适当地采用always来设计组合逻辑,往往会更具实效。已进行得范例与练习中,我们仅在实现时序逻辑电路时使用always块。从现在开始,我们对它得瞧法要稍稍改变。

下面就是一个简单得指令译码电路得设计示例。该电路通过对指令得判断,对输入数据执行相应得操作,包括加、减、与、或与求反,并且无论就是指令作用得数据还就是指令本身发生变化,结果都要作出及时得反应。显然,这就是一个较为复杂得组合逻辑电路,如果采用assign

语句,表达起来非常复杂。示例中使用了电平敏感得always块,所谓电平敏感得触发条件就是

指在后得括号内电平列表中得任何一个电平发生变化,(与时序逻辑不同,它在后得括号内没有沿敏感关键词,如posedge 或negedge)就能触发always块得动作,并且运用了case结构来进行分支判断,不但设计思想得到直观得体现,而且代码瞧起来非常整齐、便于理解。

// alu、v

`define plus 3'd0

`define minus 3'd1

`define band 3'd2

`define bor 3'd3

`define unegate 3'd4

module alu(out,opcode,a,b);

output[7:0] out;

reg[7:0] out;

input[2:0] opcode;

input[7:0] a,b; //操作数。

always(opcode or a or b) //电平敏感得always块

begin

case(opcode)

`plus: out = a+b; //加操作。

`minus: out = ab; //减操作。

`band: out = a&b; //求与。

`bor: out = a|b; //求或。

`unegate: out=~a; //求反。

default: out=8'hx;//未收到指令时,输出任意态。

endcase

end

endmodule

同一组合逻辑电路分别用always块与连续赋值语句assign描述时,代码得形式大相径庭,但就是在always中适当运用default(在case结构中)与else(在if…else结构中),通常可以综合为纯组合逻辑,尽管被赋值得变量一定要定义为reg型。不过,如果不使用default或else对缺省项进行说明,则易生成意想不到得锁存器,这一点一定要加以注意。

指令译码器得测试模块源代码:

// alu_Top、v

`timescale 1ns/1ns

`include "、/alu、v"

module alutest;

wire[7:0] out;

reg[7:0] a,b;

reg[2:0] opcode;

parameter times=5;

initial

begin

a={$random}%256; //Give a radom number blongs to [0,255] 、

b={$random}%256; //Give a radom number blongs to [0,255]、

opcode=3'h0;

repeat(times)

begin

#100 a={$random}%256; //Give a radom number、

b={$random}%256; //Give a radom number、

opcode=opcode+1;

end

#100 $stop;

end

alu alu1(out,opcode,a,b);

endmodule

仿真波形(部分):

练习:运用always块设计一个八路数据选择器。要求:每路输入数据与输出数据均为4位2进制数,当选择开关(至少3位)或输入数据发生变化时,输出数据也相应地变化。

练习六、在Verilog HDL中使用函数

目得:掌握函数在模块设计中得使用。

与一般得程序设计语言一样,Veirlog HDL也可使用函数以适应对不同变量采取同一运算得操作。Veirlog HDL函数在综合时被理解成具有独立运算功能得电路,每调用一次函数相当于改变这部分电路得输入以得到相应得计算结果。

下例就是函数调用得一个简单示范,采用同步时钟触发运算得执行,每个clk时钟周期都会执行一次运算。并且在测试模块中,通过调用系统任务$display在时钟得下降沿显示每次计算得结果。

模块源代码:

module tryfunct(clk,n,result,reset);

output[31:0] result;

input[3:0] n;

input reset,clk;

reg[31:0] result;

always (posedge clk) //clk得上沿触发同步运算。

begin

if(!reset) //reset为低时复位。

result<=0;

else

begin

result <= n * factorial(n)/((n*2)+1);

end

e nd

function [31:0] factorial; //函数定义。

input [3:0] operand;

reg [3:0] index;

begin

factorial = operand ? 1 : 0;

for(index = 2; index <= operand; index = index + 1)

factorial = index * factorial;

end

endfunction

endmodule

测试模块源代码:

`include "、/step6、v"

`timescale 1ns/100ps

`define clk_cycle 50

module tryfuctTop;

reg[3:0] n,i;

reg reset,clk;

wire[31:0] result;

initial

begin

n=0;

reset=1;

clk=0;

#100 reset=0;

#100 reset=1;

for(i=0;i<=15;i=i+1)

begin

#200 n=i;

end

#100 $stop;

end

always #`clk_cycle clk=~clk;

tryfunct tryfunct(、clk(clk),、n(n),、result(result),、reset(reset)); endmodule

上例中函数factorial(n)实际上就就是阶乘运算。必须提醒大家注意得就是,在实际得设计中,我们不希望设计中得运算过于复杂,以免在综合后带来不可预测得后果。经常得情况就是,我们把复杂得运算分成几个步骤,分别在不同得时钟周期完成。

仿真波形(部分):

练习:设计一个带控制端得逻辑运算电路,分别完成正整数得平方、立方与阶乘得运算。编写测试模块,并给出仿真波形。

练习七、在Verilog HDL中使用任务(task)

目得:掌握任务在结构化Verilog HDL设计中得应用。

仅有函数并不能完全满足Veirlog HDL中得运算需求。当我们希望能够将一些信号进行运算并输出多个结果时,采用函数结构就显得非常不方便,而任务结构在这方面得优势则十分突出。任务本身并不返回计算值,但就是它通过类似C语言中形参与实参得数据交换,非常快捷地实现运算结果得调用。此外,我们还常常利用任务来帮助我们实现结构化得模块设计,将批量得操作以任务得形式独立出来,这样设计得目得通常一眼瞧过去就很明了。

下面就是一个利用task与电平敏感得always块设计比较后重组信号得组合逻辑得实例。可以瞧到,利用task非常方便地实现了数据之间得交换,如果要用函数实现相同得功能就是非常复杂得;另外,task也避免了直接用一般语句来描述所引起得不易理解与综合时产生冗余逻辑等问题。

模块源代码:

// sort4、v

module sort4(ra,rb,rc,rd,a,b,c,d);

output[3:0] ra,rb,rc,rd;

input[3:0] a,b,c,d;

reg[3:0] ra,rb,rc,rd;

reg[3:0] va,vb,vc,vd;

always (a or b or c or d)

begin

{va,vb,vc,vd}={a,b,c,d};

sort2(va,vc); //va 与vc互换。

sort2(vb,vd); //vb 与vd互换。

sort2(va,vb); //va 与vb互换。

sort2(vc,vd); //vc 与vd互换。

sort2(vb,vc); //vb 与vc互换。

{ra,rb,rc,rd}={va,vb,vc,vd};

end

task sort2;

inout[3:0] x,y;

reg[3:0] tmp;

if(x>y)

begin

tmp=x; //x与y变量得内容互换,要求顺序执行,所以采用阻塞赋值方式。

x=y;

y=tmp;

end

endtask

endmodule

值得注意得就是task中得变量定义与模块中得变量定义不尽相同,它们并不受输入输出类型得限制。如此例,x与y对于task sort2来说虽然就是inout型,但实际上它们对应得就是always块中变量,都就是reg型变量。

测试模块源代码:

`timescale 1ns/100ps

`include "sort4、v"

module task_Top;

reg[3:0] a,b,c,d;

wire[3:0] ra,rb,rc,rd;

initial

begin

a=0;b=0;c=0;d=0;

repeat(5)

begin

#100 a ={$random}%15;

b ={$random}%15;

c ={$random}%15;

d ={$random}%15;

end

#100 $stop;

sort4 sort4 (、a(a),、b(b),、c(c),、d(d), 、ra(ra),、rb(rb),、rc(rc),、rd(rd)); endmodule

仿真波形(部分):

练习:设计一个模块,通过任务完成3个8位2进制输入数据得冒泡排序。要求:时钟触发任务得执行,每个时钟周期完成一次数据交换得操作。

练习八、利用有限状态机进行复杂时序逻辑得设计

目得:掌握利用有限状态机实现复杂时序逻辑得方法;

在数字电路中我们已经学习过通过建立有限状态机来进行数字逻辑得设计,而在Verilog HDL硬件描述语言中,这种设计方法得到进一步得发展。通过Verilog HDL提供得语句,我们可以直观地设计出适合更为复杂得时序逻辑得电路。关于有限状态机得设计方法在教材中已经作了较为详细得阐述,在此就不赘述了。

下例就是一个简单得状态机设计,功能就是检测一个5位二进制序列“10010”。考虑到序列重叠得可能,有限状态机共提供8个状态(包括初始状态IDLE)。

模块源代码:

seqdet、v

module seqdet(x,z,clk,rst,state);

input x,clk,rst;

output z;

output[2:0] state;

reg[2:0] state;

wire z;

parameter IDLE='d0, A='d1, B='d2,

C='d3, D='d4,

E='d5, F='d6,

G='d7;

assign z = ( state==E && x==0 )? 1 : 0; //当x=0时,状态已变为E, //状态为D时,x仍为1。因此 //输出为1得条件为( state==E && x==0 )。always (posedge clk)

if(!rst)

begin

state <= IDLE;

end

else

casex(state)

IDLE : if(x==1)

begin

state <= A;

end

A: if(x==0)

begin

state <= B;

end

B: if(x==0)

begin

state <= C;

end

else

begin

state <= F;

end

C: if(x==1)

begin

state <= D;

end

else

begin

state <= G;

end

D: if(x==0)

begin

state <= E;

end

else

begin

state <= A;

end

E: if(x==0)

begin

state <= C;

end

else

begin

state <= A;

end

F: if(x==1)

begin

state <= A;

end

else

begin

state <= B;

end

G: if(x==1)

begin

state <= F;

end

default:state=IDLE; //缺省状态为初始状态。 endcase

endmodule

测试模块源代码:

// seqdet、v

`timescale 1ns/1ns

`include "、/seqdet、v"

module seqdet_Top;

reg clk,rst;

reg[23:0] data;

wire[2:0] state;

wire z,x;

assign x=data[23];

always #10 clk = ~clk;

always (posedge clk)

data={data[22:0],data[23]};

initial

begin

clk=0;

rst=1;

#2 rst=0;

#30 rst=1;

data ='b1100_1001_0000_1001_0100;

#500 $stop;

end

seqdet m(x,z,clk,rst,state);

endmodule

仿真波形:

练习:设计一个串行数据检测器。要求就是:连续4个或4个以上得1时输出为1,其她输入情况下为0。编写测试模块并给出仿真波形。

练习九、利用状态机得嵌套实现层次结构化设计

目得:1、运用主状态机与子状态机产生层次化得逻辑设计;

2、在结构化设计中灵活使用任务(task)结构。

在上一节,我们学习了如何使用状态机得实例。实际上,单个有限状态机控制整个逻辑电路得运转在实际设计中就是不多见,往往就是状态机套用状态机,从而形成树状得控制核心。这一点也与我们提倡得层次化、结构化得自顶而下得设计方法相符,下面我们就将提供一个这样得示例以供大家学习。

该例就是一个简化得EPROM得串行写入器。事实上,它就是一个EPROM读写器设计中实现写功能得部分经删节得到得,去除了EPROM得启动、结束与EPROM控制字得写入等功能,只具备这样一个雏形。工作得步骤就是:1、地址得串行写入;2、数据得串行写入;3、给信号源应答,信号源给出下一个操作对象;4、结束写操作。通过移位令并行数据得以一位一位输出。

模块源代码:

module writing(reset,clk,address,data,sda,ack);

input reset,clk;

input[7:0] data,address;

output sda,ack; //sda负责串行数据输出;

//ack就是一个对象操作完毕后,模块给出得应答信号。

reg link_write; //link_write决定何时输出。

reg[3:0] state; //主状态机得状态字。

reg[4:0] sh8out_state; //从状态机得状态字。

reg[7:0] sh8out_buf; //输入数据缓冲。

reg finish_F; //用以判断就是否处理完一个操作对象。 reg ack;

parameter

idle=0,addr_write=1,data_write=2,stop_ack=3;

parameter

bit0=1,bit1=2,bit2=3,bit3=4,bit4=5,bit5=6,bit6=7,bit7=8; assign sda = link_write? sh8out_buf[7] : 1'bz;

always (posedge clk)

begin

i f(!reset) //复位。

begin

link_write<= 0;

state <= idle;

finish_F <= 0;

sh8out_state<=idle;

ack<= 0;

sh8out_buf<=0;

end

e lse

case(state)

idle:

begin

l ink_write <= 0;

state <= idle;

finish_F <= 0;

sh8out_state<=idle;

ack<= 0;

sh8out_buf<=address;

state <= addr_write;

end

addr_write: //地址得输入。

begin

i f(finish_F==0)

begin shift8_out; end

e lse

begin

sh8out_state <= idle;

sh8out_buf <= data;

state <= data_write;

finish_F <= 0;

end

end

data_write: //数据得写入。

begin

i f(finish_F==0)

begin shift8_out; end

e lse

begin

link_write <= 0;

state <= stop_ack;

finish_F <= 0;

ack <= 1;

end

end

stop_ack: //完成应答。

begin

ack <= 0;

state <= idle;

end

endcase

end

task shift8_out; //串行写入。 begin

case(sh8out_state)

idle:

begin

link_write <= 1;

sh8out_state <= bit0;

end

bit0:

begin

link_write <= 1;

sh8out_state <= bit1;

sh8out_buf <= sh8out_buf<<1;

end

bit1:

begin

sh8out_state<=bit2;

sh8out_buf<=sh8out_buf<<1;

end

bit2:

begin

sh8out_state<=bit3;

sh8out_buf<=sh8out_buf<<1;

end

bit3:

begin

sh8out_state<=bit4;

sh8out_buf<=sh8out_buf<<1;

end

bit4:

begin

sh8out_state<=bit5;

sh8out_buf<=sh8out_buf<<1;

end

bit5:

begin

sh8out_state<=bit6;

sh8out_buf<=sh8out_buf<<1;

end

bit6:

begin

sh8out_state<=bit7;

sh8out_buf<=sh8out_buf<<1;

end

bit7:

begin

link_write<= 0;

finish_F<=finish_F+1;

end

endcase

end

endtask

endmodule

测试模块源代码:

`timescale 1ns/100ps

`define clk_cycle 50

module writingTop;

reg reset,clk;

reg[7:0] data,address;

wire ack,sda;

always #`clk_cycle clk = ~clk;

initial

begin

clk=0;

reset=1;

data=0;

address=0;

#(2*`clk_cycle) reset=0;

#(2*`clk_cycle) reset=1;

#(100*`clk_cycle) $stop;

end

always (posedge ack) //接收到应答信号后,给出下一个处理对象。

begin

data=data+1;

address=address+1;

end

writing writing(、reset(reset),、clk(clk),、data(data),

、address(address),、ack(ack),、sda(sda));

endmodule

仿真波形:

练习:仿照上例,编写一个实现EPROM内数据串行读取得模块。编写测试模块,给出仿真波形。

练习十、通过模块之间得调用实现自顶向下得设计

目得:学习状态机得嵌套使用实现层次化、结构化设计。

现代硬件系统得设计过程与软件系统得开发相似,设计一个大规模得集成电路得往往由模块多层次得引用与组合构成。层次化、结构化得设计过程,能使复杂得系统容易控制与调试。在Verilog HDL中,上层模块引用下层模块与C语言中程序调用有些类似,被引用得子模块在综合时作为其父模块得一部分被综合,形成相应得电路结构。在进行模块实例引用时,必须注意得就是模块之间对应得端口,即子模块得端口与父模块得内部信号必须明确无误地一一对应,否则容易产生意想不到得后果。

下面给出得例子就是设计中遇到得一个实例,其功能就是将并行数据转化为串行数据送交外部电路编码,并将解码后得到得串行数据转化为并行数据交由CPU处理。显而易见,这实际上就是两个独立得逻辑功能,分别设计为独立得模块,然后再合并为一个模块显得目得明确、层次清晰。

// p_to_s、v

module p_to_s(D_in,T0,data,SEND,ESC,ADD_100);

output D_in,T0; // D_in就是串行输出,T0就是移位时钟并给

// CPU中断,以确定何时给出下个数据。

input [7:0] data; //并行输入得数据。

input SEND,ESC,ADD_100; //SEND、ESC共同决定就是否进行并到串

//得数据转化。ADD_100决定何时置数。

wire D_in,T0;

reg [7:0] DATA_Q,DATA_Q_buf;

assign T0 = ! (SEND & ESC); //形成移位时钟。、

assign D_in = DATA_Q[7]; //给出串行数据。

always (posedge T0 or negedge ADD_100) //ADD_100下沿置数,T0上沿移位。

begin

if(!ADD_100)

DATA_Q = data;

else

begin

DATA_Q_buf = DATA_Q<<1; //DATA_Q_buf作为中介,以令综合器

DATA_Q = DATA_Q_buf; //能辨明。

end

end

endmodule

在p_to_s、v中,由于移位运算虽然可综合,但就是不就是简单得RTL级描述,直接用DATA_Q<=DATA_Q<<1得写法在综合时会令综合器产生误解。另外,在该设计中,由于时钟T0得频率较低,所以没有象以往那样采用低电平置数,而就是采用ADD_100得下降沿置数。

// s_to_p、v

module s_to_p(T1, data, D_out,DSC,TAKE,ADD_101);

output T1; //给CPU中断,以确定CPU何时取转化

//得到得并行数据。

output [7:0] data;

input D_out, DSC, TAKE, ADD_101; //D_out提供输入串行数据。DSC、TAKE //共同决定何时取数。

wire [7:0] data;

wire T1,clk2;

reg [7:0] data_latch, data_latch_buf;

assign clk2 = DSC & TAKE ; //提供移位时钟。

assign T1 = !clk2;

assign data = (!ADD_101) ? data_latch : 8'bz;

always(posedge clk2)

begin

data_latch_buf = data_latch << 1; //data_latch_buf作缓冲

data_latch = data_latch_buf; //,以令综合器能辩明。

data_latch[0] = D_out;

end

endmodule

将上面得两个模块合并起来得sys、v得源代码:

// sys、v

`include "、/p_to_s、v"

`include "、/s_to_p、v"

module sys(D_in,T0,T1, data, D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101);

input D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101;

inout [7:0] data;

output D_in,T0,T1;

p_to_s p_to_s(、D_in(D_in),、T0(T0),、data(data),

、SEND(SEND),、ESC(ESC),、ADD_100(ADD_100));

s_to_p s_to_p(、T1(T1),、data(data),、D_out(D_out),

、DSC(DSC),、TAKE(TAKE),、ADD_101(ADD_101));

endmodule

测试模块源代码:

//Top test sys、v

`timescale 1ns/100ps

`include "、/sys、v"

module Top;

reg D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101;

reg[7:0] data_buf;

wire [7:0] data;

wire clk2;

assign data = (ADD_101) ? data_buf : 8'bz;

//data在sys中就是inout型变量,ADD_101 //控制data就是作为输入还就是进行输出。assign clk2 =DSC && TAKE;

initial

begin

SEND = 0;

ESC = 0;

DSC = 1;

TAKE = 1;

ADD_100 = 1;

ADD_101 = 1;

end

initial

begin

data_buf = 8'b10000001;

#90 ADD_100 = 0;

#100 ADD_100 = 1;

end

always

begin

#50;

SEND = ~SEND;

ESC = ~ESC;

end

initial

begin

#1500 ;

SEND = 0;

ESC = 0;

DSC = 1;

TAKE = 1;

XFP模块电路设计

XFP模块电路设计 一、应用要求 1、多速率应用:TELECOM(SONET OC-192 and G.709 “OTU-2”) DATACOM(10 Gb/s Ethernet and 10 Gb/s Fibre Channel) 2、XFI(9.95Gb/s~11.7Gb/s)高速信号可以在改良的FR4电路板上传输 300mm或普通的FR4电路板上传输200mm。 3、热插拔智能化,能够提供模块的实时工作状态的监视值 二、指标要求 3、封装结构:按照XFP-MSA的要求 三、方案选择 1、发射器件的选择:采用公司成熟的TO封装工艺开发的发射器件。 2、接收组件的选择:采用公司成熟的TO封装工艺开发的接收组件。

四、电路设计 1、原理框图 LOS Data In TxDis SCL SDA TxFault

2、原理图设计 3、PCB设计 (1)传输线设计: 在PCB设计中采用微带线来进行信号传输,保证高深信号在PCB上传输不发生波形畸变,我们通过AppCAD模拟可得到微带线的宽度和各微带线之间的间距。在10Gb/s的工作速率下,信号波长已经可以与器件尺寸相比拟,基于电路性能、器件选择和电磁兼容等因素的考虑,必须以网络散射分析(S参数)、信号完整性分析、电磁仿真分析、电路仿真分析等手段,来综合考量实际电路系统的工作性能。对电路板、元器件进行结构性电磁仿真并精确提取相应的SPICE电路模型参数,作为电路设计的依据,以此有效减小电感器件在高频设计应用中的误差影响。而且现在国外的产品技术参数大多包含有S参数,通常可用于精确的高频应用分析。信号传输微带线的等效分析见下图。

SystemVerilog

SystemVerilog 语言简介 SystemVerilog 是一种硬件描述和验证语言(HDVL),它基于 IEEE 1364-2001 Verilog 硬件描述语言 (HDL) 并对其进行了扩展, , 包括扩充了 C 语言数据类型、结构、压缩和非压缩数组、 接口、断 言等等, 这些都使得 SystemVerilog 在一个更高的抽象层次上提高了 设计建模的能力。SystemVerilog 由 Accellera 开发,它主要定位在 芯片的实现和验证流程上, 并为系统级的设计流程提供了强大的连接 能力。 下面我们从几个方面对 SystemVerilog 所作的增强进行简要的 介绍, 期望能够通过这个介绍使大家对 SystemVerilog 有一个概括性 的了解。 1. 接口(Interface) Verilog 模块之间的连接是通过模块端口进行的。为了给组成设 计的各个模块定义端口, 我们必须对期望的硬件设计有一个详细的认 识。不幸的是,在设计的早期,我们很难把握设计的细节。而且,一 旦模块的端口定义完成后,我们也很难改变端口的配置。另外,一个 设计中的许多模块往往具有相同的端口定义,在 Verilog 中,我们必 须在每个模块中进行相同的定义,这为我们增加了无谓的工作量。 SystemVerilog 提供了一个新的、高层抽象的模块连接,这个连 接被称为接口(Interface)。接口在关键字 interface 和 endinterface 之间定义,它独立于模块。接口在模块中就像一个单一的端口一样使 用。在最简单的形式下,一个接口可以认为是一组线网。例如,可以 将 PCI 总线的所有信号绑定在一起组成一个接口。通过使用接口, 我们在进行一个设计的时候可以不需要首先建立各个模块间的互连。 随着设计的深入,各个设计细节也会变得越来越清晰,而接口内的信 号也会很容易地表示出来。当接口发生变化时,这些变化也会在使用 该接口的所有模块中反映出来,而无需更改每一个模块。 下面是一个 接口的使用实例: interface chip_bus; // 定义接口 wire read_request, read_grant; wire [7:0] address, data; endinterface: chip_bus
更多免费资料下载请进: https://www.sodocs.net/doc/b410495622.html, 中国最大的免费课件资料库

高速电路设计的经典案例

该文章版权归 smarteebit 所有。若有疑问,请联系 songmin2@https://www.sodocs.net/doc/b410495622.html,
高速数字设计的经典案例若干则
【摘要】 随着这些年半导体工艺突飞猛进的发展, “高速数字设计”对广大硬件工程师来说,已经不再是一 个陌生的词。从航空、雷达到汽车电子,从无线通信到有线接入,甚至在一些低端的嵌入式系统上,高 速数字电路都已经在大行其道。 目前行业内已经有不少关于高速数字电路理论的好文章, 笔者就不在这 上面掺和了。 本文着眼于理论和实际相结合, 所用的素材都来自笔者亲历过的案例, 相信活生生的事实, 比空洞的理论更有说服力,也希望能使入行不久的硬件工程师们得到他们想要的信息,今后少走弯路。 由于不会对理论作过多的阐述, 因此, 本文的阅读对象应该具有一点点高速数字设计的理论基础, 请知。 【关键词】 高速数字设计 高速数字电路 案例
1 信号完整性
什么词汇在高速数字设计中出现得最多?对了,SI(Signal Integrity),也就是信号完整性。信 号完整性问题的表现形式多种多样,主要有如下种类:
图 1 过冲(OVERSHOOT)
图 2 振铃(RING)
图 3 非单调性(NON MONOTONIC)
过冲: 当较快的信号沿驱动一段较长的走线, 而走线拓扑上又没有有效的匹配时, 往往会产生过冲。 过冲带来的问题主要是“1”电平高于接收端器件的输入最大电压值(VIHmax),或“0”电平低于接收端 器件的输入最小电压值(VILmin),这样可能给器件带来潜在的累积性伤害,缩短其工作寿命,从而影响 产品的长期稳定性。
Smarteebit
Page 1 of 17

verilog综合心得

综合:不可综合的运算符:= = = ,!= =,/(除法),%(取余数)。 1、不使用初始化语句。 2、不使用带有延时的描述。 3、不使用循环次数不确定的循环语句,如:forever、while等。 4、尽量采用同步方式设计电路。 5、除非是关键路径的设计,一般不调用门级元件来描述设计的方法,建议采用行为语句来完成设计。 6、用always过程块描述组合逻辑,应在信号敏感列表中列出所有的输入信号。 7、所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。 8、在verilog模块中,任务(task)通常被综合成组合逻辑的形式,每个函数(function)在调用时通常也被综合为一个独立的组合电路模块。 9、用户自定义原语(UDP)是不可综合的,它只能用来建立门级元件的仿真模型。 一般综合工具支持的V erilog HDL结构

移位运算符:V erilog HDL提供向右(>>)及向左(<<)两种运算符,运算符高位或地位一旦移出即予丢弃,其空缺的位则予以补零。 连续赋值语句(assign)、case语句、if…else语句都是可以综合的 initial 语句内若包含有多个语句时,必须以begin end 作聚合;单一的初值赋值,因此并不需以begin end做聚合。 循环(Loops)并不能单独地在程序中存在,而必须在initial和always块中才能使用。initial过程块中的语句仅执行一次,而always块中的语句是不断重复执行的。 编写顶层模块的注意事项 每个端口除了要声明是输入、输出还是双向外,还要声明其数据类型,是连线型(wire)还是寄存器型(reg),如果没有声明则综合器默认为wire型。 1、输入和双向端口不能声明为寄存器型。 2、在测试模块中不需要定义端口。 编写testbentch所归纳的心得

无线模块电路设计

基于MRF24J40的IEEE802.15.4无线收发电 路设计 时间:2010-11-30 19:05:33 来源:作者:黄智伟何娜 IEEE802.15.4无线收发器MRF24J40芯片内部包含有SPI接口、控制寄存器、MAC 模块、PHY驱动器四个主要的功能模块,支持IEEE802.15.4,MiWiTM,ZigBee等协议,工作在2.405~2.48 GHz ISM频段,接收灵敏度为-91 dBm,最大输入电平为+5 dBm,输出功率为+0 dBm,功率控制范围为38.75 dB,集成有20 MHz和32.768 kHz主控振荡器,MAC/基带部分采用硬件CSMA-CA结构,自动ACK6和FCS检测,CTR、CCM和CBC-MAC 模式采用硬件加密(AES-128),电源电压范围为2.4~3.6 V,接收模式电流消耗为18 mA,发射模式电流消耗为22 mA,睡眠模式电流消耗为2μA。 MRF24J40采用6 mm×6 mm QFN-40封装,引脚端封装形式如图1所示。图中:引脚端RFP和RFN分别为芯片的RF差分输入/输出正端和负端,两者都是模拟输入/输出端口,与系统天线相连接;VDD为电源电压输入引脚端,每个电源电压输入引脚端都必须连接一个电源去耦电容;GND为接地引脚端,必须低阻抗的连接到电路的接地板;GPIOO~GPIO5是通用数字I/O口,其中GPIO0也被用来作为外部功率放大器使能控制,GPIO1和GPIO2也被用来作为外部TX/RX开关控制;RESET为复位引脚端,低电平有效;WAKE为外部唤醒触发输入端;INT为到微控制器的中断引脚端;SDO,SDI,SCK和CS是MRF24J40的SPI接口输入输出引脚端,其中SDO是MRF24J40的串行数据输出,SDI是MRF24J40的串行接口数据输入,SCK是串行接口的时钟,CS是串行接口使能控制引脚端;LPOSC1和LPOSC2为32 kHz晶振输入正端和负端;OSC1和OSC2为20 MHz晶振输入正端和负端;CLKOUT为20/10/5/2.5 MHz时钟输出端;LCAP引脚端用来连接一个180 pF的PLL环路滤波器电容;XIP和RXQP为接收I通道和Q通道输出正端。 2 MRF24J40构成的IEEE802.15.4无线收发电路 MRF24J40构成的IEEE802.15.4无线收发电路如图2所示,各电源电压引脚端根据需要分

system verilog教程

SystemVerilog Tutorials 下面的手册会帮助你了解一些SystemVerilog中最重要的新特点。手册还提供了一些代码样本和例子使你可以对语言有更好"感觉"。这些辅导假设你们已经了解了一些Verilog语言。如果没有,你可以先去看看Verilog设计者指南(V erilog Designer’s Guide)。 * Data types * RTL design * Interfaces * Clocking * Assertion-based verification * Classes * Testbench automation and constraints * The Direct Programming Interface (DPI) SystemVerilog 的数据类型 这个手册将描述Systemverilog新引进的数据类型。他们大多数都是可以综合的,并且可以使RTL级描述更易于理解和书写。 整型和实型 SystemVerilog引进了几种新的数据类型。C语言程序员会熟悉其中的大多数。引进新的数据类型构思是这样的,如果C语言和SystemVerilog有相同的数据类型可以使C语言算法模型更容易的转化为SystemVerilog模型。 Verilog的变量类型有四态:既是0,1,X,Z。SystemVerilog引进了新的两态数据类型,每一位只可以是0或是1。当你不需要使用的X和Z值时,譬如在写Testbench和做为for语句的循环变量。使用两态变量的RTL级模型,可以使模拟器更有效率。并且使用得当的话将不会对综合结果产生影响。 二态整型 类型描述例子 Bit user-defined size bit [3:0] a_nibble; Byte 8 bits, unsigned byte a, b; Shortint 16 bits, signed shortint c, d; Int 32 bits, signed int i,j; Longint 64 bits, signed longint lword;

Systemverilog的一个牛人总结

转一篇Systemverilog的一个牛人总结 (2012-12-12 16:47:06) 转载▼ 标签: 分类:Dreamywork systemverilog 验证 面向对象 杂谈 Systemverilog 数据类型 l 合并数组和非合并数组 1)合并数组: 存储方式是连续的,中间没有闲置空间。 例如,32bit的寄存器,可以看成是4个8bit的数据,或者也可以看成是1个32bit的数据。 表示方法: 数组大小和位,必须在变量名前指定,数组大小必须是【msb:lsb】 Bit[3:0] [7:0] bytes ; 2)二维数组和合并数组识别: 合并数组: bit [3:0] [7:0] arrys; 大小在变量名前面放得,且降序 二维数组: int arrays[0:7] [0:3] ; 大小在变量名后面放得,可降序可升序 位宽在变量名前面,用于识别合并和非合并数组,位宽在后面,用于识别数组中元素个数。 3)非合并数组 一般仿真器存放数组元素时使用32bit的字边界,byte、shortint、int都放在一个字中。 非合并数组:字的地位存放变量,高位不用。 表示方法: Bit [7:0] bytes; 4)合并数组和非合并数组的选择 (1)当需要以字节或字为单位对存储单元操作。 (2)当需要等待数组中变化的,则必须使用合并数组。例如测试平台需要通过存储器数据的变化来唤醒,需要用到@,@只能用于标量或者合并数组。

Bit[3:0] [7:0] barray[3] ; 表示合并数组,合并数组中有3个元素,每个元素时8bit,4个元素可以组成合并数组 可以使用barry[0]作敏感信号。 l 动态数组 随机事物不确定大小。 使用方法:数组在开始是空的,同时使用new[]来分配空间,在new[n]指定元素的个数。 Int dyn[]; Dyn = new[5]; //分配5个元素空间 Dyn.delete() ; //释放空间 l 队列 在队列中增加或删除元素比较方便。 l 关联数组 当你需要建立一个超大容量的数组。关联数组,存放稀疏矩阵中的值。 表示方法: 采用在方括号中放置数据类型的形式声明: Bit[63:0] assoc[bit[63:0]]; l 常量: 1)Verilog 推荐使用文本宏。 好处:全局作用范围,且可以用于位段或类型定义 缺点:当需要局部常量时,可能引起冲突。 2)Parameter 作用范围仅限于单个module 3)Systemverilog: 参数可以在多个模块里共同使用,可以用typedef 代替单调乏味的宏。 过程语句 l 可以在for循环中定义变量,作用范围仅在循环内部 for(int i=0;i<10;i++) array[i] =i; l 任务、函数及void函数 1)区别:

非常好的Verilog设计经验谈

时序是设计出来的 我的boss有在华为及峻龙工作的背景,自然就给我们讲了一些华为及altera 做逻辑的一些东西,而我们的项目规范,也基本上是按华为的那一套去做。在工作这几个月中,给我感触最深的是华为的那句话:时序是设计出来的,不是仿出来的,更不是湊出来的。 在我们公司,每一个项目都有很严格的评审,只有评审通过了,才能做下一步的工作。以做逻辑为例,并不是一上来就开始写代码,而是要先写总体设计方案和逻辑详细设计方案,要等这些方案评审通过,认为可行了,才能进行编码,一般来说这部分工作所占的时间要远大于编码的时间。 总体方案主要是涉及模块划分,一级模块和二级模块的接口信号和时序(我们要求把接口信号的时序波形描述出来)以及将来如何测试设计。在这一级方案中,要保证在今后的设计中时序要收敛到一级模块(最后是在二级模块中)。什么意思呢?我们在做详细设计的时候,对于一些信号的时序肯定会做一些调整的,但是这种时序的调整最多只能波及到本一级模块,而不能影响到整个设计。记得以前在学校做设计的时候,由于不懂得设计时序,经常因为有一处信号的时序不满足,结果不得不将其它模块信号的时序也改一下,搞得人很郁闷。 在逻辑详细设计方案这一级的时候,我们已经将各级模块的接口时序都设计出来了,各级模块内部是怎么实现的也基本上确定下来了。 由于做到这一点,在编码的时候自然就很快了,最重要的是这样做后可以让设计会一直处于可控的状态,不会因为某一处的错误引起整个设计从头进行。 ==================================================================== 如何提高电路工作频率 对于设计者来说,我们当然希望我们设计的电路的工作频率(在这里如无特别说明,工作频率指FPGA片内的工作频率)尽量高。我们也经常听说用资源换速度,用流水的方式可以提高工作频率,这确实是一个很重要的方法,今天我想进一步去分析该如何提高电路的工作频率。 我们先来分析下是什么影响了电路的工作频率。 我们电路的工作频率主要与寄存器到寄存器之间的信号传播时延及 clock skew有关。在FPGA内部如果时钟走长线的话,clock skew很小,基本上可以忽略, 在这里为了简单起见,我们只考虑信号的传播时延的因素。 信号的传播时延包括寄存器的开关时延、走线时延、经过组合逻辑的时延(这样划分或许不是很准确,不过对分析问题来说应该是没有可以的),要提高电路的工作频率,我们就要在这三个时延中做文章,使其尽可能的小。 我们先来看开关时延,这个时延是由器件物理特性决定的,我们没有办法去改变,所以我们只能通过改变走线方式和减少组合逻辑的方法来提高工作频率。

SystemVerilog语言简介(doc 26页)

SystemVerilog语言简介(doc 26页)

SystemVerilog语言简介 SystemVerilog是一种硬件描述和验证语言(HDVL),它基于IEEE 1364-2001 Verilog硬件描述语言(HDL),并对其进行了扩展,包括扩充了C语言数据类型、结构、压缩和非压缩数组、接口、断言等等,这些都使得SystemVerilog在一个更高的抽象层次上提高了设计建模的能力。SystemVerilog由Accellera 开发,它主要定位在芯片的实现和验证流程上,并为系统级的设计流程提供了强大的连接能力。下面我们从几个方面对SystemV erilog所作的增强进行简要的介绍,期望能够通过这个介绍使大家对SystemVerilog有一个概括性的了解。 1. 接口(Interface) Verilog模块之间的连接是通过模块端口进行的。为了给组成设计的各个模块定义端口,我们必须对期望的硬件设计有一个详细的认识。不幸的是,在设计的早期,我们很难把握设计的细节。而且,一旦模块的端口定义完成后,我们也很难改变端口的配置。另外,一个设计中的许多模块往往具有相同的端口定义,在Verilog中,我们必须在每个模块中进行相同的定义,这为我们增加了无谓的工作量。 SystemVerilog提供了一个新的、高层抽象的模块连接,这个连接被称为接口(Interface)。接口在关键字interface和e ndinterface之间定义,它独立于模块。接口在模块中就像一个

单一的端口一样使用。在最简单的形式下,一个接口可以认为是一组线网。例如,可以将PCI总线的所有信号绑定在一起组成一个接口。通过使用接口,我们在进行一个设计的时候可以不需要首先建立各个模块间的互连。随着设计的深入,各个设计细节也会变得越来越清晰,而接口内的信号也会很容易地表示出来。当接口发生变化时,这些变化也会在使用该接口的所有模块中反映出来,而无需更改每一个模块。下面是一个接口的使用实例:

system verilog 类的继承

类的继承 SystemVerilog支持单继承(类似Java,而不像C++). 有一个让SystemVerilog支持多重继承的提案[1], 但是短期内不会看到曙光。 目录 ? 1 什么是继承? ? 2 有什么好处 ? 3 开-关定律 ? 4 参考资料 什么是继承? 继承是面向对象编程范式的关键概念。类用来创建用户自定义类型. 继承使得用户可以用非常安全,非侵入的方式对类的行为进行增加或者修改。 使用继承可以定义子类型,在子类型中增加新的方法和数据。被继承的类一般称为基类(SystemVerilog中的超类),得到的新类一般称为引申类(或子类)。 为什么继承如此重要? 因为它使得复用得以实现。让我们通过实例来说明. 假设我们对一个图像模块进行建模. 对其中一部分,我们写了一个代表颜色的类: class Color; byte unsigned red; byte unsigned green; byte unsigned blue; function new(byte unsigned red_=255, byte unsigned green_=255, byte unsigned blue_=255); red=red_; green=green_; blue=blue_; endfunction:new function mix(Color other); function brighter(float percent); task draw_pixel(int x,int y);

Now现在它的下一个版本希望能够处理部分透明的图像。为此,我们给Color类增加了一个alpha成员,。alpha代表图像的透明度。alpha越大,图像的像素越结实(不透明)。'0'代表完全透明,使得图片的背景全部可见。因此,我们修改color类如下: class Color; byte unsigned red; byte unsigned green; byte unsigned blue; byte unsigned alpha; function new(byte unsigned red_=255, byte unsigned green_=255, byte unsigned blue_=255, byte unsigned alpha_=255); red=red_; green=green_; blue=blue_; alpha=alpha_; endfunction:new function mix(Color other);// new implementation -- would depend on // alpha values for both the colors function brighter(float percent);// original implementation good enough task draw_pixel(int x,int y);// new implementation // Other functions ... endclass:Color 注意,即使许多代码是由之前版本的Color类复制而来,我们还是需要单独维护两个版本的代码。这时继承就可以发挥作用,使用继承,我们可以简单的从原始的Color类继承出新类,来添加alpha成员。 class ColorWithAlpha extends Color; byte unsigned alpha; function new(byte unsigned red_=255, byte unsigned green_=255, byte unsigned blue_=255, byte unsigned alpha_=255);

system_verilog教程

基于断言的验证技术 SystemVerilog Tutorials 下面的手册会帮助你了解一些SystemVerilog中最重要的新特点。手册还提供了一些代码样本和例子使你可以对语言有更好"感觉"。这些辅导假设你们已经了解了一些Verilog语言。如果没有,你可以先去看看Verilog设计者指南(V erilog Designer’s Guide)。 * Data types * RTL design * Interfaces * Clocking * Assertion-based verification * Classes * Testbench automation and constraints * The Direct Programming Interface (DPI) SystemVerilog 的数据类型 这个手册将描述Systemverilog新引进的数据类型。他们大多数都是可以综合的,并且可以使RTL级描述更易于理解和书写。 整型和实型 SystemVerilog引进了几种新的数据类型。C语言程序员会熟悉其中的大多数。引进新的数据类型构思是这样的,如果C语言和SystemVerilog有相同的数据类型可以使C语言算法模型更容易的转化为SystemVerilog模型。 Verilog的变量类型有四态:既是0,1,X,Z。SystemVerilog引进了新的两态数据类型,每一位只可以是0或是1。当你不需要使用的X和Z值时,譬如在写Testbench和做为for语句的循环变量。使用两态变量的RTL级模型,可以使模拟器更有效率。并且使用得当的话将不会对综合结果产生影响。 二态整型 类型描述例子 Bit user-defined size bit [3:0] a_nibble;

个人总结FPGA设计中Verilog编程的27条经验

个人总结Verilog编程27条经验 1.强烈建议用同步设计; 2.在设计时总是记住时序问题; 3.在一个设计开始就要考虑到地电平或高电平复位、同步或异步复位、上升沿 或下降沿触发等问题,在所有模块中都要遵守它; 4.在不同的情况下用if和case,最好少用if的多层嵌套(1层或2层比较合 适,当在3层以上时,最好修改写法,因为这样不仅可以reduce area,而且可以获得好的timing); 5.在锁存一个信号或总线时要小心,对于整个design,尽量避免使用latch, 因为在DFT时很难test; 6.确信所有的信号被复位,在DFT时,所有的FlipFlop都是controllable; 7.永远不要再写入之前读取任何内部存储器(如SRAM); 8.从一个时钟到另一个不同的时钟传输数据时用数据缓冲,他工作像一个双时 钟FIFO(是异步的),可以用Async SRAM搭建Async FIFO; 9.在VHDL中二维数组可以使用,它是非常有用的。在VERILOG中他仅仅可以使 用在测试模块中,不能被综合; 10.遵守register-in register-out规则; 11.像synopsys的DC的综合工具是非常稳定的,任何bugs都不会从综合工具中 产生 12.确保FPGA版本与ASIC的版本尽可能的相似,特别是SRAM类型,若版本一致 是最理想的,但是在工作中FPGA版本一般用FPGA自带的SRAM,ASIC版本一般用厂商提供的SRAM; 13.在嵌入式存储器中使用BIST; 14.虚单元和一些修正电路是必需的; 15.一些简单的测试电路也是需要的,经常在一个芯片中有许多测试模块; 16.除非低功耗不要用门控时钟,强烈建议不要在design中使用gate clock; 17.不要依靠脚本来保证设计。但是在脚本中的一些好的约束能够起到更好的性 能(例如前向加法器); 18.如果时间充裕,通过时钟做一个多锁存器来取代用MUX; 19.不要用内部tri-state, ASIC需要总线保持器来处理内部tri-state,如IO cell; 20.在top level中作pad insertion; 21.选择pad时要小心(如上拉能力,施密特触发器,5伏耐压等),选择合适的 IO cell; 22.小心由时钟偏差引起的问题; 23.不要试着产生半周期信号; 24.如果有很多函数要修正,请一个一个地作,修正一个函数检查一个函数; 25.在一个计算等式中排列每个信号的位数是一个好习惯,即使综合工具能做; 26.不要使用HDL提供的除法器; 27.削减不必要的时钟。它会在设计和布局中引起很多麻烦,大多数FPGA有1- 4个专门的时钟通道;

Systemverilog的数据类型教程

本教程将介绍新引入Systemverilog的数据类型。他们大多数是可综合的,而且使得RTL级描述更易于被编写和理解。 整型和实型 SystemVerilog 引入了几种新的数据类型。C语言程序员会熟悉其中的大多数。引进新的数据类型构思是这样的,如果C语言和SystemVeri log有相同的数据类型的话可以使C语言算法模型更容易的转化为Syst emVerilog模型。 Verilog的变量类型是四态类型:即0,1,X(未知值)和Z(高阻值)。SystemVerilog新引入了两态的数据类型,每一位只可以是0或者1。当你不需要使用的X和Z值时,譬如在写Testbench和做为For 语句的循环变量时。使用两态变量的RTL级模型,可以使仿真器效率更高。而且使用得当的话将不会对综合结果产生任何的影响。 注意:和C语言不一样,SystemVerilog指定了一些固定宽度的数据类型。 logic是一种比reg型更好更完善的数据类型。我们将会看到,你可

以使用logic型来替代过去您有可能使用reg型或wire型的地方。 数组 在Verilog-1995中,你可以定义标量或是矢量类型的线网和变量。你也可以定义一维数组变量类型的存储器数组。在Verilog-2001中允许多维的线网和变量数组存在,并且取消了部分存储器数组用法的限制。 SystemVerilog进一步完善了数组的概念,并对数组重新进行了定义,从而允许对数组进行更多的操作。 在SystemVerilog中,数组可以有压缩尺寸或是非压缩尺寸的属性,也可以同时具有两种属性。考虑下面的例子: reg [3:0][7:0] register [0:9]; 压缩尺寸是[3:0]和[7:0],非压缩尺寸是[0:9] 。(只要你喜欢可以有任意大小的压缩尺寸和非压缩尺寸) 压缩尺寸: 1)保证将在存储器中产生连续的数据 2)可以复制到任何其他的压缩对象中 3)可切片("部分选取") 4)仅限于位类型(bit, logic, int等),其中有些(如int)有固定的 尺寸 相比之下,非压缩数组在内存中的排列方式由仿真器任意选定。我们可以可靠地复制非压缩数组到另一个具有相同数据类型的数组中。对于不同数据类型的数组,你必须使用强制类型转换(有几个非压缩数组转换到压缩数组的规则)。其中非压缩数组可以是任意的类型,如实数数组。

SystemVerilog 中的随机化激励

SystemVerilog中的随机化激励 神州龙芯集成电路设计公司 杨鑫 徐伟俊 陈先勇 夏宇闻 [摘要]:随着集成电路的验证工作日渐复杂,对验证的可靠性提出了越来越高的要求。传统的验证工作中也使用随机化激励以便减轻测试代码编写的工作量,以提升验证的可靠性。在SystemVerilog更强调了利用随机化激励函数以提高验证代码的效率和验证可靠性的重要性。本文以VMM库为例,阐述了如何在SystemVerilog中使用随机化函数来编写高效率的测试代码,重点介绍了可重用验证函数库的使用方法,以帮助读者理解如何使用SystemVerilog高效率地完成复杂的设计验证。 关键字:VMM SystemVerilog 激励随机化 1. 前言 随着电路工艺设计技术的不断发展,集成电路的逻辑设计变得越来越复杂,随之对验证工作提出了更高的要求。由于投片(tip-out)的费用较高,很有必要在投片前对芯片设计进行全面、可信的验证,以尽量减少“设计——测试——投片——调试——发现Bug修改设计”这一流程的迭代次数。因此在集成电路芯片的设计中,尤其是复杂逻辑设计中,对测试工作的效率和可靠性提出了更高的要求。 在传统的验证方法中,也有将激励随机化的方法,这样可以用较少的测试代码生成较多、较全面的测试激励。这些方法减少了人为因素的干扰,能有效地提高验证的工作效率和可靠性。 在SystemVerilog中,强调在验证中使用可重用的验证IP,包括如何生成随机化激励。对于如何尽可能地使用已有的验证IP,以及编写符合标准的可重用验证组件,SystemVerilog提供了一整套的工作机制,这使得符合规范的随机化激励组件能够很好地在多个设计间复用,这更进一步地提高了验证工作的效率和可靠性。 2. 在验证中使用随机化激励 在验证中,可以依照DUT(Design Under Test,被测设计,以下简称DUT)的验证要求来设计定向的激励,并对照DUT的预期响应,用人工的方法来判断设计是否正确。但也可以使用随机化激励来驱动DUT,并使用特定的机制来完成响应的自检测。 利用随机化来产生激励可以看作一种近似的自动化激励产生,因为随机化足够长的时间后,所生成的激励可以覆盖绝大部分的待验证特性。但是纯粹的随机化激励效率并不高,因为其中正确的,或是有意义的激励只占很少一部分。必须使用一定的约束条件限制随机化的范围,从而产生大量随机而有意义的激励。

Verilog的135个经典设计实例

【例3.1】4位全加器 module adder4(cout,sum,ina,inb,cin); output[3:0] sum; output cout; input[3:0] ina,inb; input cin; assign {cout,sum}=ina+inb+cin; endmodule 【例3.2】4位计数器 module count4(out,reset,clk); output[3:0] out; input reset,clk; reg[3:0] out; always @(posedge clk) begin if (reset) out<=0; //同步复位 else out<=out+1; //计数 end endmodule 【例3.3】4位全加器的仿真程序 `timescale 1ns/1ns `include "adder4.v" module adder_tp; //测试模块的名字 reg[3:0] a,b; //测试输入信号定义为reg型 reg cin; wire[3:0] sum; //测试输出信号定义为wire型 wire cout; integer i,j; adder4 adder(sum,cout,a,b,cin); //调用测试对象 always #5 cin=~cin; //设定cin的取值 initial begin a=0;b=0;cin=0; for(i=1;i<16;i=i+1) #10 a=i; //设定a的取值 end - 1 -

initial begin for(j=1;j<16;j=j+1) #10 b=j; //设定b的取值 end initial//定义结果显示格式 begin $monitor($time,,,"%d + %d + %b={%b,%d}",a,b,cin,cout,sum); #160 $finish; end endmodule 【例3.4】4位计数器的仿真程序 `timescale 1ns/1ns `include "count4.v" module coun4_tp; reg clk,reset; //测试输入信号定义为reg型 wire[3:0] out; //测试输出信号定义为wire型 parameter DELY=100; count4 mycount(out,reset,clk); //调用测试对象 always #(DELY/2) clk = ~clk; //产生时钟波形 initial begin//激励信号定义 clk =0; reset=0; #DELY reset=1; #DELY reset=0; #(DELY*20) $finish; end //定义结果显示格式 initial $monitor($time,,,"clk=%d reset=%d out=%d", clk, reset,out); endmodule 【例3.5】“与-或-非”门电路 module AOI(A,B,C,D,F); //模块名为AOI(端口列表A,B,C,D,F) input A,B,C,D; //模块的输入端口为A,B,C,D output F; //模块的输出端口为F - 2 -

实验四串口接收模块电路设计

实验四串口接收模块电路设计 一、实验目的: 1、熟练使用ISE设计工具。 2、理解串口传输协议。理解采用“自顶向下”设计思路,分解模块的方法。 3、在ISE使用Verilog HDL设计串口接收模块,完成仿真、下载。 二、原理分析 (一)串口传输协议概述 设计完成异步串口通信通用异步收发是一种典型的异步串口通信,简称UART。串口通信时序如图1所示。 图1 通用异步收发时序图 由图1可以看出,在没有数据传送时,通信线会一直处于高电平,即逻辑1状态;当有数据传送时,数据帧以起始位开始,以停止位结束。起始位为低电平,即逻辑0状态;停止位为高电平,即逻辑1状态,其持续时间可选为1位、1.5位或2位(本次设计选择持续时间1位)。接收端在接收到停止位后,知道一帧数据已经传完,转为等待数据接收状态;只要再接收到0状态,即为新一帧数据的起始状态。 数据帧的数据位低位(LSB)在前,高位(MSB)在后,根据不同的编码规则,数据位可能为5位、6位、7位或者8位(本次设计数据位定位8位)。校验位也可根据需要选择奇校验、偶校验或者不要校验(本次设计不要校验位)。 (二)串口时序分析 串口通讯常用“波特率”表述串口传输速率,常用的参数有9600 bps 和115200 bps等。在硬件传输角度看,波特率表征了传输一位数据所需要的时间。例如:波特率是9600 bps,传输一位数据的时间是1/9600= 0.000104166666666667秒。如果FPGA系统时钟是20MHZ,则一位数据传输时间相当于(1/9600)/(1/20M)=2083个20MHZ时钟周期。 设一帧数据位数=1(开始位)+8(数据位)+1(校验位)+1(结束位)=11位,所以传输一帧数据的时间是11*1/9600=0.00114583333333333333333333333333秒。 为了稳定采集串口数据帧的数据,需要在每位数据的“中间时刻”采样,由此,需要在每位数据开始时刻对时钟进行计数,若系统时钟是20MHZ,则在计数至2083/2=1042时采样此时刻的数值。 三、系统分析: 为实现串口接收电路,FPGA应该完成: 1、及时发现数据传输的开始,并判断每一位的开始。 2、按照“在数据位中间采样”的要求,确认采样时刻。 3、将采样得到串行数据转换为并行数据。

电源电路设计模块图

电源电路单元 前面介绍了电路图中的元器件的作用和符号。一张电路图通常有几十乃至几百个元器件,它们的连线纵横交叉,形式变化多端,初学者往往不知道该从什么地方开始,怎样才能读懂它。其实电子电路本身有很强的规律性,不管多复杂的电路,经过分析可以发现,它是由少数几个单元电路组成的。好象孩子们玩的积木,虽然只有十来种或二三十种块块,可是在孩子们手中却可以搭成几十乃至几百种平面图形或立体模型。同样道理,再复杂的电路,经过分析就可发现,它也是由少数几个单元电路组成的。因此初学者只要先熟悉常用的基本单元电路,再学会分析和分解电路的本领,看懂一般的电路图应该是不难的。 按单元电路的功能可以把它们分成若干类,每一类又有好多种,全部单元电路大概总有几百种。下面我们选最常用的基本单元电路来介绍。让我们从电源电路开始。 一、电源电路的功能和组成 每个电子设备都有一个供给能量的电源电路。电源电路有整流电源、逆变电源和变频器三种。常见的家用电器中多数要用到直流电源。直流电源的最简单的供电方法是用电池。但电池有成本高、体积大、需要不时更换(蓄电池则要经常充电)的缺点,因此最经济可靠而又方便的是使用整流电源。 电子电路中的电源一般是低压直流电,所以要想从 220 伏市电变换成直流电,应该先把220 伏交流变成低压交流电,再用整流电路变成脉动的直流电,最后用滤波电路滤除脉动直流电中的交流成分后才能得到直流电。有的电子设备对电源的质量要求很高,所以有时还需要再增加一个稳压电路。因此整流电源的组成一般有四大部分,见图 1 。其中变压电路其实就是一个铁芯变压器,需要介绍的只是后面三种单元电路。 二、整流电路 整流电路是利用半导体二极管的单向导电性能把交流电变成单向脉动直流电的电路。 ( 1 )半波整流 半波整流电路只需一个二极管,见图 2 ( a )。在交流电正半周时 VD 导通,负半周时 VD 截止,负载 R 上得到的是脉动的直流电

System Verilog笔记总结

Systemverilog 数据类型 l 合并数组和非合并数组 1)合并数组: 存储方式是连续的,中间没有闲置空间。 例如,32bit的寄存器,可以看成是4个8bit的数据,或者也可以看成是1个32bit的数据。 表示方法: 数组大小和位,必须在变量名前指定,数组大小必须是【msb:lsb】 Bit[3:0] [7:0] bytes ; 2)二维数组和合并数组识别: 合并数组: bit [3:0] [7:0] arrys; 大小在变量名前面放得,且降序 二维数组: int arrays[0:7] [0:3] ; 大小在变量名后面放得,可降序可升序 位宽在变量名前面,用于识别合并和非合并数组,位宽在后面,用于识别数组中元素个数。 3)非合并数组 一般仿真器存放数组元素时使用32bit的字边界,byte、shortint、int都放在一个字中。 非合并数组:字的地位存放变量,高位不用。 表示方法: Bit [7:0] bytes; 4)合并数组和非合并数组的选择 (1)当需要以字节或字为单位对存储单元操作。 (2)当需要等待数组中变化的,则必须使用合并数组。例如测试平台需要通过存储器数据的变化来唤醒,需要用到@,@只能用于标量或者合并数组。 Bit[3:0] [7:0] barray[3] ; 表示合并数组,合并数组中有3个元素,每个元素时8bit,4个元素可以组成合并数组 可以使用barry[0]作敏感信号。 l 动态数组 随机事物不确定大小。 使用方法:数组在开始是空的,同时使用new[]来分配空间,在new[n]指定元素的个数。 Int dyn[]; Dyn = new[5]; //分配5个元素空间 Dyn.delete() ; //释放空间

verilog学习心得

verilog学习心得 1.数字电路基础知识:布尔代数、门级电路的内部晶体管结构、组合逻辑电路分析与设计、触发器、时序逻辑电路分析与设计 2.数字系统的构成:传感器AD 数字处理器DA 执行部件 3.程序通在硬件上的执行过程: C语言(经过编译)-->该处理器的机器语言(放入存储器)-->按时钟的节拍,逐条取出指令、分析指令、执行指令 4.DSP处理是个广泛概念,统指在数字系统中做的变换(DFT)、滤波、编码解码、加密解密、压缩解压等处理 5.数字处理器包括两部分:高速数据通道接口逻辑、高速算法电路逻辑 6.当前,IC产业包括IC制造和IC设计两部分,IC设计技术发展速度高于IC设计 7.FPGA设计的前续课程:数值分析、DSP、C语言、算法与数据结构、数字电路、HDL语言计算机微体系结构 8.数字处理器处理性能的提高:软件算法的优化、微体系结构的优化 9.数字系统的实现方式: 编写C程序,然后用编译工具得到通用微处理器的机器指令代码,在通用微处理器上运行(如8051/ARM/PENTUIM) 专用DSP硬件处理器 用FPGA硬件逻辑实现算法,但性能不如ASIC 用ASIC实现,经费充足、大批量的情况下使用,因为投片成本高、周期长 10.FPGA设计方法:IP核重用、并行设计、层次化模块化设计、top-down思想 FPGA设计分工:前端逻辑设计、后端电路实现、仿真验证 11.matlab的应用: matlab中有许多现成的数学函数可以利用,节省了复杂函数的编写时间 matlab可以与C程序接口 做算法仿真和验证时能很快生成有用的数据文件和表格 DSP builder可以直接将simulink模型转换成HDL代码,跳过了中间的C语言改写步骤 12.常规从算法到硬件电路的开发过程: 算法的开发 C语言的功能描述 并行结构的C语言改写 verilog的改写 仿真、验证、修正 综合、布局布线、投入实用 13.C语言改写成verilog代码的困难点: 并行C语言的改写,因为C本身是顺序执行,而不是并行执行 不使用C语言中的复杂数据结构,如指针 目前有将C语言转换成verilog的工具? 14.HDL HDL描述方法是从电路图描述方法演化来的,相比来说更容易修改 符合IEEE标准的有verilog HDL和VHDL VHDL由美国国防部开发,有1987和1993两个版本 verilog由cadence持有,有1995、2001、2005三个版本 verilog较VHDL更有前景:具有模拟电路描述能力、不仅可以开发电路还可以验证电路、门级以下描述比VHDL强

相关主题