verilog牛客网刷题代码汇总(下)(2)

简介: 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线优先编码器

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
相关文章
|
7月前
|
C语言
C程序设计内容与例题讲解 -- 第四章--选择结构程序设计(第五版)谭浩强
C程序设计内容与例题讲解 -- 第四章--选择结构程序设计(第五版)谭浩强
120 1
|
7月前
|
C语言
C程序设计内容与例题讲解 -- 第四章--选择结构程序设计第二部分(第五版)谭浩强
C程序设计内容与例题讲解 -- 第四章--选择结构程序设计第二部分(第五版)谭浩强
|
算法 C语言
C语言 每日一题 力扣习题 10.19日 day1
C语言 每日一题 力扣习题 10.19日 day1
50 0
|
算法 C语言
C语言 每日一题 牛客网习题 10.20 day2
C语言 每日一题 牛客网习题 10.20 day2
52 0
|
芯片
牛客网Verilog刷题(2)
牛客网Verilog刷题(2)
105 0
|
C语言
牛客网Verilog刷题(1)
牛客网Verilog刷题(1)
83 0
|
存储 算法 C语言
[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)
[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)
|
算法 C语言
想说说关于在刷题网站(牛客 、C语言网、力扣)上测试样例过了但是OJ判错这档子事
想说说关于在刷题网站(牛客 、C语言网、力扣)上测试样例过了但是OJ判错这档子事
|
机器学习/深度学习 存储 人工智能
C语言程序设计第五版谭浩强课后答案 第五章习题答案(3-17题)
C语言程序设计第五版谭浩强课后答案 第五章习题答案(3-17题)
|
存储 算法 异构计算
牛客网verilog刷题知识点盘点(75道题的版本)
还有几个坑没填,知识点整理总结自互联网,本人csdn博客搬运
597 0