verilog 常见模块编程(持续更新)

发布于:2022-11-28 ⋅ 阅读:(328) ⋅ 点赞:(0)

目录

1、四选一多路器

2、异步复位串联触发器

3、奇偶校验

4、移位运算与乘法

5、拆分与运算

6、 多功能数据处理器

7、generater...for语句简化代码

9、使用子模块实现三输入数的大小比较

10、函数

11、组合逻辑

12、超前进位加法器

13、优先编码器

14、3-8译码器

15、四选一多路选择器

16、 数据选择器实现逻辑电路

17、三段式有限状态机,mealy

18、三段式状态机


1、四选一多路器

`timescale 1ns/1ns
module mux4_1(
input [1:0]d1,d2,d3,d0,
input [1:0]sel,
output[1:0]mux_out
);
//*************code***********//
    reg[1:0] mux_out_reg;
    assign mux_out = mux_out_reg;
    always@(*) begin
        case(sel)
            2'b00: mux_out_reg = d3;
            2'b01: mux_out_reg = d2;
            2'b10: mux_out_reg = d1;
            2'b11: mux_out_reg = d0;
            default:
            mux_out_reg = d3;
            endcase
    end
//*************code***********//
endmodule

在使用例化模块进行编程时经常会遇到这两种类型的数据相连接的情况
 
 wire型数据:在assign左侧被赋值;
 
reg型数据:在always@的左侧被赋值;
 
两者均能在assign和always@的右侧被使用。
    */

2、异步复位串联触发器

`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q  
);
//*************code***********//
//T触发器如果是输入1,则上一周期输出取反
    reg q1;
    always@(posedge clk or rst)
    begin
        if(!rst) begin
            q1<=1'b0;
        end
        else begin
             if(data)
                q1<=~q1;
             end
    end
     
    always@(posedge clk or rst)
    begin
        if(!rst) begin
            q<=1'b0;
        end
        else begin
            if(q1)
                q<=~q;
             end
    end
//*************code***********//
endmodule

3、奇偶校验

`timescale 1ns/1ns
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//
assign check=sel?^bus:~^bus;

//*************code***********//
endmodule

4、移位运算与乘法

        利用有限状态机:初状态也加入状态,然后在4个状态中循环,always@(state) 中不是always@(*),就会保持当时的输入状态循环,不然就是实施的采集输入的d。

`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//
parameter T0=3'b000,T1=3'b001,T3=3'b010,T7=3'b011,T8=3'b100;
    
    reg [7:0]din;
    reg [3:0]state;
    reg [3:0]next_state;
    reg rst_n,rff1;
    
    always@(posedge clk or rst) begin
        if(!rst)
            {rst_n,rff1}<=2'b0;
        else
            {rst_n,rff1}<={rff1,1'b1};
    end
    
    always@(posedge clk or rst_n)begin
        if(!rst_n)
            state<=0;
        else
            state<=next_state;
    end
    
    always@(state) begin
        case(state)
            T0:begin
                out<=0;
                input_grant<=0;
                next_state<=T1;
            end  
            
            T1:begin
                din<=d;
                next_state<=T3;
                out<=d;
                input_grant<=1;
            end
              
            T3:begin
                next_state<=T7;
                out<=din+{din,1'b0};
                input_grant<=0;
            end
            
            T7:begin
                next_state<=T8;
                out<=din+{din,1'b0}+{din,2'b0};
                input_grant<=0;
            end
            
            T8:begin
                next_state<=T1;
                out<={din,3'b0};
                input_grant<=0;
            end 
            default:next_state<=T0;
        endcase
    end
            
//*************code***********//
endmodule

 

 rff1连接高电平,

5、拆分与运算

`timescale 1ns/1ns

module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,

output [4:0]out,
output validout
);
//*************code***********//
    reg [3:0]num1,num2,num3,num4;
    reg [4:0]out_t;
    reg validout_t;
    
    always@(posedge clk or rst) begin
        if(!rst) begin
            out_t<=0;
            validout_t<=0;
        end
        else begin
        case(sel)
        0:begin
            num1<=d[3:0];
            num2<=d[7:4];
            num3<=d[11:8];
            num4<=d[15:12];
            out_t<=0;
            validout_t<=0;
        end
        1:begin
            out_t<=num1+num2;
            validout_t<=1;
        end
        2:begin
            out_t<=num1+num3;
            validout_t<=1;
        end
        3:begin
            out_t<=num1+num4;
            validout_t<=1;
        end
        endcase
        end
    end

assign validout=validout_t;
assign out=out_t; 
                
//*************code***********//
endmodule

6、 多功能数据处理器

`timescale 1ns/1ns
module data_select(
	input clk,
	input rst_n,
	input signed[7:0]a,
	input signed[7:0]b,
	input [1:0]select,
	output reg signed [8:0]c
);
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            c<=0;
        end
        else begin
        case(select)
                0:begin
                    c<=a;
                end
                1:begin
                    c<=b;
                end
                2:begin
                    c<=a+b;
                end
                3:begin
                    c<=a-b;
                end
         endcase           
         end
    end            
endmodule

注意:negedge rst_n并不会触发;

  • 改成异步复位同步释放如下:

rst_n为低,执行{rst,rff1}<=2'b0;第二个always中的rst动作,输出异步复位值。0

rst_n释放为高,执行{rst,rff1}<={rff1,1'b1};rst依然为低,rff1为高,当posedge来临时,此时rst_n为高,再次执行{rst,rff1}<={rff1,1'b1}; rst为高,第二个always中的rst动作为高,输出非复位的结果。

`timescale 1ns/1ns
module data_select(
	input clk,
	input rst_n,
	input signed[7:0]a,
	input signed[7:0]b,
	input [1:0]select,
	output reg signed [8:0]c
);
    
    reg rst,rff1;
    always@(posedge clk or rst_n) begin
        if(!rst_n)
            {rst,rff1}<=2'b0;
        else
            {rst,rff1}<={rff1,1'b1};
    end
    
    always@(posedge clk or rst) begin
        if(!rst) begin
            c<=0;
        end
        else begin
        case(select)
                0:begin
                    c<=a;
                end
                1:begin
                    c<=b;
                end
                2:begin
                    c<=a+b;
                end
                3:begin
                    c<=a-b;
                end
         endcase           
         end
    end            
endmodule

7、generater...for语句简化代码

注意:1、genvar一个参数,2、然后for循环的写法,3、起个名字

`timescale 1ns/1ns
module gen_for_module( 
    input [7:0] data_in,
    output [7:0] data_out
);

    genvar i;
    generate for(i=0;i<8;i=i+1) 
        begin:bit_reverse//起个名字
            assign data_out[i]=data_in[7-i];
        end
    endgenerate
endmodule

9、使用子模块实现三输入数的大小比较

`timescale 1ns/1ns
module main_mod(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,
	input [7:0]c,
	
	output [7:0]d
);
    wire [7:0] temp0,temp1;
    sub_mod sd0(.a(a),.b(b),.c(temp0),.clk(clk),.rst_n(rst_n));
    sub_mod sd1(.a(a),.b(c),.c(temp1),.clk(clk),.rst_n(rst_n));
    sub_mod sd2(.a(temp0),.b(temp1),.c(d),.clk(clk),.rst_n(rst_n));
    
endmodule

module sub_mod(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,
	output reg [7:0]c
);
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            c<=0;
        else
            c<=a>b?b:a;
    end
    
endmodule

10、函数

返回类型缺省就是reg类型的

`timescale 1ns/1ns
module function_mod(
	input [3:0]a,
	input [3:0]b,
	input clk,
    input rst_n,
	output [3:0]c,
	output [3:0]d
);


    assign c=big2sall(a);
    assign d=big2sall(b);
    
    function [3:0]big2sall;
        input [3:0]datain;
        integer i;
        for (i=0;i<4;i=i+1)    
            begin:re
                big2sall[i]=datain[3-i];
        end
    endfunction
        
endmodule

11、组合逻辑

注意:找到使Y输出1的条件,多个条件满足时用逻辑并,注意用符号

`timescale 1ns/1ns

module comparator_4(
	input		[3:0]       A   	,
	input	   [3:0]		B   	,
 
 	output	 wire		Y2    , //A>B
	output   wire        Y1    , //A=B
    output   wire        Y0      //A<B
);

    assign Y2=(A[3]>B[3]) | ((A[3]==B[3])&&(A[2]>B[2])) |((A[3]==B[3])&&(A[2]==B[2])&&(A[1]>B[1]))| ((A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]>B[0]));
    assign Y1=(A[3]==B[3])&&(A[2]===B[2])&&(A[1]==B[1])&&(A[0]==B[0]);
    assign Y0=(~Y2)&(~Y1);
 
endmodule

12、超前进位加法器

注意,加号用逻辑与表示

`timescale 1ns/1ns

module lca_4(
	input		[3:0]       A_in  ,
	input	    [3:0]		B_in  ,
    input                   C_1   ,
 
 	output	 wire			CO    ,
	output   wire [3:0]	    S
);
    
    wire [3:0]G;
    wire [3:0]P;
    
    assign G[0]=A_in[0]&B_in[0];  
    assign G[1]=A_in[1]&B_in[1]; 
    assign G[2]=A_in[2]&B_in[2]; 
    assign G[3]=A_in[3]&B_in[3]; 
    
    assign P[0]=A_in[0]&B_in[0];  
    assign P[1]=A_in[1]&B_in[1]; 
    assign P[2]=A_in[2]&B_in[2]; 
    assign P[3]=A_in[3]&B_in[3]; 
    
    wire [3:0]C;
    
    assign S[0]=P[0]^C_1;
    assign S[1]=P[1]^C[0];
    assign S[2]=P[2]^C[1];
    assign S[3]=P[3]^C[2];
    assign CO=C[3];
    
    assign C[0]=G[0] |P[0]&C_1;
    assign C[1]=G[1] |P[1]&C[0];
    assign C[2]=G[2] |P[2]&C[1];
    assign C[3]=G[3] |P[3]&C[2];
    
endmodule

 或这样:

`timescale 1ns/1ns

module lca_4(
	input		[3:0]       A_in  ,
	input	    [3:0]		B_in  ,
    input                   C_1   ,
 
 	output	 wire			CO    ,
	output   wire [3:0]	    S
);
    
    assign {CO,S}=A_in+B_in+C_1;
    
endmodule

13、优先编码器

注意:? 为不管是0还是1

`timescale 1ns/1ns
module encoder_0(
   input      [8:0]         I_n   ,
   
   output reg [3:0]         Y_n   
);
    always@(*) begin
        casex (I_n)
            9'b1_1111_1111: Y_n = 4'b1111;
            9'b0_xxxx_xxxx: Y_n = 4'b0110;
            9'b1_0xxx_xxxx: Y_n = 4'b0111;
            9'b1_10xx_xxxx: Y_n = 4'b1000;
            9'b1_110x_xxxx: Y_n = 4'b1001;
            9'b1_1110_xxxx: Y_n = 4'b1010;
            9'b1_1111_0xxx: Y_n = 4'b1011;
            9'b1_1111_10xx: Y_n = 4'b1100;
            9'b1_1111_110x: Y_n = 4'b1101;
            9'b1_1111_1110: Y_n = 4'b1110;
            default: Y_n = 4'b0000;
        endcase
    end
endmodule

关于casecasezcasex,三者都是可以综合的。case进行全等匹配,casez忽略?z对应的位进行匹配,casex忽略x?z对应的位进行匹配。

比如:输入信号9'b0_1001_0100,第一位匹配上,第二位与x匹配必为1,第三位与x匹配必为1....,全匹配上了之后,就选择这个输出(9'b0_xxxx_xxxx: Y_n = 4'b0110;)

14、3-8译码器

  • 加一个组合逻辑②请使用3-8译码器①和必要的逻辑门实现函数L=(~A)·C+A·B

  

`timescale 1ns/1ns


module decoder_38(
   input             E1_n   ,
   input             E2_n   ,
   input             E3     ,
   input             A0     ,
   input             A1     ,
   input             A2     ,
   
   output wire       Y0_n   ,  
   output wire       Y1_n   , 
   output wire       Y2_n   , 
   output wire       Y3_n   , 
   output wire       Y4_n   , 
   output wire       Y5_n   , 
   output wire       Y6_n   , 
   output wire       Y7_n   
);
wire E ;
assign E = E3 & ~E2_n & ~E1_n;
assign  Y0_n = ~(E & ~A2 & ~A1 & ~A0);
assign  Y1_n = ~(E & ~A2 & ~A1 &  A0);
assign  Y2_n = ~(E & ~A2 &  A1 & ~A0);
assign  Y3_n = ~(E & ~A2 &  A1 &  A0);
assign  Y4_n = ~(E &  A2 & ~A1 & ~A0);
assign  Y5_n = ~(E &  A2 & ~A1 &  A0);
assign  Y6_n = ~(E &  A2 &  A1 & ~A0);
assign  Y7_n = ~(E &  A2 &  A1 &  A0);
     
endmodule

module decoder0(
   input             A     ,
   input             B     ,
   input             C     ,
   
   output wire       L
);
                  
wire       Y0_n   ;  
wire       Y1_n   ; 
wire       Y2_n   ; 
wire       Y3_n   ; 
wire       Y4_n   ; 
wire       Y5_n   ; 
wire       Y6_n   ; 
wire       Y7_n   ;

decoder_38 U0(
   .E1_n   (1'b0),
   .E2_n   (1'b0),
   .E3     (1'b1),
   .A0     (C),
   .A1     (B),
   .A2     (A),
  
   .Y0_n   (Y0_n),  
   .Y1_n   (Y1_n), 
   .Y2_n   (Y2_n), 
   .Y3_n   (Y3_n), 
   .Y4_n   (Y4_n), 
   .Y5_n   (Y5_n), 
   .Y6_n   (Y6_n), 
   .Y7_n   (Y7_n)
);

assign L = ~(Y1_n & Y3_n & Y6_n & Y7_n);

endmodule

15、四选一多路选择器

 

16、 数据选择器实现逻辑电路

表达式中要的留下,不要的去掉。

`timescale 1ns/1ns

module data_sel(
   input             S0     ,
   input             S1     ,
   input             D0     ,
   input             D1     ,
   input             D2     ,
   input             D3     ,
   
   output wire        Y    
);

assign Y = ~S1 & (~S0&D0 | S0&D1) | S1&(~S0&D2 | S0&D3);
     
endmodule

module sel_exp(
   input             A     ,
   input             B     ,
   input             C     ,
   
   output wire       L            
);
    data_sel d1(.S0(A),.S1(B),.D0(0),.D1(~C),.D2(C),.D3(1),.Y(L));
endmodule

17、三段式有限状态机,mealy

`timescale 1ns/1ns

module seq_circuit(
      input                A   ,
      input                clk ,
      input                rst_n,
 
      output   wire        Y   
);
    parameter s00=2'b00,s01=2'b01,s10=2'b10,s11=2'b11;
    reg [1:0]state,next_state;
    reg yy;
    assign Y=yy;
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            state<=0;
        else
            state<=next_state;
    end
    
    always@(*) begin
        case(state)
        s00:begin
            if(A==0)
                next_state<=s01;
            else
                next_state<=s11;
        end
            
        s01:begin
            if(A==0)
                next_state<=s10;
            else
                next_state<=s00;
        end
            
        s10:begin
            if(A==0)
                next_state<=s11;
            else
                next_state<=s01;
        end
            
        s11:begin
            if(A==0)
                next_state<=s00;
            else
                next_state<=s10;
        end
        default:next_state<=s00;
        endcase
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            yy<=0;
        else begin
            case(next_state)
        s00:yy<=0;
        
        s01:yy<=0;
            
        s10:yy<=0;
        
        s11:yy<=1;
        endcase
        end
    end
endmodule

 错误方式:主要是第三段,A无论是不是1,输出都是0

`timescale 1ns/1ns

module seq_circuit(
      input                A   ,
      input                clk ,
      input                rst_n,
 
      output   wire        Y   
);
    parameter s00=2'b00,s01=2'b01,s10=2'b10,s11=2'b11;
    reg [1:0]state,next_state;
    reg yy;
    assign Y=yy;
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            state<=0;
        else
            state<=next_state;
    end
    
    always@(*) begin
        case(state)
        s00:begin
            if(A==0)
                next_state<=s01;
            else
                next_state<=s11;
        end
            
        s01:begin
            if(A==0)
                next_state<=s10;
            else
                next_state<=s00;
        end
            
        s10:begin
            if(A==0)
                next_state<=s11;
            else
                next_state<=s01;
        end
            
        s11:begin
            if(A==0)
                next_state<=s00;
            else
                next_state<=s10;
        end
        default:next_state<=s00;
        endcase
    end
    
   always@(state or A) begin
        case(state)
        s00:if(A==0)
                yy<=0;
            else
                yy<=0;
        end
         
        s01:if(A==0)
                yy<=0;
            else
                yy<=0;
        end
             
        s10:if(A==0)
                yy<=0;
            else
                yy<=0;
        end
         
        s11:if(A==0)
                yy<=1;
            else
                yy<=1;
        end
        endcase
    end
endmodule

18、三段式状态机

次态逻辑

状态记忆

输出逻辑

`timescale 1ns/1ns

module seq_circuit(
   input                C   ,
   input                clk ,
   input                rst_n,
 
   output   wire        Y   
);
    reg yy;
    reg [1:0]state,next_state;
    parameter s00=2'b00,s01=2'b01,s10=2'b10,s11=2'b11;
    
    assign C=yy;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            state<=0;
        else
            state<=next_state;
    end
    
    always@(*) begin
        case(state)
            s00:begin
                if(C==1)
                    next_state<=s01;
                else
                    next_state<=s00;
            end
                
            s01:begin
                if(C==1)
                    next_state<=s01;
                else
                    next_state<=s11;
            end
            
            s10:begin
                if(C==1)
                    next_state<=s10;
                else
                    next_state<=s00;
            end
            
            s11:begin
                if(C==1)
                    next_state<=s10;
                else
                    next_state<=s11;
            end
            default: next_state<=s00;
        endcase
    end
          

    always@(*) begin
        case(state)
            s00:yy<=0;    
            s01:yy<=0;
            s10:begin
                if(C==1)
                   yy<=1;
                else
                   yy<=0;
            end
            s11:yy<=0;
        endcase
    end         
endmodule

注意:第二段是组合逻辑,第三段可组合case(state)可时序case(next_state)

最后一句代码还是很重要的。

`timescale 1ns/1ns

module seq_circuit(
   input                C   ,
   input                clk ,
   input                rst_n,
 
   output   wire        Y   
);
    
    reg [1:0] curr_state;
    reg [1:0] next_state;
    // one step
    always @ (posedge clk&nbs***bsp;negedge rst_n)
        begin
            if( ~rst_n ) begin
                curr_state <= 2'b00;
            end 
            else begin
                curr_state <= next_state;
            end 
        end 
    
    // two step
    always @ (*)
        begin
            case(curr_state)
                2'b00 : next_state = (C == 1'b1) ? 2'b01 : 2'b00;
                2'b01 : next_state = (C == 1'b1) ? 2'b01 : 2'b11;
                2'b10 : next_state = (C == 1'b1) ? 2'b10 : 2'b00;
                2'b11 : next_state = (C == 1'b1) ? 2'b10 : 2'b11;
                default : next_state = 2'b00;
            endcase
        end
    
    assign Y = ((curr_state == 2'b11) | ((curr_state == 2'b10)&&(C == 1'b1)) )? 1 : 0;
    
endmodule

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到