verilog牛客网刷题代码汇总

博客首页:安静到无声

⛳️ 欢迎关注 ❤️ 点赞 收藏 ✏️ 留言

系列专栏:Verilog学习

由于HDLBits刷题并不方便,在这里给大家强烈推荐一款嵌入式硬件模拟面试、刷题神器——牛客网( [ Verilog,C等基础,更有一些硬件知识点拨

❤️ 点击免费注册和我一起刷题吧

verilog牛客网刷题代码汇总_第1张图片

目录

  • 1. Verilog快速入门
    • 1. 基础语法
      • VL1 四选一多路器
      • VL2 异步复位的串联T触发器
      • LV3 奇偶校验
      • VL4 移位运算与乘法
      • LV5 位拆分与运算
      • VL6 多功能数据处理器
      • VL7 求两个数的差值
      • VL8 使用generate…for语句简化代码
      • VL9 使用子模块实现三输入数的大小比较
      • VL10 使用函数实现数据大小端转换
    • 02 组合逻辑
      • VL11 4位数值比较器电路
      • VL12 4bit超前进位加法器电路
      • VL13 优先编码器电路①
      • VL14 用优先编码器①实现键盘编码电路
      • VL15 优先编码器Ⅰ
      • VL16 使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器
    • 03 时序逻辑
      • VL21 根据状态转移表实现时序电路
      • VL22 根据状态转移图实现时序电路
      • VL23 ROM的简单实现
      • VL24 边沿检测
  • 2 Verilog进阶挑战
    • 01 序列检测
      • VL25 输入序列连续的序列检测
      • VL26 含有无关项的序列检测
      • VL27 不重叠序列检测
      • VL28 输入序列不连续的序列检测
    • 02 时序逻辑
      • VL29 信号发生器
      • VL30 数据串转并电路
      • VL31 数据累加输出
      • VL32 非整数倍数据位宽转换24to128
      • VL33 非整数倍数据位宽转换8to12
      • VL34 整数倍数据位宽转换8to16
      • VL35 状态机-非重叠的序列检测
      • VL36 状态机-重叠序列检测
      • VL37 时钟分频(偶数)
      • VL38 自动贩售机1
      • VL39 自动贩售机2
      • VL40 占空比50%的奇数分频
      • VL41 任意小数分频
      • VL42 无占空比要去的奇数分频
      • VL43 根据状态转移写状态机-三段式
      • VL44 根据状态转移写状态机-二段式
    • 03 跨时钟域传输
      • VL45 异步FIFO
      • VL46 同步FIFO
      • VL47 格雷码计数器
      • VL48 多bit MUX同步器
      • VL49 脉冲同步电路
    • 04 计数器
      • VL50 简易秒表
      • VL51 可置位计数器
      • VL52 加减计数器
    • 05 存储器
      • VL53 单端口RAM
      • VL54 RAM的简单实现
    • 06 综合
      • VL55 Johnson Counter
      • VL56 流水线乘法器
      • VL57 交通灯
      • VL58 游戏机计费程序

1. Verilog快速入门

1. 基础语法

VL1 四选一多路器

`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]         state                      ;

always @(*) begin
    case (sel)
        2'b00:state = d3;
        2'b01:state = d2;
        2'b11:state = d0;
        2'b10:state = d1;
        default:state = d3;
    endcase
end
assign mux_out = state;
*/


assign mux_out = sel[1]==1?(sel[0]==1?d0:d1):(sel[0]==1?d2:d3);
//*************code***********//
endmodule

VL2 异步复位的串联T触发器

VL2 异步复位的串联T触发器

`timescale 1ns/1ns
module Tff_2 (
    input  wire                         data, clk, rst             ,
    output reg                          q                           
);

reg                                     data1                      ;
always @(posedge clk or negedge rst) begin
    if(!rst) begin
        data1 <= 1'b0;
    end else begin
        if (data) begin
            data1 <= !data1;
        end
        else begin
            data1 <= data1;
        end
    end
    
end

always @(posedge clk or negedge rst) begin
    if(!rst) begin
        q <= 1'b0;
    end else begin
        if (data1) begin
            q <= !q;
        end else begin
            q <= q;
        end
    end
    
end

endmodule

LV3 奇偶校验

LV3 奇偶校验

`timescale 1ns/1ns
module odd_sel(
    input              [  31:0]         bus                        ,
    input                               sel                        ,
    output                              check                       
);
//*************code***********//
reg state;

always @(*) begin
    case (sel)
        1'b1:
            if(^bus == 1) begin
                state = 1;
            end
            else begin
                state = 0;
            end
        1'b0:
            if (^bus == 0) begin
                state = 1;
            end 
            else begin
                state = 0;
            end
        default: state = 0;

    endcase
end
assign check = state;


endmodule

VL4 移位运算与乘法

VL4 移位运算与乘法

`timescale 1ns/1ns

module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);

reg [1:0] state;
reg [7:0] din;


always @(posedge clk or negedge rst) begin
    if(!rst)begin
        out <= 11'b0;
        state <= 2'b00;
        input_grant <= 0;
        din <= 0;
    end    
    else begin
        case (state)
            2'b00:begin
                input_grant <= 1;
                din <= d;
                out <= d;
                //out <= (din<<2) - din;
                state <= 2'b01;
            end
            2'b01: begin
                out <= (din<<2) - din;
                input_grant <= 0;
                state <= 2'b10;
            end
            2'b10:begin
                out <= (din<<3) - din; 
                input_grant <= 0;
                state  <= 2'b11;
            end 
            2'b11: begin
                out <= (din<<3);
                input_grant <= 0;
                state <= 2'b00;
            end
            default:begin
                state <= 2'b00;
                input_grant <= 0;
            end
        endcase
    end
end

endmodule

LV5 位拆分与运算

LV5 位拆分与运算

`timescale 1ns/1ns

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

    output             [   4:0]         out                        ,
    output                              validout                    
);
reg                    [   4:0]         out_map                    ;
reg                    [  15:0]         d_luck                     ;
reg                                     validout_tmp               ;

always @(posedge clk or negedge rst) begin
    if(!rst)begin
        out_map <= 5'd0;
        validout_tmp<=1'b0;
    end
    else begin
        case (sel)
            2'd0: begin
                d_luck <= d;
                validout_tmp<=1'b0;
                out_map <=  5'd0;
            end
            2'd1: begin
                out_map <= d_luck[3:0] + d_luck[7:4];
                validout_tmp<=1'b1;
            end
            2'd2: begin
                out_map <= d_luck[3:0] + d_luck[11:8];
                validout_tmp<=1'b1;
            end
            2'd3: begin
                out_map <= d_luck[3:0] + d_luck[15:12];
                validout_tmp<=1'b1;
            end
            default:begin
                out_map <= 5'd0;
                validout_tmp<=1'b0;
            end
        endcase
    end

end
assign out = out_map;
assign validout = validout_tmp;
endmodule

VL6 多功能数据处理器

VL6 多功能数据处理器

`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)
    if(!rst_n)
        c <= 9'd0;
    else case(select)
    2'b00:  c <= a;
    2'b01:  c <= b;
    2'b10:  c <= a+b;
    2'b11:  c <= a-b;
    default: c <= 9'd0;
    endcase
  
endmodule

VL7 求两个数的差值

VL7 求两个数的差值

`timescale 1ns/1ns
module data_minus(
    input                               clk                        ,
    input                               rst_n                      ,
    input              [   7:0]         a                          ,
    input              [   7:0]         b                          ,

    output reg         [   8:0]         c                           
);

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        c <= 9'b0;
    end
    else begin
        if (a>b) begin
            c <= a - b;
        end
        else if(a <= b) begin
            c <= b - a;
        end
    end
end
endmodule

VL8 使用generate…for语句简化代码

VL8 使用generate…for语句简化代码

`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

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

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

`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]         m,n                        ;

sub_module sub_ab(
    .clk                               (clk                       ),
    .rst_n                             (rst_n                     ),
    .a                                 (a                         ),
    .b                                 (b                         ),
    .c                                 (m                         ) 
);


sub_module sub_mc(
    .clk                               (clk                       ),
    .rst_n                             (rst_n                     ),
    .a                                 (b                        ),
    .b                                 (c                         ),
    .c                                 (n                         ) 
);

sub_module sub_mn(
    .clk                               (clk                       ),
    .rst_n                             (rst_n                     ),
    .a                                 (m                        ),
    .b                                 (n                         ),
    .c                                 (d                         ) 
);


endmodule

module sub_module (
    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)begin
         c <= 8'd0;
    end else begin
        if(a <= b) begin
            c <= a;
        end
        else begin
            c <= b;
        end
    end
end

endmodule

VL10 使用函数实现数据大小端转换

VL10 使用函数实现数据大小端转换

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



function [3:0] reverse;
    input              [   3:0]         data_in                    ;
    integer i;
    begin
        for (i = 0;i<4 ;i = i + 1 ) begin
            reverse[i] = data_in[3-i];
        end
    end
endfunction

assign c = reverse(a);
assign d = reverse(b);

endmodule

02 组合逻辑

VL11 4位数值比较器电路

VL11 4位数值比较器电路

`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
);

reg Y2_tmp,Y1_tmp,Y0_tmp;

always @(A or B) begin
    if(A > B) begin
        Y2_tmp = 1;
        Y1_tmp = 0;
        Y0_tmp = 0;
    end
    else if (A < B) begin
        Y2_tmp = 0;
        Y1_tmp = 0;
        Y0_tmp = 1;       
    end
    else if(A == B) begin
        Y2_tmp = 0;
        Y1_tmp = 1;
        Y0_tmp = 0;       
    end
end
assign Y2 = Y2_tmp;
assign Y1 = Y1_tmp;
assign Y0 = Y0_tmp;

endmodule

VL12 4bit超前进位加法器电路

VL12 4bit超前进位加法器电路

`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_i;
wire [3:0] P_i;
wire [3:0] C_i; 


assign G_i = A_in & B_in;
assign P_i = A_in ^ B_in;



assign C_i[0] = G_i[0] | P_i[0]&C_1;
assign C_i[1] = G_i[1] | P_i[1]&G_i[0] | P_i[1]&P_i[0]&C_1;
assign C_i[2] = G_i[2] | P_i[2]&G_i[1] | P_i[2]&P_i[1]&G_i[0] | P_i[2]&P_i[1]&P_i[0]&C_1;
assign C_i[3] = G_i[3] | P_i[3]&G_i[2] | P_i[3]&P_i[2]&G_i[1] | P_i[3]&P_i[2]&P_i[1]&(G_i[0] | P_i[0]&C_1);


assign S[0] = P_i[0] ^ C_1;
assign S[1] = P_i[1] ^ C_i[0];
assign S[2] = P_i[2] ^ C_i[1];
assign S[3] = P_i[3] ^ C_i[2];

assign CO = C_i[3];

endmodule

VL13 优先编码器电路①

VL13 优先编码器电路①

`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'b1111;
endcase
end
endmodule

VL14 用优先编码器①实现键盘编码电路

VL14 用优先编码器①实现键盘编码电路

`timescale 1ns/1ns
module encoder_0(
    input              [   8:0]         I_n                        ,
   
    output reg         [   3:0]         Y_n                         
);

always @(*)begin
   casex(I_n)
      9'b111111111 : Y_n = 4'b1111;
      9'b0xxxxxxxx : Y_n = 4'b0110;
      9'b10xxxxxxx : Y_n = 4'b0111;
      9'b110xxxxxx : Y_n = 4'b1000;
      9'b1110xxxxx : Y_n = 4'b1001;
      9'b11110xxxx : Y_n = 4'b1010;
      9'b111110xxx : Y_n = 4'b1011;
      9'b1111110xx : Y_n = 4'b1100;
      9'b11111110x : Y_n = 4'b1101;
      9'b111111110 : Y_n = 4'b1110;
      default      : Y_n = 4'b1111;
   endcase
end
     
endmodule

module key_encoder(
    input              [   9:0]         S_n                        ,
 
    output wire        [   3:0]         L                          ,
    output wire                         GS                          
);

wire                   [   3:0]         L_tmp                      ;

encoder_0 encoder_0(
    .I_n                               (S_n[9:1]                  ),
    .Y_n                               (L_tmp                     ) 
);

assign L = ~L_tmp;
assign GS = ((L_tmp == 4'b1111) && (S_n[0] == 1)) ? 0: 1;


endmodule

VL15 优先编码器Ⅰ

VL15 优先编码器Ⅰ

`timescale 1ns/1ns
module encoder_83(
   input      [7:0]       I   ,
   input                  EI  ,
   
   output wire [2:0]      Y   ,
   output wire            GS  ,
   output wire            EO    
);
assign Y[2] = EI & (I[7] | I[6] | I[5] | I[4]);
assign Y[1] = EI & (I[7] | I[6] | ~I[5]&~I[4]&I[3] | ~I[5]&~I[4]&I[2]);
assign Y[0] = EI & (I[7] | ~I[6]&I[5] | ~I[6]&~I[4]&I[3] | ~I[6]&~I[4]&~I[2]&I[1]);

assign EO = EI&~I[7]&~I[6]&~I[5]&~I[4]&~I[3]&~I[2]&~I[1]&~I[0];

assign GS = EI&(I[7] | I[6] | I[5] | I[4] | I[3] | I[2] | I[1] | I[0]);
//assign GS = EI&(| I);
         
endmodule

VL16 使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器

VL16 使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器

`timescale 1ns/1ns
module encoder_83(
   input      [7:0]       I   ,
   input                  EI  ,
   
   output wire [2:0]      Y   ,
   output wire            GS  ,
   output wire            EO    
);
assign Y[2] = EI & (I[7] | I[6] | I[5] | I[4]);
assign Y[1] = EI & (I[7] | I[6] | ~I[5]&~I[4]&I[3] | ~I[5]&~I[4]&I[2]);
assign Y[0] = EI & (I[7] | ~I[6]&I[5] | ~I[6]&~I[4]&I[3] | ~I[6]&~I[4]&~I[2]&I[1]);

assign EO = EI&~I[7]&~I[6]&~I[5]&~I[4]&~I[3]&~I[2]&~I[1]&~I[0];

assign GS = EI&(I[7] | I[6] | I[5] | I[4] | I[3] | I[2] | I[1] | I[0]);
//assign GS = EI&(| I);
         
endmodule

module encoder_164(
   input      [15:0]      A   ,  //分为高8位和低8位
   input                  EI  ,  //使能表示有无按键按下
   
   output wire [3:0]      L   ,
   output wire            GS  ,
   output wire            EO    
);


wire [2:0]      Y_0;
wire [2:0]      Y_1;
wire            GS_0;
wire            EO_0;    
wire            GS_1;
wire            EO_1;   

encoder_83 u_0(
    .I(A[7:0]),
    .EI(EO_1),

    .Y(Y_0),
    .GS(GS_0),
    .EO(EO)
);

encoder_83 u_1(
    .I(A[15:8]),
    .EI(EI),
    
    .Y(Y_1),
    .GS(GS_1),
    .EO(EO_1)
);

assign GS = GS_1 | GS_0;
assign L[3] = GS_1;
assign L[2] = Y_1[2] | Y_0[2];
assign L[1] = Y_1[1] | Y_0[1];
assign L[0] = Y_1[0] | Y_0[0];

endmodule

03 时序逻辑

VL21 根据状态转移表实现时序电路

VL21 根据状态转移表实现时序电路

`timescale 1ns/1ns

module seq_circuit(
      input                A   ,
      input                clk ,
      input                rst_n,
 
      output   wire        Y   
);

reg q0,q1;

always@(posedge clk or negedge rst_n) begin 
    if(~rst_n) begin
        q1 <= 0;
    end   
    else begin;
        q1 <= (~A)&(~q1)&(q0) | (~A)&(q1)&(~q0) | (A)&(~q1)&(~q0) | (A)&(q1)&(q0);
    end
end

always@(posedge clk or negedge rst_n) begin 
    if(~rst_n) begin
        q0 <= 0;
    end   
    else begin;
        q0 <= ~q0;
    end
end

assign Y = q0 & q1;

endmodule

VL22 根据状态转移图实现时序电路

VL22 根据状态转移图实现时序电路

`timescale 1ns/1ns

module seq_circuit(
   input                C   ,
   input                clk ,
   input                rst_n,
 
   output   wire        Y   
);

//定义的状态类型
parameter            IDLE  = 2'b00 ;
parameter            GET1  = 2'b01 ;
parameter            GET2  = 2'b10 ;
parameter            GET3  = 2'b11 ;

//machine variable
reg [1:0]            st_next ;
reg [1:0]            st_cur ;

//(1) state transfer
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        st_cur      <= IDLE ;
    end
    else begin
        st_cur      <= st_next ;
    end
end

always @(*) begin
    case (st_cur)
        IDLE:begin
            if (C == 0) begin
                st_next <= IDLE;
            end
            else begin
                st_next <= GET1;
            end
        end

        GET1:begin
            if (C == 1) begin
                st_next <= GET1;
            end
            else begin
                st_next <= GET3;
            end
        end

        GET3:begin
            if (C == 0) begin
                st_next <= GET3;
            end
            else begin
                st_next <= GET2;
            end
        end

        GET2:begin
            if (C == 1) begin
                st_next <= GET2;
            end
            else begin
                st_next <= IDLE;
            end
        end
        default:st_next <= IDLE;
    endcase
end

reg Y_tmp;

always@(*) begin 
    case (st_cur)
        IDLE:begin
            Y_tmp <= 1'b0;
        end 
        GET1:begin
            Y_tmp <= 1'b0;
        end
        GET2:begin
            if (C == 1) begin
                Y_tmp <= 1'b1;
            end
            else begin
                Y_tmp <= 1'b0;
            end
        end        
        GET3:begin
            if (C == 0) begin
                Y_tmp <= 1'b1;
            end 
        end
        default: Y_tmp <= 1'b0;
    endcase
end


assign Y = Y_tmp;

endmodule

VL23 ROM的简单实现

VL23 ROM的简单实现

`timescale 1ns/1ns
module rom(
	input clk,
	input rst_n,
	input [7:0]addr,
	
	output [3:0]data
);

//开辟一个深度为8,位宽为4的空间
reg [3:0] rom_data [7:0];
assign data = rom_data[addr];
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        rom_data[0] <= 4'd0;
        rom_data[1] <= 4'd2;
        rom_data[2] <= 4'd4;
        rom_data[3] <= 4'd6;
        rom_data[4] <= 4'd8;
        rom_data[5] <= 4'd10;
        rom_data[6] <= 4'd12;
        rom_data[7] <= 4'd14;
    end   
    else begin
        rom_data[0] <= 4'd0;
        rom_data[1] <= 4'd2;
        rom_data[2] <= 4'd4;
        rom_data[3] <= 4'd6;
        rom_data[4] <= 4'd8;
        rom_data[5] <= 4'd10;
        rom_data[6] <= 4'd12;
        rom_data[7] <= 4'd14;        
    end
end
endmodule

VL24 边沿检测

VL24 边沿检测

`timescale 1ns/1ns
module edge_detect(
	input clk,
	input rst_n,
	input a,
	
	output reg rise,
	output reg down
);


reg a_tep;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        a_tep <= 1'b0;
    end
    else begin
        a_tep <= a;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        rise <= 1'b0;
        down <= 1'b0;
    end
    else begin
        if (a & ~a_tep) begin
            rise <= 1'b1;
            down <= 1'b0;
        end
        else if (~a & a_tep) begin
            rise <= 1'b0;
            down <= 1'b1;
        end
        else begin
            rise <= 1'b0;
            down <= 1'b0;
        end
    end
end

endmodule

2 Verilog进阶挑战

01 序列检测

VL25 输入序列连续的序列检测

VL25 输入序列连续的序列检测

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);

reg [7:0] state_cache;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        state_cache <= 8'b0;
        match <= 1'b0;
    end
    else begin
        state_cache <= {state_cache[6:0],a};
        if (state_cache == 8'b0111_0001) begin
            match <= 1'b1;
        end
        else begin
            match <= 1'b0;
        end
    end
end
  
endmodule

VL26 含有无关项的序列检测

VL26 含有无关项的序列检测

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);

reg [8:0] state_cache;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        state_cache <= 8'b0;
        match <= 1'b0;
    end
    else begin
        state_cache <= {state_cache[7:0],a};
        if (state_cache[8:6] == 3'b011 && state_cache[2:0] == 3'b110) begin
            match <= 1'b1;
        end
        else begin
            match <= 1'b0;
        end
    end
end
  
endmodule

VL27 不重叠序列检测

VL27 不重叠序列检测

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);

//定义的状态类型
    parameter                           IDLE = 4'd0                ;
    parameter                           s1 = 4'd1                  ;
    parameter                           s2 = 4'd2                  ;
    parameter                           s3 = 4'd3                  ;
    parameter                           s4 = 4'd4                  ;
    parameter                           s5 = 4'd5                  ;
    parameter                           s6 = 4'd6                  ;
    parameter                           sf1 = 4'd7                 ;
    parameter                           sf2 = 4'd8                 ;
    parameter                           sf3 = 4'd9                 ;
    parameter                           sf4 = 4'd10                ;
    parameter                           sf5 = 4'd11                ;
    parameter                           sf6 = 4'd12                ;


//machine variable
reg                    [   3:0]         st_next                    ;
reg                    [   3:0]         st_cur                     ;

//(1) state transfer
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        st_cur      <= IDLE ;
    end
    else begin
        st_cur      <= st_next ;
    end
end

always@(st_cur or data) begin
	case (st_cur)
		IDLE:begin
			if(data == 0) begin
				st_next = s1;
			end
			else begin
				st_next = sf1;
			end
		end

		s1:begin
			if(data == 1) begin
				st_next = s2;
			end
			else begin
				st_next = sf2;
			end
		end

		s2:begin
			if(data == 1) begin
				st_next = s3;
			end
			else begin
				st_next = sf3;
			end
		end

		s3:begin
			if(data == 1) begin
				st_next = s4;
			end
			else begin
				st_next = sf4;
			end
		end

		s4:begin
			if(data == 0) begin
				st_next = s5;
			end
			else begin
				st_next = sf5;
			end
		end

		s5:begin
			if(data == 0) begin
				st_next = s6;
			end
			else begin
				st_next = sf6;
			end
		end

		s6:begin
			if(data == 0) begin
				st_next = s1;
			end
			else begin
				st_next = sf1;
			end
		end

		sf1:begin
			st_next = sf2;
		end

		sf2:begin
			st_next <= sf3;
		end

		sf3:begin
			st_next = sf4;
		end

		sf4:begin
			st_next = sf5;
		end

		sf5:begin
			st_next = sf6;
		end

		sf6:begin
			if (data == 0) begin
				st_next = s1;
			end
			else begin
				st_next = sf1;
			end
		end

		default: st_next = IDLE;

	endcase
end

always @(*) begin
	if (!rst_n) begin
		match <= 1'b0;
		not_match <= 1'b0;
	end else begin
		if(st_cur == s6) begin
			match <= 1'b1;
			not_match <= 1'b0;
		end
		else if(st_cur == sf6) begin
			match <= 1'b0;
			not_match <= 1'b1;
		end
		else begin
			match <= 1'b0;
			not_match <= 1'b0;
		end
	end
	
end

endmodule

VL28 输入序列不连续的序列检测

VL28 输入序列不连续的序列检测

`timescale 1ns/1ns
module sequence_detect(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               data                       ,
    input                               data_valid                 ,
    output reg                          match                       
    );

//定义的状态类型
    parameter                           IDLE = 4'd0                ;
    parameter                           s1_0 = 4'd1                ;
    parameter                           s2_01 = 4'd2               ;
    parameter                           s3_011 = 4'd3              ;
    parameter                           s4_0110 = 4'd4             ;

//machine variable
reg                    [   3:0]         st_next                    ;
reg                    [   3:0]         st_cur                     ;
  

//(1) state transfer
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        st_cur      <= IDLE ;
    end
    else begin
        st_cur      <= st_next ;
    end
end

always @(st_cur or data or data_valid) begin
    case (st_cur)
        IDLE:begin
            if(data_valid && data == 0) begin
                    st_next = s1_0;
                end
            else begin
                st_next = IDLE;
                end
            end
        s1_0:begin
            if(data_valid) begin
                if (data == 1) begin
                    st_next = s2_01;
                end else begin
                    st_next = s1_0;
                end
            end
            else begin
                st_next = s1_0;
            end
        end

        s2_01:begin
            if(data_valid) begin
                if (data == 1) begin
                    st_next = s3_011;
                end else begin
                    st_next = s1_0;
                end
            end
            else begin
                st_next = s2_01;
            end
        end

        s3_011:begin
            if(data_valid) begin
                if (data == 0) begin
                    st_next = s4_0110;
                end else begin
                    st_next = IDLE;
                end
            end
            else begin
                st_next = s3_011;
            end
        end


        s4_0110:begin
            if(data_valid) begin
                if (data == 0) begin
                    st_next = s1_0;
                end else begin
                    st_next = IDLE;
                end
            end
            else begin
                st_next = IDLE;
            end
        end
       
        default: st_next = IDLE;
    endcase
end

always @(st_cur or rst_n) begin
    if(!rst_n==1) begin
        match <= 1'b0;
    end
    else if (st_cur == s4_0110) begin
        match <= 1'b1;
    end
        else begin
            match <= 1'b0;
        end
end

endmodule

02 时序逻辑

VL29 信号发生器

VL29 信号发生器

`timescale 1ns/1ns
module signal_generator(
	input clk,
	input rst_n,
	input [1:0] wave_choise,
	output reg [4:0]wave
	);

  
endmodule

VL30 数据串转并电路

VL30 数据串转并电路

`timescale 1ns/1ns

module s_to_p(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               valid_a                    ,
    input                               data_a                     ,
 
    output reg                          ready_a                    ,
    output reg                          valid_b                    ,
    output reg         [   5:0]         data_b                      
);
reg                    [   5:0]         data_cache                 ;//数据缓存
reg                    [   2:0]         data_cnt                   ;//计数器

//计数器 值如果有效加1;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        data_cnt <= 3'b0;
    end else  begin
        if(valid_a) begin
            if(data_cnt == 3'd5) begin
                data_cnt <= 0;
            end else begin
                data_cnt <= data_cnt + 1;
            end
        end
        else begin
            data_cnt <= data_cnt;
        end
    end
end

//有效赋值
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        data_cache <= 6'b00_0000;
    end 
    else if(valid_a && data_cnt <= 3'd5) begin
            data_cache <= {data_a,data_cache[5:1]};
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        data_b <= 6'd0;
    end
    else if(data_cnt == 3'd5) begin
        data_b <= {data_a,data_cache[5:1]};
    end
    else begin
        data_b <= data_b;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        valid_b <= 1'b0;
    end 
    else if (data_cnt == 3'd5) begin
        valid_b <= 1'd1;
    end else begin
        valid_b <= 1'd0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        ready_a <= 1'd0;
    end else begin
        ready_a <= 1'd1;
    end
end
endmodule

VL31 数据累加输出

VL31 数据累加输出

`timescale 1ns/1ns

module valid_ready(
    input                               clk                        ,
    input                               rst_n                      ,
    input              [   7:0]         data_in                    ,
    input                               valid_a                    ,
    input                               ready_b                    ,
 
    output                              ready_a                    ,
    output reg                          valid_b                    ,
    output reg         [   9:0]         data_out                    
);

reg                    [   1:0]         data_cnt                   ;


//计数器用于表示计算是否满
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        data_cnt <= 2'b0;
    end else  begin
        if(valid_a && ready_a) begin
            if(data_cnt == 2'd3) begin
                data_cnt <= 0;
            end else begin
                data_cnt <= data_cnt + 1;
            end
        end
        else begin
            data_cnt <= data_cnt;
        end
    end
end


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_out <= 10'd0;
    end
    else if(valid_a && ready_a) begin
        if(data_cnt == 2'd0) begin
            data_out <= data_in;
        end else begin
            data_out <= data_out + data_in;
        end
    end
    else begin
        data_out <= data_out;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        valid_b <= 1'b0;
    end else begin
        if(data_cnt == 2'd3 && valid_a && ready_a) begin
            valid_b <= 1'b1;
        end
        else if (valid_b && ready_b) begin
            valid_b <= 1'b0;
        end
        else begin
            valid_b <= valid_b;
        end
    end
end

assign ready_a = ~valid_b | ready_b;

endmodule

VL32 非整数倍数据位宽转换24to128

VL32 非整数倍数据位宽转换24to128

`timescale 1ns/1ns

module width_24to128(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               valid_in                   ,
    input              [  23:0]         data_in                    ,
 
    output reg                          valid_out                  ,
    output reg         [ 127:0]         data_out                    
);




reg [3:0] data_cnt;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_cnt <= 3'd0;
    end else begin
        if(valid_in) begin
            if(data_cnt == 4'd15) begin
                data_cnt <= 4'd0;
            end else begin
                data_cnt <= data_cnt + 1'd1;
            end
        end else begin
            data_cnt <= data_cnt;
        end
    end    
end

reg [120-1:0] data_buff;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_buff <= 120'd0;
    end else if(valid_in) begin
        data_buff <= {data_buff[95:0],data_in};
    end
    else begin
        data_buff <= data_buff;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_out <= 128'd0;
        valid_out <= 1'd0;
    end else begin
        if(valid_in && data_cnt == 4'd5) begin
            data_out <= {data_buff,data_in[23:16]};
            valid_out <= 1'd1;
        end        
        else if(valid_in && data_cnt == 4'd10) begin
            data_out <= {data_buff[111:0],data_in[23:8]};
            valid_out <= 1'd1;
        end
        else if(valid_in && data_cnt == 4'd15) begin
            data_out <= {data_buff[103:0],data_in};
            valid_out <= 1'd1;
        end
        else begin
            valid_out <= 1'd0;
        end
    end
    
end
endmodule

VL33 非整数倍数据位宽转换8to12

VL33 非整数倍数据位宽转换8to12

`timescale 1ns/1ns
/*
valid_in表示输入有效,当为1表示输入有效,当为0上表述输入数据无效

*/


module width_8to12(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               valid_in                   ,
    input              [   7:0]         data_in                    ,
 
    output reg                          valid_out                  ,
    output reg         [  11:0]         data_out                    
);

reg [1:0]                                    data_cnt                   ;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_cnt <= 2'b0;
    end else begin
        if (valid_in) begin
            if (data_cnt == 2'd2) begin
                data_cnt <= 2'd0;
            end
            else begin
                data_cnt <=  data_cnt + 1'd1;
            end
        end
        else begin
            data_cnt <= data_cnt;
        end
    end
end

reg                    [   7:0]         data_buff                  ;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_buff <= 8'd0;
    end else begin
        if (valid_in) begin
            data_buff <= data_in;
        end
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_out <= 12'd0;
        valid_out <= 1'd0;        
    end else begin
        if(data_cnt == 2'd1 && valid_in) begin
            data_out <= {data_buff,data_in[7:4]};
            valid_out <= 1'd1;
        end
        else if(data_cnt == 2'd2 && valid_in) begin
            data_out <= {data_buff[3:0],data_in};
            valid_out <= 1'd1;            
        end
        else begin
            valid_out <= 1'd0;
        end
    end
end


endmodule

VL34 整数倍数据位宽转换8to16

VL34 整数倍数据位宽转换8to16

`timescale 1ns/1ns

module width_8to16(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               valid_in                   ,
    input              [   7:0]         data_in                    ,
 
    output reg                          valid_out                  ,
    output reg         [  15:0]         data_out                    
);



reg                                     data_cnt                   ;

//计数器用于表示计算是否满
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        data_cnt <= 1'b0;
	end
	else begin
		if(valid_in) begin
			data_cnt <= data_cnt + 1'b1;
		end
		else begin
			data_cnt <= data_cnt;
		end
	end	
end

reg [7:0] data_reg;
always @(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		data_out <= 16'b0;
		valid_out <= 1'b0;
	end else begin
		if (valid_in) begin
			if (data_cnt == 0) begin
				data_reg <=  data_in;
				valid_out <= 1'b0;
			end else begin
				data_out <= {data_reg,data_in};
				valid_out <= 1'b1;
			end
		end else begin
			valid_out <= 1'b0;

		end
	end


end

endmodule

VL35 状态机-非重叠的序列检测

VL35 状态机-非重叠的序列检测

`timescale 1ns/1ns

module sequence_test1(
	input wire clk  ,
	input wire rst  ,
	input wire data ,
	output reg flag
);
//*************code***********//
parameter IDLE = 3'b000;
parameter s1_1 = 3'b001;
parameter s2_10 = 3'b010;
parameter s3_101 = 3'b011;
parameter s4_1011 = 3'b100;
parameter s5_10111 = 3'b101;

//machine variable
reg                    [   2:0]         st_next                    ;
reg                    [   2:0]         st_cur                     ;
  
//(1) state transfer
always @(posedge clk or negedge rst) begin
    if (!rst) begin
        st_cur      <= IDLE ;
    end
    else begin
        st_cur      <= st_next ;
    end
end

always @(*) begin
    case (st_cur)
        IDLE: begin
            st_next = data?s1_1:IDLE;
        end
        s1_1: begin
            st_next = data?s1_1:s2_10;
        end
        s2_10: begin
            st_next = data?s3_101:IDLE;
        end
        s3_101: begin
            st_next = data?s4_1011:s2_10;
        end
        s4_1011: begin
            st_next = data?s5_10111:s2_10;
        end
        s5_10111:begin
            st_next = data?s1_1:IDLE;
        end
        default: st_next = IDLE;
    endcase
end

always @(*) begin
    if(!rst) begin
        flag <= 1'b0;
    end
    else if(st_cur == s5_10111) begin
        flag <= 1'b1;
    end
    else begin
        flag <= 1'b0;
    end
end

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

VL36 状态机-重叠序列检测

VL36 状态机-重叠序列检测

`timescale 1ns/1ns

module sequence_test2(
	input wire clk  ,
	input wire rst  ,
	input wire data ,
	output reg flag
);
//*************code***********//
    parameter S0=0, S1=1, S2=2, S3=3, S4=4;
    reg [2:0] state, nstate;
    
    always@(posedge clk or negedge rst) begin
        if(~rst)
            state <= S0;
        else
            state <= nstate;
    end
    
    always@(*) begin
        if(~rst)
            nstate <= S0;
        else
            case(state)
                S0     : nstate <= data? S1: S0;
                S1     : nstate <= data? S1: S2;
                S2     : nstate <= data? S3: S0;
                S3     : nstate <= data? S4: S2;
                S4     : nstate <= data? S1: S2;
                default: nstate <= S0;
            endcase
    end
    
    always@(posedge clk or negedge rst) begin
        if(~rst)
            flag <= 0;
        else
            flag <= state==S4;
    end

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

VL37 时钟分频(偶数)

VL37 时钟分频(偶数)

`timescale 1ns/1ns

module even_div
    (
    input  wire                         rst                        ,
    input  wire                         clk_in                     ,
    output wire                         clk_out2                   ,
    output wire                         clk_out4                   ,
    output wire                         clk_out8                    
    );
//*************code***********//
reg                    [   1:0]         clk_cnt                    ;
reg                                     s_1,s_2,s_3                ;
always @(posedge clk_in or negedge rst) begin
    if(!rst) begin
        clk_cnt <= 2'b0;
    end
    else if (clk_cnt == 2'b11) begin
        clk_cnt <= 2'b0;     
    end else begin
        clk_cnt <= clk_cnt + 1'b1;
    end
end

always @(posedge clk_in or negedge rst) begin
    if (!rst) begin
        s_1 <= 1'b0;
        s_2 <= 1'b0;
        s_3 <= 1'b0;
    end  else begin
        if(clk_cnt==2'd0 ||clk_cnt==2'd1||clk_cnt==2'd2||clk_cnt==2'd3) begin
            s_1 <= ~s_1;
        end
        if (clk_cnt == 2'd0 || clk_cnt == 2'd2) begin
            s_2 <= ~s_2;
        end
        if(clk_cnt == 2'd0) begin
            s_3 <= ~s_3;
        end
    end

end
assign clk_out2 = s_1;
assign clk_out4 = s_2;
assign clk_out8 = s_3;


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

VL38 自动贩售机1

VL38 自动贩售机1

`timescale 1ns/1ns
module seller1(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,
	input wire d2 ,
	input wire d3 ,
	
	output reg out1,
	output reg [1:0]out2
);
//*************code***********//
localparam      IDLE        = 0,
                HALF        = 1,
                ONE         = 2,
                ONE_HALF    = 3,
                TWO         = 4,
                TWO_HALF    = 5,
                THREE       =6;
    reg[2:0] curr_state,next_state;
    always @(posedge clk or negedge rst)begin
        if(~rst)
            curr_state <= IDLE;
        else
            curr_state <= next_state;
    end
    
    always @(*)begin
        case(curr_state)
            IDLE        :begin
                            next_state =d1? HALF:
                                        d2? ONE:
                                        d3? TWO:
                                        next_state;
                         end
            HALF        :begin
                            next_state =d1? ONE:
                                        d2? ONE_HALF:
                                        d3? TWO_HALF:
                                        next_state;
                         end 
            ONE         :begin
                            next_state =d1? ONE_HALF:
                                        d2? TWO:
                                        d3? THREE:
                                        next_state;
                         end 
            ONE_HALF    :next_state =IDLE;
            TWO         :next_state =IDLE;  
            TWO_HALF    :next_state =IDLE;
            THREE       :next_state =IDLE;
            default     :next_state =IDLE;
        endcase
    end
    
    always @(posedge clk or negedge rst)begin
        if(~rst)begin
            out1 <= 0;
            out2 <= 0;
        end else begin
            case(next_state) 
                ONE_HALF:begin
                            out1 <= 1'b1; out2<=0;
                         end
                TWO     :begin
                            out1 <= 1'b1; out2<=1;
                         end
                TWO_HALF:begin
                            out1 <= 1'b1; out2<=2;
                         end 
                THREE   :begin
                            out1 <= 1'b1; out2<=3;
                         end   
                default :begin
                            out1 <= 1'b0; out2<=0;
                         end
            endcase
        end
        
    end
//*************code***********//
endmodule

VL39 自动贩售机2

VL39 自动贩售机2

`timescale 1ns/1ns

module seller2(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,
	input wire d2 ,
	input wire sel ,
	
	output reg out1,
	output reg out2,
	output reg out3
);
//*************code***********//


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

VL40 占空比50%的奇数分频

VL40 占空比50%的奇数分频

`timescale 1ns/1ns

module odo_div_or
   (
    input  wire                         rst                        ,
    input  wire                         clk_in                     ,
    output wire                         clk_out7                    
    );

//*************code***********//

//*************code***********//
reg                    [   2:0]         clk_cnt                    ;
always @(posedge clk_in or negedge rst) begin
    if(!rst) begin
        clk_cnt <= 3'b0;
    end
    else if (clk_cnt == 3'd6) begin
        clk_cnt <= 3'b0;
    end else begin
        clk_cnt <= clk_cnt + 1'b1;
    end
end
reg                

                     s_1                        ;

always @(posedge clk_in or negedge rst) begin
    if (!rst) begin
        s_1 <= 1'b0;
    end
    else begin
        if(clk_cnt == 3'd6) begin
            s_1 <= ~s_1;
        end
        else begin
            s_1 <= s_1;
        end
    end
end

always @(negedge clk_in or negedge rst) begin
    if (!rst) begin
        s_1 <= 1'b0;
    end
    else begin
        if(clk_cnt == 3'd3) begin
            s_1 <= ~s_1;
        end
        else begin
            s_1 <= s_1;
        end
    end
end
assign clk_out7 = s_1;
//*************code***********//
endmodule

VL41 任意小数分频

VL41 任意小数分频

`timescale 1ns/1ns

module div_M_N(
    input  wire                         clk_in                     ,
    input  wire                         rst                        ,
    output wire                         clk_out                     
);
    parameter                           M_N = 8'd87                ;
    parameter                           c89 = 8'd24                ;//8/9时钟切换点
    parameter                           div_e = 5'd8               ;//偶数周期
    parameter                           div_o = 5'd9               ;//奇数周期 
//*************code***********//

reg                    [   6:0]         data_cnt                   ;
always @(posedge clk_in or negedge rst) begin
    if (!rst) begin
        data_cnt <= 7'd0;
    end else begin
        if(data_cnt == 7'd86) begin
            data_cnt <= 0;
        end else begin
            data_cnt <= data_cnt + 1'd1;
        end
    end
end


reg                                     clk_out_ache               ;

always @(posedge clk_in or negedge rst) begin
    if (!rst) begin
        clk_out_ache <= 1'd0;
    end else begin
        if(data_cnt < c89) begin
//            if (data_cnt < 3) begin
//                clk_out_ache <= 1'b1;
//            end
            if(data_cnt == 0||
                data_cnt == 4||
                data_cnt == 8||
                data_cnt == 12||
                data_cnt == 16||
                data_cnt == 20) begin
                   clk_out_ache <= ~clk_out_ache; 
            end
            else begin
                clk_out_ache <= clk_out_ache;
            end
        end
        else if(data_cnt == 24 ||data_cnt==28 ||
                data_cnt == 33 ||data_cnt==37 ||
                data_cnt == 42 ||data_cnt==46 ||
                data_cnt == 51 ||data_cnt==55 ||
                data_cnt == 60 ||data_cnt==64 ||
                data_cnt == 69 ||data_cnt==73 ||
                data_cnt == 78 ||data_cnt==82 

        )begin
            clk_out_ache <= ~clk_out_ache; 
        end
        else begin
            clk_out_ache <= clk_out_ache;
        end
end
end


assign clk_out = clk_out_ache;
    

endmodule

VL42 无占空比要去的奇数分频

VL42 无占空比要去的奇数分频

`timescale 1ns/1ns

module odd_div (
    input  wire                         rst                        ,
    input  wire                         clk_in                     ,
    output wire                         clk_out5                    
);
//*************code***********//
reg                    [   2:0]         data_cnt                   ;
always @(posedge clk_in or negedge rst) begin
    if (!rst) begin
        data_cnt <= 'd0;
    end else begin
        if(data_cnt == 3'd4) begin
            data_cnt <= 3'd0;
        end else begin
            data_cnt <= data_cnt + 1'd1;
        end
    end
end

reg                                     clk_out_cache               ;
always @(posedge clk_in or negedge rst) begin
    if (!rst) begin
        clk_out_cache <= 1'b0;
    end 
    else if (data_cnt == 3'd0 || data_cnt == 3'd2) begin
        clk_out_cache <= ~clk_out_cache;
    end else begin
        clk_out_cache <= clk_out_cache;
    end
end


assign clk_out5 = clk_out_cache;
endmodule

VL43 根据状态转移写状态机-三段式

VL43 根据状态转移写状态机-三段式

`timescale 1ns/1ns

module fsm1(
	input wire clk  ,
	input wire rst  ,
	input wire data ,
	output reg flag
);
//*************code***********//

parameter s0 = 3'b000;
parameter s1 = 3'b001;
parameter s2 = 3'b010;
parameter s3 = 3'b100;

reg [2:0] st_cur,next_cur;

always @(posedge clk or negedge rst) begin
    if (!rst) begin
        st_cur <= s0;
    end else begin
        st_cur <= next_cur;
    end    
end

always @(*) begin
    case (st_cur)
        s0:begin
            next_cur = (data)?s1:s0;
        end
        s1: begin
            next_cur = (data)?s2:s1;
        end
        s2: begin
            next_cur = (data)?s3:s2;
        end 
        s3: begin
            next_cur = (data)?s0:s3;
        end 
        default: next_cur = s0;
    endcase
    
end

always @(posedge clk or negedge rst) begin
    if(!rst) begin
        flag <= 1'b0;
    end else begin
        if(st_cur == s3) begin
            if (data) begin
                flag <= 1'b1;
            end
            else begin
                flag <= 1'b0;
            end
        end else begin
            flag <= 1'b0;
        end
    end
end

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

VL44 根据状态转移写状态机-二段式

VL44 根据状态转移写状态机-二段式

`timescale 1ns/1ns

module fsm2(
	input wire clk  ,
	input wire rst  ,
	input wire data ,
	output reg flag
);

//*************code***********//

parameter s0 = 4'b0000;
parameter s1 = 4'b0001;
parameter s2 = 4'b0010;
parameter s3 = 4'b0100;
parameter s4 = 4'b1000;

reg [3:0] st_cur,next_cur;
always @(posedge clk or negedge rst) begin
    if (!rst) begin
        st_cur <=  s0;
    end else begin
        st_cur <= next_cur;
    end
end

always @(*) begin
    if(!rst) begin
        flag <= 1'b0;
//        next_cur = s0;
    end
    case (st_cur)
        s0: begin
            next_cur = data?s1:s0;
            flag <= 1'b0;
        end 
        s1: begin
            next_cur = data?s2:s1;
            flag <= 1'b0;
        end 
        s2: begin
            next_cur = data?s3:s2;
            flag <= 1'b0;
        end 
        s3: begin
            next_cur = data?s4:s3;
            flag <= 1'b0;
        end 
        s4: begin
            next_cur = data?s1:s0;
            flag <= 1'b1;
            
        end              
        default: begin
            next_cur = s0;
            flag <= 1'b0;
        end
    endcase
end


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

03 跨时钟域传输

VL45 异步FIFO

VL45 异步FIFO

`timescale 1ns/1ns

/***************************************RAM*****************************************/
module dual_port_RAM #(           
    parameter                           DEPTH = 16                 ,  //ram的存储空间8*16
    parameter                           WIDTH = 8                   
    ) (
    input                               wclk                       ,//写时钟
    input                               wenc                       ,//写使能
    input              [$clog2(DEPTH)-1:0]waddr                    ,//深度对2取对数,得到地址的位宽。
    input              [WIDTH-1:0]      wdata                      ,//数据写入
    input                               rclk                       ,//读时钟
    input                               renc                       ,//读使能
    input              [$clog2(DEPTH)-1:0]raddr                    ,//深度对2取对数,得到地址的位宽。
    output reg         [WIDTH-1:0]      rdata                       //数据输出
);

reg                    [WIDTH-1:0] RAM_MEM [0:DEPTH-1]                           ;//开辟存储空间

always @(posedge wclk) begin                                        //写数据
    if(wenc)
        RAM_MEM[waddr] <= wdata;
end

always @(posedge rclk) begin                                        //读数据
    if(renc)
        rdata <= RAM_MEM[raddr];
end

endmodule  

/***************************************AFIFO*****************************************/
module asyn_fifo#(   //8为宽,数据深度为16,则用4位地址可以表示
	parameter	WIDTH = 8,
	parameter 	DEPTH = 16
)(
    input                               wclk                       ,//写时钟
    input                               rclk                       ,//读时钟 
    input                               wrstn                      ,//写时钟域异步复位
    input                               rrstn                      ,//读时钟域异步复位
    input                               winc                       ,//写使能
    input                               rinc                       ,//读使能
    input              [WIDTH-1:0]      wdata                      ,//写数据

    output wire                         wfull                      ,//将满标志
    output wire                         rempty                     ,//将空标志
    output wire        [WIDTH-1:0]      rdata                       //读出数据
);


localparam ADDR_WIDTH = $clog2(DEPTH);    //定义地址宽度

//定义双端口ram的读写地址
wire                   [ADDR_WIDTH-1:0] wr_adr                     ;//双端口ram的写地址
wire                   [ADDR_WIDTH-1:0] rd_adr                     ;//双端口ram的读地址
 
reg                    [ADDR_WIDTH:0]   wr_adr_ptr                 ;//写指针
reg                    [ADDR_WIDTH:0]   rd_adr_ptr                 ;//读指针

//转换为格雷码进行打拍操作
wire                   [ADDR_WIDTH:0]   wr_adr_gray                ;//写地址指针二进制转化为格雷码
reg                    [ADDR_WIDTH:0]   wr_adr_gray1               ;//打一拍缓存
reg                    [ADDR_WIDTH:0]   wr_adr_gray2               ;//打两拍缓存

wire                   [ADDR_WIDTH:0]   rd_adr_gray                ;//读地址指针二进制转化为格雷码 
reg                    [ADDR_WIDTH:0]   rd_adr_gray1               ;//打一拍缓存
reg                    [ADDR_WIDTH:0]   rd_adr_gray2               ;//打两拍缓存


//读写地址比控制指针少一位
assign wr_adr = wr_adr_ptr[ADDR_WIDTH-1:0];
assign rd_adr = rd_adr_ptr[ADDR_WIDTH-1:0];

//写地址指针控制
always @(posedge wclk or negedge wrstn) begin
    if (!wrstn) begin
        wr_adr_ptr <= 'd0;
    end else begin
        if(winc && (~wfull)) begin
            wr_adr_ptr <= wr_adr_ptr + 1'b1;
        end else begin
            wr_adr_ptr <= wr_adr_ptr;
        end
    end
end

//读地址指针控制
always @(posedge rclk or negedge rrstn) begin
    if (!rrstn) begin
        rd_adr_ptr <= 'd0;
    end else begin
        if(rinc && (~rempty)) begin
            rd_adr_ptr <= rd_adr_ptr + 1'b1;
        end else begin
            rd_adr_ptr <= rd_adr_ptr;
        end
    end
end

//二进制指针转化为格雷码
assign wr_adr_gray = (wr_adr_ptr >> 1) ^ wr_adr_ptr;
assign rd_adr_gray = (rd_adr_ptr >> 1) ^ rd_adr_ptr;

reg                   [ADDR_WIDTH:0]   wr_adr_gray_reg                ;//写地址指针二进制转化为格雷码

always @(posedge wclk or negedge wrstn) begin
    if (!wrstn) begin
        wr_adr_gray_reg <= 'd0;
    end else begin
        wr_adr_gray_reg <= wr_adr_gray;
    end
end

reg                   [ADDR_WIDTH:0]   rd_adr_gray_reg                ;//写地址指针二进制转化为格雷码

always @(posedge rclk or negedge rrstn) begin
    if (!rrstn) begin
        rd_adr_gray_reg <= 'd0;
    end else begin
        rd_adr_gray_reg <= rd_adr_gray;
    end
end


//格雷码的同步 读时钟域同步到写时钟域
always @(posedge wclk or negedge wrstn) begin
    if (!wrstn) begin
        rd_adr_gray1 <= 'd0;
        rd_adr_gray2 <= 'd0;
    end else begin
        rd_adr_gray1 <= rd_adr_gray_reg;
        rd_adr_gray2 <= rd_adr_gray1;
    end
end

//格雷码的同步 写时钟域同步到读时钟域
always @(posedge rclk or negedge rrstn) begin
    if (!rrstn) begin
        wr_adr_gray1 <= 'd0;
        wr_adr_gray2 <= 'd0;
    end else begin
        wr_adr_gray1 <= wr_adr_gray_reg;
        wr_adr_gray2 <= wr_adr_gray1;
    end
end

assign rempty = (rd_adr_gray_reg == wr_adr_gray2) ? 1'b1 : 1'b0;
assign wfull = (wr_adr_gray_reg[ADDR_WIDTH] != rd_adr_gray2[ADDR_WIDTH]) && (wr_adr_gray[ADDR_WIDTH-1] != rd_adr_gray2[ADDR_WIDTH-1]) && (wr_adr_gray[ADDR_WIDTH-2:0] == rd_adr_gray2[ADDR_WIDTH-2:0]);

dual_port_RAM #(.DEPTH(DEPTH), .WIDTH(WIDTH))
                u_dual_port_RAM(
                    .wclk(wclk),
                    .rclk(rclk),
                    .wenc(winc && (~wfull)),
                    .renc(rinc && (~rempty)),
                    .waddr(wr_adr),
                    .raddr(rd_adr),
                    .wdata(wdata),
                    .rdata(rdata)
                );

endmodule

VL46 同步FIFO

VL46 同步FIFO

`timescale 1ns/1ns
/******


*******/

/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,
    parameter                           WIDTH = 8 )(                  
    input                               wclk                        //写数据时钟 
    ,input wenc                                                     //写使能
    ,input [$clog2(DEPTH)-1:0] waddr                                //深度对2取对数,得到地址的位宽
    ,input [WIDTH-1:0] wdata                                        //数据写入
    ,input rclk                                                     //读数据时钟
    ,input renc                                                     //读使能
    ,input [$clog2(DEPTH)-1:0] raddr                                //深度对2取对数,得到地址的位宽。
    ,output reg [WIDTH-1:0] rdata                                   //数据输出
);

reg                    [WIDTH-1:0] RAM_MEM [0:DEPTH-1]                           ;//开辟宽度为WIDTH,深度为DEPTH的RAM_MEM

//向RAM_MEM中写入数据,其中waddr写地址
always @(posedge wclk) begin
    if(wenc)
        RAM_MEM[waddr] <= wdata;
end

//从RAM_MEM读出数据,其中raddr为读地址
always @(posedge rclk) begin
    if(renc)
        rdata <= RAM_MEM[raddr];
end

endmodule

/**********************************SFIFO************************************/
module sfifo#(
    parameter                           WIDTH = 8                  ,//定义宽度
    parameter                           DEPTH = 16                  //定义深度
)(
    input                               clk                        ,//时钟
    input                               rst_n                      ,//复位
    input                               winc                       ,//写使能
    input                               rinc                       ,//读使能
    input              [WIDTH-1:0]      wdata                      ,//写数据

    output reg                          wfull                      ,//写满标志
    output reg                          rempty                     ,//读空标志
    output wire        [WIDTH-1:0]      rdata                       //读数据
);

localparam                              ADDR_WIDTH = $clog2(DEPTH) ;
reg                    [ADDR_WIDTH:0]   waddr                      ;
reg                    [ADDR_WIDTH:0]   raddr                      ;

//写地址定义
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        waddr <= 'b0;
    end else begin
        if(winc && ~wfull) begin                                    //如果写使能,而且写未满
            waddr <= waddr + 1'b1;
        end
        else begin
            waddr <= waddr;
        end
    end
end

//读地址定义
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        raddr <= 'b0;
    end else begin
        if(rinc && ~rempty) begin                                   //如果写使能,而且写未满
            raddr <= raddr + 1'b1;
        end
        else begin
            raddr <= raddr;
        end
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        wfull <= 'b0;
        rempty <= 'b0;
    end else begin
        wfull <= (raddr == {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH-1:0]});
        rempty <= (raddr == waddr);
    end
end


dual_port_RAM #(
 .DEPTH(DEPTH),
 .WIDTH(WIDTH)
)
dual_port_RAM_U0(
    .wclk(clk),
    .wenc(winc&&~wfull),
    .waddr(waddr[ADDR_WIDTH-1:0]),
    .wdata(wdata),
    .rclk(clk),
    .renc(rinc&&~rempty),
    .raddr(raddr[ADDR_WIDTH-1:0]),
    .rdata(rdata)
);

endmodule

VL47 格雷码计数器

VL47 格雷码计数器

`timescale 1ns/1ns

module gray_counter(
    input                               clk                        ,
    input                               rst_n                      ,

    output reg         [   3:0]         gray_out                    
);

reg                    [   3:0]         binary_cnt                 ;
reg                                     flag                       ;


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag <= 1'd0;
    end
    else begin
        flag <= ~flag;
    end
end
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        binary_cnt <= 1'd0;
    end else begin
        if (flag == 1'd1) begin
            binary_cnt <= binary_cnt + 1'd1;
        end else begin
            binary_cnt <= binary_cnt;
        end
    end
end

always @(*) begin
    gray_out <= binary_cnt ^ (binary_cnt >> 1);
end

endmodule

VL48 多bit MUX同步器

VL48 多bit MUX同步器

`timescale 1ns/1ns

module mux(
	input 				clk_a	, 
	input 				clk_b	,   
	input 				arstn	,
	input				brstn   ,
	input		[3:0]	data_in	,
	input               data_en ,

	output reg  [3:0] 	dataout
);
endmodule

VL49 脉冲同步电路

VL49 脉冲同步电路

`timescale 1ns/1ns

module pulse_detect(
    input                               clk_fast                   ,
    input                               clk_slow                   ,
    input                               rst_n                      ,
    input                               data_in                    ,

    output                              dataout                     
);

reg                                     src_state                  ;
reg                                     src_state_d0               ;
reg                                     src_state_d1               ;
reg                                     src_state_d2               ;
	
//原时钟域下脉冲信号转变为电平信号
always @(posedge clk_fast or negedge rst_n) begin
    if(!rst_n)
        src_state <= 1'b0;
    else
        src_state <= data_in ^ src_state;                               //通过异或门做处理
end

always @(posedge clk_slow  or negedge rst_n) begin
    if (!rst_n) begin
        src_state_d0 <= 1'b0;
        src_state_d1 <= 1'b0;
        src_state_d2 <= 1'b0;
    end else begin
        src_state_d0 <= src_state;
        src_state_d1 <= src_state_d0;
        src_state_d2 <= src_state_d1;
    end
    
end

//边沿检测产生新的脉冲
assign dataout = src_state_d1 ^ src_state_d2;


endmodule

04 计数器

VL50 简易秒表

VL50 简易秒表

`timescale 1ns/1ns

module count_module(
    input                               clk                        ,
    input                               rst_n                      ,

    output reg         [   5:0]         second                     ,
    output reg         [   5:0]         minute                      
    );
	

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        second <= 'd0;
        //minute <= 'd0;
    end else begin
        if(second == 6'd60) begin
            second <= 1'd1;
        end else begin
            second <= second + 1'd1;
        end
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        minute <= 1'd0;
    end else begin
        if (second == 6'd60) begin
            minute <= minute + 1'd1;
        end
        if (minute == 6'd60) begin
            minute <= 1'd0;
        end
end
end
endmodule

VL51 可置位计数器

VL51 可置位计数器

`timescale 1ns/1ns

module count_module(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               set                        ,
    input              [   3:0]         set_num                    ,
    output reg         [   3:0]         number                     ,
    output reg                          zero                        
    );


reg                    [   3:0]         data_cnt                   ;

//定义计数器
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_cnt <= 'd0;
    end else begin
        if(set == 1'd1) begin
            data_cnt <= set_num;
        end
            data_cnt <= data_cnt + 1'd1;
    end
end
//
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        zero <= 1'd0;
    end else begin
        if (data_cnt == 1'd0) begin
            zero <= 1'd1;
        end else begin
            zero <= 1'd0;
        end        
    end

end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        number <=4'd0;
    end else begin
        number <= data_cnt;
    end
end

endmodule

VL52 加减计数器

VL52 加减计数器

`timescale 1ns/1ns

module count_module(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               mode                       ,
    output reg         [   3:0]         number                     ,
    output reg                          zero                        
    );
reg                    [   3:0]         data_cnt                   ;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_cnt <= 4'd0;
    end else begin
        if(mode == 1'd1) begin
            if(data_cnt == 4'd9) begin
                data_cnt <= 1'd0;
            end else begin
                data_cnt <= data_cnt + 1'd1;
            end
        end
        else if(mode == 1'd0) begin
            if (data_cnt == 4'd0) begin
                data_cnt <= 4'd9;
            end else begin
            data_cnt <= data_cnt - 1'd1;
        end
    end
end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        number <= 4'd0;
    end else begin
        number <= data_cnt;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        zero <= 1'd0;
    end else begin
        if(data_cnt ==  1'd0) begin
            zero <= 1'd1;
        end else begin
            zero <= 1'd0;
        end
    end
end

endmodule

05 存储器

VL53 单端口RAM

VL53 单端口RAM

`timescale 1ns/1ns

module RAM_1port(
    input                               clk                        ,
    input                               rst                        ,
    input                               enb                        ,
    input              [   6:0]         addr                       ,
    input              [   3:0]         w_data                     ,
    output wire        [   3:0]         r_data                      
);
//*************code***********//
reg [3:0] ram_reg [127:0];    //存储宽度为4位,深度为128
reg                    [   3:0]         r_data_ache                ;
integer  i;
always @(posedge clk or negedge rst) begin
    if(!rst) begin
        for (i =0 ; i < 128; i = i + 1) begin
            ram_reg[i] <= 4'b0;
        end
    end else begin
        if(enb) begin
            ram_reg[addr] <= w_data;
        end else begin
            ram_reg[addr] <= ram_reg[addr];
        end
    end
end

assign r_data = enb ? 4'd0 : ram_reg[addr];

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

VL54 RAM的简单实现

VL54 RAM的简单实现

`timescale 1ns/1ns
module ram_mod(
    input                               clk                        ,
    input                               rst_n                      ,
	
    input                               write_en                   ,
    input              [   7:0]         write_addr                 ,
    input              [   3:0]         write_data                 ,
	
    input                               read_en                    ,
    input              [   7:0]         read_addr                  ,
    output reg         [   3:0]         read_data                   
);

reg [3:0] ram_reg  [127:0];
integer i;
always @(posedge clk or negedge rst_n) begin
	if (!rst_n) begin
		for (i = 0;i<128 ; i = i + 1) begin
            ram_reg[i] <= 4'b0;
        end
        read_data <= 4'd0;
	end else begin
		if(write_en) begin
            ram_reg[write_addr] <= write_data;
        end
        if(read_en) begin
            read_data <= ram_reg[read_addr];
        end
	end
end
endmodule

06 综合

VL55 Johnson Counter

VL55 Johnson Counter

`timescale 1ns/1ns

module JC_counter(
    input                               clk                        ,
    input                               rst_n                      ,
 
    output reg         [   3:0]         Q                           
);

reg                    [   2:0]         data_cnt                   ;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        data_cnt <= 3'b0;
    end else begin
        data_cnt <= data_cnt + 1'd1;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        Q <=  4'd0;
    end else begin
        if (data_cnt <= 4'd3) begin
            Q <= (Q>>1) | 1000;
        end
        else begin
            Q <= (Q>>1);
        end
    end
end


endmodule

VL56 流水线乘法器

VL56 流水线乘法器

`timescale 1ns/1ns
 
module multi_pipe#(
    parameter size = 4
)(
    input                      clk        ,   
    input                      rst_n       ,
    input   [size-1:0]          mul_a       ,
    input   [size-1:0]          mul_b       ,
  
    output  reg [size*2-1:0]    mul_out    
);
 
/********************************************************************/
    reg [7:0]  addr01;
    reg [7:0]  addr23;

    wire [7:0] temp0 ;
    wire [7:0] temp1 ;
    wire [7:0] temp2 ;
    wire [7:0] temp3 ;

    assign temp0 = mul_b[0]? {4'b0, mul_a} : 'd0;
    assign temp1 = mul_b[1]? {3'b0, mul_a, 1'b0} : 'd0;
    assign temp2 = mul_b[2]? {2'b0, mul_a, 2'b0} : 'd0;
    assign temp3 = mul_b[3]? {1'b0, mul_a, 3'b0} : 'd0;

    always @(posedge clk or negedge rst_n) begin 
        if(~rst_n) begin
            addr01  <= 'd0;
            addr23  <= 'd0;
            mul_out <= 'd0;
        end 
        else begin
            addr01 <= temp0 + temp1;
            addr23 <= temp2 + temp3;

            mul_out <= addr01 + addr23;
        end
    end
endmodule

VL57 交通灯

VL57 交通灯

`timescale 1ns/1ns

module triffic_light
    (
		input rst_n, //异位复位信号,低电平有效
        input clk, //时钟信号
        input pass_request,
		output wire[7:0]clock,
        output reg red,
		output reg yellow,
		output reg green
    );
	
endmodule

VL58 游戏机计费程序

VL58 游戏机计费程序

`timescale 1ns/1ns

module game_count
    (
		input rst_n, //异位复位信号,低电平有效
        input clk, 	//时钟信号
        input [9:0]money,
        input set,
		input boost,
		output reg[9:0]remain,
		output reg yellow,
		output reg red
    );


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
       remain <= 'd0;         
    end else begin
        if(set) begin
            remain <= money + remain;
        end
        else if (boost) begin
            if (remain < 'd2) begin
                remain <= 'd0;
            end else begin
                remain <= remain - 'd2;
            end
        end
        else if (!boost) begin
            if (remain < 'd1) begin
                remain <= 'd0;
            end
            else begin
                remain <= remain - 'd1;
            end 
        end
        else begin
            remain <= remain;
        end
    end
end


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        red <= 1'd0;
    end else begin 
        if(remain < 'd1) begin
            red <= 1'd1;
        end else begin
            red <= 1'd0;
        end
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        yellow <= 1'd0;
    end else begin 
        if(yellow < 'd10 && yellow > 'd0) begin
            yellow <= 1'd1;
        end else begin
            yellow <= 1'd0;
        end
    end
end

endmodule

你可能感兴趣的:(FPGA,#,Verilog学习,fpga开发)