verilog中reg变量赋初始值问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了verilog中reg变量赋初始值问题相关的知识,希望对你有一定的参考价值。
大家帮我看看,我遇到2个问题,非常感谢
1:reg型变量能在定义的时候直接赋值吗?比如reg[3:0] a=10;有人说可以,但是我试过,不行
2:reg型变量,可以在always中利用reset 赋值,这个我试过,可以。但是有个问题,我不用按reset 键也能赋值,咋回事呢?比如,下面程序上电自动赋值,不用按键。
always@(posedge clk,negedge rst)
if(!rst) a=10; //a赋初值
else
begin
......
end
不用按reset 键也能赋值,是因为你的硬件有一个上电复位电容,就是但凡刚启动,都会自动复位。追问
非常感谢!但是没有积分了,呵呵
参考技术A reg型变量能在定义的时候直接赋值,这跟综合工具有关,一般不建议将这样的代码直接综合而是仅仅仿真用。不用按reset 键也能赋值,是因为你的硬件有一个上电复位电容,就是但凡刚启动,都会自动复位。 参考技术B 求可综合,可以简单写成:
always@ (posedge a)
begin
@ (negedge b)
c<=...;
end
如果要想可综合的话,需要用状态机类似的概念,
即设一个标志位,当a上升沿来是,把它赋值为1,
当它为1且b下降沿来时,给c赋值,并将它赋值回0:
并且,如果a,b不是时钟的话,不推荐使用posedge的写法
采用下面的方法比较好:
reg a_dly,b_dly; //a,b的1始终delay信号
wire a_pos,b_pos; //a,b的上升沿抓取信号
assign a_pos = a & !a_dly;
assign b_pos = b & !b_dly;
reg flag;//标志位
always@(posedge clk or posedge rst)
begin
if(rst) begin
a_pos <= 1'b0;
b_pos <= 1'b0;
end
else begin
a_pos <= a;
b_pos <= b;
end
end
always@(posedge clk or posedge rst)
begin
if(rst)
flag <= 1'b0;
else if(a_pos)
flag <= 1'b1;
else if(b_pos)
flag <= 1'b0;
end
always@(posedge clk)
begin
if(flag & b_pos)
c<=....
end
把flag赋值回为0很重要,不然逻辑有问题。
用3段状态机写就是
parameter IDLE = 2'h0;
parameter WAIT_B_POS = 2'h1;
parameter GET_C = 2'h2;
reg [1:0] cs; //current state
reg [1:0] ns; //next state
//1段 状态转换
always@(posedge clk or posedge rst)
begin
if(rst)
cs <= IDLE;
else
cs <= ns;
end
//2段 状态迁移
always@(a_pos or b_pos or cs or ns)
begin
ns = XX; //设置ns为xx
case(cs)
IDLE: begin
if(a_pos) ns = WAIT_B_POS;//用阻塞赋值
else ns = IDLE;
end
WAIT_B_POS:begin
if(b_pos) ns = GET_C;
else ns = WAIT_B_POS;
end
GET_C:begin
ns = IDLE;
end
default:;
endcase
end
//3段 赋值
always@(posedge clk or posedge rst)
begin
if(rst)
c<=1'b0;
else begin
if(ns == GET_C)
c <= .....;
end
end
用状态机写的好处就是不用加标志位了,但是个人觉得没有必要这样写。
能力有限,错误请指正 参考技术C 1.reg类型的不可以直接赋值的,一般在always块中进行赋值。
2.有上电复位的。 参考技术D 不能,可不可以把完整的程序,发给我看下!!
verilog中reg和wire的区别
参考技术A 首先要先清楚一点,verilog是硬件描述语言,其最终是为了生成一个电路,所以它的变量类型是根据实际电路来决定的。从名字理解:
wire,线型,实际上在电路中的作用就是一根连线;
reg,寄存器型,在电路中就作为寄存器存在。
连线和寄存器是构成数字电路的基本结构,这也是verilog这两种变量类型的来源。
当然,在verilog的升级版system verilog中提供了更多的,更一些抽象化的变量类型本回答被提问者采纳 参考技术B wire表示直通,即输入有变化,输出马上无条件地反映(如与、非门的简单连接)。
reg表示一定要有触发,输出才会反映输入的状态。
reg相当于存储单元,wire相当于物理连线。reg表示一定要有触发,没有输入的时候可以保持原来的值,但不直接实际的硬件电路对应。
两者的区别是:寄存器型数据保持最后一次的赋值,而线型数据需要持续的驱动。wire使用在连续赋值语句中,而reg使用在过程赋值语句(initial,always)中。wire若无驱动器连接,其值为z,reg默认初始值为不定值 x 。
在连续赋值语句中,表达式右侧的计算结果可以立即更新表达式的左侧。在理解上,相当于一个逻辑之后直接连了一条线,这个逻辑对应于表达式的右侧,而这条线就对应于wire。
在过程赋值语句中(比如always语句),表达式右侧的计算结果在某种条件的触发下放到一个变量当中,而这个变量可以声明成reg类型的,根据触发条件的不同,过程赋值语句可以建模不同的硬件结构:如果这个条件是时钟的上升沿或下降沿,那么这个硬件模型就是一个触发器;如果这个条件是某一信号的高电平或低电平,那么这个硬件模型就是一个锁存器;如果这个条件是赋值语句右侧任意操作数的变化,那么这个硬件模型就是一个组合逻辑。
对组合逻辑输出变量,可以直接用assign。即如果不指定为reg类型,那么就默认为1位wire类型,故无需指定1位wire类型的变量。当然专门指定出wire类型,可能是多位或为使程序易读。wire只能被assign连续赋值,reg只能在initial和always中赋值。
输入端口可以由wire/reg驱动,但输入端口只能是wire;输出端口可以是wire/reg类型,输出端口只能驱动wire;若输出端口在过程块中赋值则为reg型,若在过程块外赋值则为net型(wire/tri)。用关键词inout声明一个双向端口,inout端口不能声明为reg类型,只能是wire类型。
默认信号是wire类型,reg类型要申明。这里所说的默认是指输出信号申明成output时为wire。如果是模块内部信号,必须申明成wire或者reg.
对于always语句而言,赋值要申明成reg,连续赋值assign的时候要用wire。
模块调用时 信号类型确定方法总结如下:
•信号可以分为端口信号和内部信号。出现在端口列表中的信号是端口信号,其它的信号为内部信号。
•对于端口信号,输入端口只能是net类型。输出端口可以是net类型,也可以是register类型。若输出端口在过程块中赋值则为register类型;若在过程块外赋值(包括实例化语句),则为net类型。
•内部信号类型与输出端口相同,可以是net或register类型。判断方法也与输出端口相同。若在过程块中赋值,则为register类型;若在过程块外赋值,则为net类型。
•若信号既需要在过程块中赋值,又需要在过程块外赋值。这种情况是有可能出现的,如决断信号。这时需要一个中间信号转换。
下面所列是常出的错误及相应的错误信息(error message)
•用过程语句给一个net类型的或忘记声明类型的信号赋值。
信息:illegal …… assignment.
•将实例的输出连接到声明为register类型的信号上。
信息: has illegal output port specification.
以上是关于verilog中reg变量赋初始值问题的主要内容,如果未能解决你的问题,请参考以下文章