一、生存锁存器
Syntactically-correct code does not necessarily result in a reasonable circuit (combinational logic + flip-flops). The usual reason is: "What happens in the cases other than those you specified?". Verilog's answer is: Keep the outputs unchanged.
语法正确的代码不一定产生合理的电路(组合逻辑+触发器)。通常的原因是:“除了你指定的那些情况之外,会发生什么?”Verilog的答案是:保持输出不变。
如果写代码时,存在未指定的输出,那么编译器会将未指定输出连到锁存器,这是为了“保持输出不变”。以HDLbits的题目为例:
Always if2 - HDLBits (01xz.net)
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
end
endmodule
以上的代码在Vivado综合后的电路就包含了锁存器:
下面的代码就是补全了else的部分。如果将代码补全,将相应的输出补充了,那么锁存器就不会出现在综合的电路中:
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
else
keep_driving = 0;
end
endmodule
二、Case语句生成多路选择器
Case语句一般会被综合成多路选择器。
Always case - HDLBits (01xz.net)
// synthesis verilog_input_version verilog_2001
module top_module (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [3:0] out );//
always@(*) begin // This is a combinational circuit
case(sel)
0:out = data0;
1:out = data1;
2:out = data2;
3:out = data3;
4:out = data4;
5:out = data5;
default:out = 0;
endcase
end
endmodule
三、Case语句生成ROM
如果你的case语句非常多,那么编译器会把你的电路综合成ROM。
Always case2 - HDLBits (01xz.net)
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always@(*)begin
case(in)
4'h0:pos= 2'h0;
4'h1:pos= 2'h0;
4'h2:pos= 2'h1;
4'h3:pos= 2'h0;
4'h4:pos= 2'h2;
4'h5:pos= 2'h0;
4'h6:pos= 2'h1;
4'h7:pos= 2'h0;
4'h8:pos= 2'h3;
4'h9:pos= 2'h0;
4'ha:pos= 2'h1;
4'hb:pos= 2'h0;
4'hc:pos= 2'h2;
4'hd:pos= 2'h0;
4'he:pos= 2'h1;
4'hf:pos= 2'h0;
default: pos = 2'b0;
endcase
end
endmodule
四、Case语句生成锁存器(Latch)
由于我的case代码缺少了default语句,因此综合中出现了锁存器。
当加入了default语句以后,锁存器也就消失了。
五、移位寄存器
题目:
https://hdlbits.01xz.net/wiki/Exams/2014_q4bhttps://hdlbits.01xz.net/wiki/Exams/2014_q4b
代码:
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
); //
wire w,L,E,clk;
wire [3:0] R;
assign {w,L,E,clk} = KEY;
assign R = SW;
MUXDFF MUXDFF_3(
.clk(clk),
.R(R[3]),
.E(E),
.L(L),
.w(w),
.Q(LEDR[3])
);
MUXDFF MUXDFF_2(
.clk(clk),
.R(R[2]),
.E(E),
.L(L),
.w(LEDR[3]),
.Q(LEDR[2])
);
MUXDFF MUXDFF_1(
.clk(clk),
.R(R[1]),
.E(E),
.L(L),
.w(LEDR[2]),
.Q(LEDR[1])
);
MUXDFF MUXDFF_0(
.clk(clk),
.R(R[0]),
.E(E),
.L(L),
.w(LEDR[1]),
.Q(LEDR[0])
);
endmodule
module MUXDFF (
input clk,
input R,
input E,
input L,
input w,
output Q
);
wire D0,D1;
assign D0 = E?w:Q;
assign D1 = L?R:D0;
always@(posedge clk)
Q <= D1;
endmodule
六、三输入查找表
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output Z );
reg [7:0] q;
reg [2:0] a;
assign a={A,B,C};
always@(posedge clk)
if(!enable)
q<=q;
else begin
q[0]<=S;
q[1]<=q[0];
q[2]<=q[1];
q[3]<=q[2];
q[4]<=q[3];
q[5]<=q[4];
q[6]<=q[5];
q[7]<=q[6];
end
always@(*)begin
case(a)
3'b000:Z=q[0];
3'b001:Z=q[1];
3'b010:Z=q[2];
3'b011:Z=q[3];
3'b100:Z=q[4];
3'b101:Z=q[5];
3'b110:Z=q[6];
3'b111:Z=q[7];
default:Z=q[0];
endcase
end
endmodule
七、Rule90
Rule90 - HDLBitshttps://hdlbits.01xz.net/wiki/Rule90
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q );
always@(posedge clk)
if(load)
q<=data;
else
q<={1'b0,q[511:1]}^{q[510:0],1'b0};
endmodule
八、Moore FSM
Fsm1s - HDLBitshttps://hdlbits.01xz.net/wiki/Fsm1s
// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
input clk;
input reset; // Synchronous reset to state B
input in;
output out;//
reg out;
// Fill in state name declarations
parameter B=0;
parameter A=1;
reg present_state, next_state;
always@(posedge clk)
if(reset)
present_state <= B;
else
present_state <= next_state;
always@(*)begin
case(present_state)
A:
if(in) next_state =A;
else next_state = B;
B:
if(in) next_state =B;
else next_state = A;
default:next_state =B;
endcase
end
assign out = (present_state==B);
endmodule
九、Fsm3onehot
module top_module(
input in,
input [3:0] state,
output [3:0] next_state,
output out); //
parameter A=0, B=1, C=2, D=3;
// State transition logic: Derive an equation for each state flip-flop.
assign next_state[A] = (state[A]&&~in)|(state[C]&&~in);
assign next_state[B] = (state[B]&& in)|(state[D]&&in)|(state[A]&&in);
assign next_state[C] = (state[B]&&~in)|(state[D]&&~in);
assign next_state[D] = (state[C]&& in);
// Output logic:
assign out = state[D];
endmodule
十、Fsm ps2
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
parameter BYTE1= 4'b0001;
parameter BYTE2= 4'b0010;
parameter BYTE3= 4'b0100;
parameter DONE = 4'b1000;
reg [4:0] state,next_state;
always@(posedge clk)begin
if(reset)
state <= BYTE1;
else
state <= next_state;
end
always@(*)begin
case(state)
BYTE1:begin
if(in[3]==1'b1) next_state = BYTE2;
else next_state = BYTE1;
end
BYTE2:next_state = BYTE3;
BYTE3:next_state = DONE;
DONE:begin
if(in[3] == 1'b1) next_state = BYTE2;
else next_state = BYTE1;
end
default:next_state = BYTE1;
endcase
end
assign done=(state==DONE);
endmodule
十一、 Fsm ps2data
这道题在输出字节数据之前,使用移位寄存器进行的了缓存。
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done); //
parameter BYTE1= 4'b0001;
parameter BYTE2= 4'b0010;
parameter BYTE3= 4'b0100;
parameter DONE = 4'b1000;
reg [4:0] state,next_state;
reg [7:0] byte1,byte2,byte3;
always@(posedge clk)begin
if(reset)
state <= BYTE1;
else
state <= next_state;
end
always@(*)begin
case(state)
BYTE1:begin
if(in[3]==1'b1) next_state = BYTE2;
else next_state = BYTE1;
end
BYTE2:next_state = BYTE3;
BYTE3:next_state = DONE;
DONE:begin
if(in[3] == 1'b1) next_state = BYTE2;
else next_state = BYTE1;
end
default:next_state = BYTE1;
endcase
end
always@(posedge clk)begin
byte1 <= in;
byte2 <= byte1;
byte3 <= byte2;
end
assign done=(state==DONE);
assign out_bytes=(state == DONE)?{byte3,byte2,byte1}:0;
endmodule
十二、 Fsm serialdata
这一道题写了两天,犯的错真的是千奇百怪........在这里记录一下参考资料和我的代码。
[HDLBits] Fsm serialdata-CSDN博客
Fsm serial 有限状态机_fsm serial-CSDN博客
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
reg [4:0] state,next_state;
// Use FSM from Fsm_serial
// 0:空闲状态
// 1:起始低电平信号
// 2~9:数据位
// 10:停止位
// 11:校验状态
always@(*)begin
case(state)
0:next_state =in?0:1;
1:next_state =2;
2:next_state =3;
3:next_state =4;
4:next_state =5;
5:next_state =6;
6:next_state =7;
7:next_state =8;
8:next_state =9;
9:next_state =in?10:11;
10:next_state =in?0:1;
11:next_state =in?0:11;
default:next_state=0;
endcase
end
always@(posedge clk)begin
if(reset)
state <=0;
else
state<=next_state;
end
assign done=(state==10);
// New: Datapath to latch input bits.
always@(posedge clk)begin
case(state)
1:out_byte[0]<=in;
2:out_byte[1]<=in;
3:out_byte[2]<=in;
4:out_byte[3]<=in;
5:out_byte[4]<=in;
6:out_byte[5]<=in;
7:out_byte[6]<=in;
8:out_byte[7]<=in;
default out_byte<=out_byte;
endcase
end
endmodule
十三、Fsm serialdp
这道题需要注意第9位bit是0还是1,in=0要求奇校验,in=1要求偶校验。
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
// Modify FSM and datapath from Fsm_serialdata
parameter IDLE = 4'd0;
parameter START = 4'd1;
parameter DATA1 = 4'd2;
parameter DATA2 = 4'd3;
parameter DATA3 = 4'd4;
parameter DATA4 = 4'd5;
parameter DATA5 = 4'd6;
parameter DATA6 = 4'd7;
parameter DATA7 = 4'd8;
parameter DATA8 = 4'd9;
parameter ODD_check = 4'd10;
parameter STOP = 4'd11;
parameter WAIT = 4'd12;
// New: Add parity checking.
reg [3:0] state,next_state;
always@(posedge clk)begin
if(reset)
state<=IDLE;
else
state<=next_state;
end
always@(*)begin
case(state)
IDLE: next_state=in?IDLE:START;
START: next_state=DATA1;
DATA1: next_state=DATA2;
DATA2: next_state=DATA3;
DATA3: next_state=DATA4;
DATA4: next_state=DATA5;
DATA5: next_state=DATA6;
DATA6: next_state=DATA7;
DATA7: next_state=DATA8;
DATA8: next_state=ODD_check;
ODD_check: begin
if(in)
next_state = STOP;
else
next_state = WAIT;
end
STOP: next_state=in?IDLE:START;
WAIT: next_state=in?IDLE:WAIT;
default: next_state=IDLE;
endcase
end
always@(posedge clk)begin
case(state)
START:out_byte[0]<=in;
DATA1:out_byte[1]<=in;
DATA2:out_byte[2]<=in;
DATA3:out_byte[3]<=in;
DATA4:out_byte[4]<=in;
DATA5:out_byte[5]<=in;
DATA6:out_byte[6]<=in;
DATA7:out_byte[7]<=in;
endcase
end
//进行奇偶校验的相应状态
wire p_state;
assign p_state=(state==START)|(state==DATA1)|(state==DATA2)|(state==DATA3)|(state==DATA4)|(state==DATA5)|(state==DATA6)|(state==DATA7);
//奇偶校验输入信号
wire in_p;
assign in_p=p_state∈
//奇偶校验重置信号
wire reset_p;
assign reset_p=(reset|(state==IDLE)|(state==STOP));
//奇偶校验输出信号
wire odd;
//奇偶校验模块例化
parity parity(
.clk(clk),
.reset(reset_p),
.in(in_p),
.odd(odd)
);
//输入缓存
reg [1:0]in_reg;
//在state==STOP时输出Done信号时,校验位在2个时钟周期之前就输入了,所以将校验位延迟两个时钟周期,即in_reg[1]
always@(posedge clk)begin
in_reg[0] <= in;
in_reg[1] <= in_reg[0];
end
//第9位校验位为in=1时,为偶校验;in=0时,为奇校验;
//偶校验:传送数据有偶数个1,则传输数据成功
//奇校验:传送数据有奇数个1,则传输数据成功
//odd=0时,传输数据位有偶数个1
//odd=1时,传输数据位有奇数个1
//(state==STOP)&(!odd)&in_reg 偶校验,偶数个1则拉高
//(state==STOP)&odd&in_reg 奇校验,奇数个1则拉高
//assign done = in_reg;
assign done=in_reg[1]?((state==STOP)&(!odd)&in_reg[1]):((state==STOP)&odd&(~in_reg[1]));
endmodule
十四、Exams/ece241 2013 q8
我很想问出题人,为啥一个3bit的序列检测器,不先写简单的四状态机,而上来就搞进阶的三状态机?默认我们学过吗?
参考:
序列检测器(两种设计方法和四种检测模式|verilog代码|Testbench|仿真结果)_使用移位寄存器设计序列检测器-CSDN博客
hdlbits-Exams/ece241 2013 q8 - 江左子固 - 博客园 (cnblogs.com)
Exams/ece241 2013 q8 - HDLBits (01xz.net)
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output z );
parameter IDLE =4'd0;
parameter ONE =4'd1;
parameter TWO =4'd2;
parameter THREE =4'd0;
reg [3:0] state,next_state;
always@(posedge clk or negedge aresetn)
if(!aresetn)
state <= ONE;
else
state <= next_state;
always@(*)begin
case(state)
ONE: next_state=x?TWO:ONE;
TWO: next_state=x?TWO:THREE;
THREE: next_state=x?TWO:ONE;
default:next_state = ONE;
endcase
end
assign z = (state==THREE)?x:0;
endmodule
十五、Exams/ece241 2014 q5b
题目: Exams/ece241 2014 q5b - HDLBits
了解与 Exams/ece241 2014 q5a在数据输出端的区别,学习Moore、Mealy状态机的两者区别。
参考:
【状态机设计】Moore、Mealy状态机、三段式、二段式、一段式状态机书写规范-CSDN博客
Verilog HDLBits 第十九期:3.2.9 Finite State Machines(3.2.5.21-3.2.5.26)_verilog q5a-CSDN博客
十六、 Exams/2014 q3fsm
代码参考:
Exams/2014 q3fsm_exams/2014_q3fsm-CSDN博客
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter s0=4'd0;
parameter s1=4'd1;
parameter s2=4'd2;
parameter s3=4'd3;
reg[1:0] state,next_state;
reg[1:0] cnt;
always@(posedge clk)begin
if(reset)
state<=s0;
else
state<=next_state;
end
always@(posedge clk)begin
case(state)
s0:cnt=0;
s1:cnt=w;
s2:cnt=cnt+w;
s3:cnt=cnt+w;
endcase
end
always@(*)begin
case(state)
s0:next_state=s?s1:s0;
s1:next_state=s2;
s2:next_state=s3;
s3:next_state=s1;
default:next_state=s1;
endcase
end
always@(*)begin
case(state)
s1:z = (cnt==2)?1:0;
default:z=0;
endcase
end
endmodule