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
相关文章
|
芯片
牛客网Verilog刷题(2)
牛客网Verilog刷题(2)
105 0
|
C语言
牛客网Verilog刷题(1)
牛客网Verilog刷题(1)
83 0
|
存储 算法 C语言
[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)
[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)
|
存储 算法 异构计算
牛客网verilog刷题知识点盘点(75道题的版本)
还有几个坑没填,知识点整理总结自互联网,本人csdn博客搬运
598 0
verilog牛客网刷题代码汇总(上)(3)
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线优先编码器
135 0
verilog牛客网刷题代码汇总(上)(4)
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线优先编码器
98 0
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线优先编码器
119 0
verilog牛客网刷题代码汇总(下)(3)
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线优先编码器
153 0
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线优先编码器
311 0
verilog牛客网刷题代码汇总(下)(4)
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线优先编码器
132 0