Building large circuit(1)
这就是道简单的计数器问题,代码如下
module top_module (
input clk,
input reset,
output [9:0] q);
always @(posedge clk) begin
if(reset)
q<=10’d0;
else if(q==10’d999)
q<=10’d0;
else
q<=q+1;
end
endmodule
另一种写法时序与组合逻辑分开
always@(posedge clk)
begin
if(rst)
begin
count <= 1’b0;
end
else
begin
count <= nextCount;
end
end
assign nextCount = count + 1’b1;
这道题目的意思是当shift_ena有效时,进行移位操作,同时加上data的值,count_ena有效时,进行减法器的功能,代码如下:
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output reg [3:0] q); // reg [3:0] q;
always @(posedge clk)
begin
if(shift_ena == 0&&count_ena == 0)
q<=q;
else if(shift_ena == 1 &&count_ena == 0)
begin
q <= (q<<1) + data;
end
else if(shift_ena==0&&count_ena ==1)
begin
if(q>0)
q<=q-1’b1;
else
q<=4’b1111;
end
end
endmodule
错误:这道题当时博主犯了个巨大的错误,就是没有搞懂阻塞与非阻塞赋值的区别,在always@(*)下的begin-end模块下的阻塞语句时顺序执行,但是时序下的begin-end模块下的非阻塞赋值语句是并行执行的,举个例子:如果上述程序写成q<=q<<1; q<=q+data;
这就是上述问题的错误结果,只进行了加法操作,问题出现了当同时有两个赋值一起执行,最后的结果如何,到底是左移的结果还是相加的结果呢,以及这样的原因,有待解决,这个问题得到了解决,这种赋值方式称为赋值冲突,只会执行最后一句,执行q<=q+data;
这是序列检测的问题,一般用于状态机的方法,这道题当初最大的问题在于检测到正确的序列1101后如何让输出一直为1,直到复位有效,也就是把输出当做判断条件,一旦输出为一就一直为一,所以在不同的状态下进行输出的判断。代码如下:
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output start_shifting);
reg [2:0] state,next_state;
reg flag;
parameter Idle=0,s0=1,s1=2,s2=3,s3=4;
always @(posedge clk)
begin
if(reset)
state<=Idle;
else
state<=next_state;
endalways @(*)
begin
case(state)
Idle: next_state=data?s0:Idle;
s0: next_state=data?s1:Idle;
s1: next_state=data?s1:s2;
s2: next_state=data?s3:Idle;
s3: next_state=data?s0:Idle;
endcase
end
always @(posedge clk)
begin
if(reset)
begin
start_shifting<=0;
end
else
begin
case(next_state)
Idle:
begin
if(start_shifting == 1)
start_shifting<=1;
else
start_shifting<=0;
end
s0:
begin
if(start_shifting == 1)
start_shifting<=1;
else
start_shifting<=0;
end
s1:
begin
if(start_shifting == 1)
start_shifting<=1;
else
start_shifting<=0;
end
s2:
begin
if(start_shifting==1)
start_shifting<=1;
else
start_shifting<=0;
end
s3:
start_shifting<=1;
endcase
end
end
endmodule
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena); reg [2:0] cnt; always @(posedge clk) begin
if(reset)
begin
cnt<=0;
shift_ena<=1;
end
else if(shift_ena==1&&cnt<3)
begin
shift_ena<=1;
cnt<=cnt+1;
end
else
begin
shift_ena<=0;
cnt<=0;
end
end
endmodule
分析:这道题由于在复位有效下,shift_ena需要持续四个周期的高电平,因此需要计数器,第二个复位shift_ena持续了六个周期,这说明当reset有效时需要重新计数,那什么作为计数的判断条件呢?那就是输出一旦输出为一说明reset有效过,然后进行计数器的加一。代码如下:
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
reg [2:0] cnt;
always @(posedge clk) begin
if(reset)
begin
cnt<=0;
shift_ena<=1;
end
else if(shift_ena==1&&cnt<3)
begin
shift_ena<=1;
cnt<=cnt+1;
end
else
begin
shift_ena<=0;
cnt<=0;
end
end
endmodule 今天先更新到这里