Verilog学习笔记

一、生存锁存器

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_q4bicon-default.png?t=N7T8https://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

六、三输入查找表

https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q12icon-default.png?t=N7T8https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q12

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 - HDLBitsicon-default.png?t=N7T8https://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 - HDLBitsicon-default.png?t=N7T8https://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

Fsm ps2data - HDLBits

这道题在输出字节数据之前,使用移位寄存器进行的了缓存。

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

Fsm serialdata - HDLBits

这一道题写了两天,犯的错真的是千奇百怪........在这里记录一下参考资料和我的代码。

[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&in;          
   //奇偶校验重置信号
    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

 

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值