1、在always块与块之间是并行的,always块与initial块之间是并行的。
2、always块如果是用非阻塞(<=)是并行的;如果是用阻塞(=)是顺序的;
这道题最好的方法是用标准的状态机写法。
module gray(
input Clk,
input Reset,
input En,
output reg[2:0] Output,
output reg Overflow
);
reg [2:0] state;
reg flag;
initial begin
state <= 3'b000;
//flag <= 1'b0;
end
always @(posedge Clk ) begin
if(Reset) begin
state <=3'b000;
Output <= 3'b000;
Overflow <= 1'b0;
end
else if(En) begin
case(state)
3'b000: begin
state <= 3'b001;
Output <= 3'b001;
end
3'b001: begin
state<=3'b011;
Output<=3'b011;
end
3'b011: begin
state<=3'b010;
Output<=3'b010;
end
3'b010:begin
state<=3'b110;
Output<=3'b110;
end
3'b110:begin
state<=3'b111;
Output<=3'b111;
end
3'b111:begin
state<=3'b101;
Output<=3'b101;
end
3'b101:begin
state<=3'b100;
Output<=3'b100;
end
3'b100:begin
state<=3'b000;
Output<=3'b000;
Overflow<=1'b1;
end
endcase
end
end
endmodule
也可以采取利用二进制数直接根据公式转为对应的格雷码,格雷码的最高位就是对应二进制的最高位,格雷码除了最高位的其他位都是对应二进制的这一位和上一位的异或,比如求二进制数110对应的格雷码,最高位和110一样是1,次高位是二进制数的次高位和最高位的异或(1^1=0),最低位是二进制数最低位和次高位的异或(1^0=1),所以格雷码是101。
展示一种错误的代码:
`timescale 1ns/1ps
//`timescale 1ns/1ps
module gray (
input Clk,
input Reset,
input En,
output reg[2:0] Output,
output Overflow
);
reg [2:0] normal;
reg flow;
always @(posedge Clk) begin
if (Reset==1) begin
normal<=0;
flow <= 0;
end
else
begin
if (normal == 7 && En==1) begin
normal <= 0;
flow <= 1;
end
else if (En==1 && normal !=7) begin
normal <=normal+1;
end
else begin
normal <= normal;
end
end
output[2]<=normal[2];
output[1]<=normal[2]^normal[1];
output[0]<=normal[1]^normal[0];
Overflow<=flow;
end
endmodule
错误原因,认为always里的赋值语句是顺序执行的,认为给output赋的值是在normal被更新完后进行的,而实际上output的赋值和normal的赋值时并行执行的,所以output的值利用的时上一轮的normal(output的值晚了一个周期)
正确写法:
`timescale 1ns/1ps
//`timescale 1ns/1ps
module gray (
input Clk,
input Reset,
input En,
output [2:0] Output,
output Overflow
);
reg [2:0] normal;
reg flow;
always @(posedge Clk) begin
if (Reset==1) begin
normal<=0;
flow <= 0;
end
else
begin
if (normal == 7 && En==1) begin
normal <= 0;
flow <= 1;
end
else if (En==1 && normal !=7) begin
normal <=normal+1;
end
else begin
normal <= normal;
end
end
end
assign Output[2] = normal[2];
assign Output[1] = normal[2] ^normal[1];
assign Output[0] = normal[1]^normal[0];
assign Overflow=flow;
endmodule
assign相当于导线,可以理解为只要normal改变,给output的赋值行为在瞬间进行。因此此时的output就是在和normal同步变化。