Verilog 学习之路(三)——牛客刷题篇

news2024/10/3 0:33:55

1.输入序列连续的序列检测

  • 题面
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kJH9kHFH-1690301233803)(https://s2.loli.net/2023/07/26/HJPXR2mhbaVCG6d.png)]
  • 思路

对于序列检测题目,常规的解法有两种:状态机法和序列缓存对比法。
状态机法的过程类似于:在初始状态中,先判断第一位是否符合,若符合则进入下一个状态,判断第二位是否符合;若第一位不符合则保持在初始状态,直到第一位匹配。如前两位匹配,则判断第三位是否符合,若第一位匹配,最新输入的数值和目标序列的第二位不匹配,则根据最新一位是否匹配第一位,进入第一位匹配状态或者初始状态。依次类推。
序列缓存对比法,则是将八个时刻的数据缓存,作为一个数组,每个时刻的输入位于数组的末尾,数组其它元素左移,把最早输入的数据移出。然后将数组和目标序列对比,如果数组和目标序列相等,则说明出现目标序列。
序列缓存对比法在实现上比较简单。首先声明一个数组,缓存八个时刻的a输入的数值。移位可以通过位截取操作和位拼接操作实现:a_tem[6:0]表示截取a_tem的低7位,{a_tem[6:0],a}表示把a_tem[6:0]和新输入的数值a拼接,a位于低位。

  • 代码
`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);
	reg [7:0] a_tem;
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			match <=1'b0;
		end
		else if (a_tem == 8'b0111_0001) begin
			match <= 1'b1;
		end
		else begin
			match <= 1'b0;
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			a_tem <= 8'b0;
		end
		else begin
			a_tem <= {a_tem[6:0],a};
		end
	end
  
endmodule

2.含有无关项的序列检测

  • 题面
    在这里插入图片描述
  • 思路

序列缓存对比法,则是将九个时刻的数据缓存,作为一个数组,每个时刻的输入位于数组的末尾,数组其它元素左移,把最早输入的数据移出。然后截取数组的前三位和目标序列011对比,截取数组的后三位和目标序列110对比,如果两段数组都和目标序列相等,则说明出现目标序列。
序列缓存对比法在实现上比较简单,本题采用该方法实现。首先声明一个数组,缓存九个时刻的a输入的数值。移位可以通过位截取操作和位拼接操作实现:a_tem[7:0]表示截取a_tem的低7位,{a_tem[7:0],a}表示把a_tem[7:0]和新输入的数值a拼接,a位于低位。

  • 代码
`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output match
	);
    reg [8:0] a_tem;
    reg match_f;
    reg match_b;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            match_f <=1'b0;
        end
        else if (a_tem[8:6] == 3'b011) begin
            match_f <= 1'b1;
        end
        else begin
            match_f <= 1'b0;
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            match_b <= 1'b0;
        end
        else if (a_tem[2:0] == 3'b110) begin
            match_b <= 1'b1;
        end
        else begin
            match_b <= 1'b0;
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            a_tem <= 9'b0;
        end 
        else begin
            a_tem <= {a_tem[7:0],a};
        end
    end

    assign match = match_b && match_f;
endmodule
  • 解法2
`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);
    reg [8:0] sequence;

	always @(posedge clk or negedge rst_n) begin
		if (~rst_n) begin
			sequence <= 9'b0;
		end
		else begin
			sequence <= {sequence[7:0],a};
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (~rst_n) begin
			match <= 0;
		end
		else if (sequence[8:6] == 3'b011 && sequence[2:0] == 3'b110) begin
			match <= 1;
		end
		else begin
			match <= 0;
		end
	end

endmodule
  • 解法3
`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);
    reg [8:0] val;
    
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            val <= 9'b0;
        end else begin
            val <= {val[7:0],a};
        end
    end
    
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            match <= 1'b0;
        end else begin
            casex (val)
                9'b011xxx110 : match <= 1'b1;
                default : match <= 1'b0;
            endcase
        end
    end
  
endmodule

3. 不重叠序列检测

  • 题意
    在这里插入图片描述
    题目描写错误,应该是001110,而题目是011100,差评。
  • 思路

使用数选器选择出来对应的位,再做同或与最后做与运算,资源用的也很少。

  • 代码
`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);
    
    reg [2:0] cnt;
    reg cmp;
    reg  detect_cmp;
    parameter detect = 6'b011100;
    
    always@(posedge clk or negedge rst_n)begin
        if(! rst_n) 
            cnt  <=  3'd0;
        else if(cnt == 3'd5)
            cnt  <=  3'd0;
        else 
            cnt  <=  cnt  + 3'd1;
    end
    always@(*)begin
        case(cnt)
        3'd0: cmp = 1'd0;
        3'd1: cmp = 1'd1;
        3'd2: cmp = 1'd1;
        3'd3: cmp = 1'd1;
        3'd4: cmp = 1'd0;
        3'd5: cmp = 1'd0;
        default: cmp = 1'd0;
        endcase
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(! rst_n)
                detect_cmp <= 1'd1;
                else if(cnt == 3'd5)
                        detect_cmp  <=  1'd1;
        else
            detect_cmp <= detect_cmp && (~( cmp^ data));
    end
                
    always@(posedge clk or negedge rst_n) begin
        if(! rst_n)
                match <= 1'd0;
        else if((detect_cmp )&&(cnt == 3'd5))
                match <= 1'd1;
        else
                match <= 1'd0;
    end
                
     always@(posedge clk or negedge rst_n) begin
        if(! rst_n)
                not_match <= 1'd0;
         else if((!detect_cmp)&&(cnt == 3'd5))
                not_match <= 1'd1;
        else
                not_match <= 1'd0;
    end
endmodule

4. 简易秒表

  • 题意

image-20230725181116009

  • 思路

首先确定second的取值逻辑:当minute=60时停止计数,即保持second为0;当second=60时,下一个周期second置为1。其余情况second 等于前一时刻的值加一。 然后明确minute的取值逻辑:当second=60,minute等于前一时刻的值加一。其余情况,minute保持不变。

  • 代码
`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
            minute <= 6'd0;
        end 
        else if (second == 6'd60) begin
            minute <= minute + 1;
        end
        else begin
            minute <= minute;
        end
    end
	
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            second <= 6'd0;
        end 
        else if (second == 6'd60) begin
            second <= 6'd1;
        end
        else if (minute == 60) begin
            second <=0;
        end 
        else 
            second <= second + 1'd1;
    end
endmodule

5. 可置位计数器

  • 题意
    在这里插入图片描述
  • 思路

​ 首先明确number的取值逻辑,声明number变量为4位无符号数,数值每个时钟加一,则每次数值达到15,下一个时钟因为位宽的限制,自动变为1,可以实现十六进制计数。当set信号为1时,将set_num的值赋给number。

然后确定zero的取值逻辑,在默认情况下为0,当number=0时,zero值为1。

因为判断number4’d0需要一个时钟,zero信号为1,总是滞后number0一个时钟周期。所以可以考虑将number延迟一个时钟再输出。使用num变量代替上述的number,再通过以下语句实现number延迟一个时钟输出。【因为number是寄存器类型,无法通过组合逻辑进行阻塞赋值同时匹配。 如果直接使用number进行zero的判断来说,zero肯定是比number过“0”时刻慢一拍的; 所以不妨使用num_reg,进行延迟; 因为zero肯定是比num_reg慢一拍的,所以再通过num_reg延迟一拍给number,则number与zero同步输出匹配;】

  • 代码
`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] num;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            zero = 1'd0;
        end 
        else if (num == 4'd0) begin
            zero <= 1'b1;
        end 
        else begin
            zero <= 1'b0;
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            num <= 4'b0;
        end
        else if (set) begin
            num <= set_num;
        end
        else begin
            num <= num + 1'd1;
        end
    end

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

6. 加减计数器

  • 题意
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njD5fjwg-1690301397147)(https://s2.loli.net/2023/07/26/sOD1nVqmpaLbWyC.png)]

  • 思路

​ 首先确定zero的取值逻辑,在默认情况下为0,当number=0时,zero值为1。 always @(posedge clk or negedge rst_n)

​ 然后将mode的值作为if-else的判断条件,当mode为1时,number每个时钟周期加一,当mode为0时,number每个时钟周期减一。

​ 按照以上代码,因为判断number4’d0需要一个时钟,zero信号为1,总是滞后number0一个时钟周期。所以可以考虑将number延迟一个时钟再输出。使用num变量代替上述的number,再通过以下语句实现number延迟一个时钟输出。

  • 代码
`timescale 1ns/1ns

module count_module(
	input clk,
	input rst_n,
	input mode,
	output reg [3:0]number,
	output reg zero
	);
    reg [3:0] num;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            zero <= 1'd0;
        end
        else if (num == 4'd0) begin
            zero <= 1'b1;
        end
        else begin
            zero <= 1'b0;
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            num <= 4'b0;
        end 
        else if (mode) begin
            if (num == 9) 
				num <= 0;
            else 
				num <= num + 1'd1;
        end 
		else if (!mode) begin
            if (num == 0) num <= 9;
            else num <= num - 1'd1;
        end
        else 
			num <= num ;
    end

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

7.RAM的简单实现

  • 题意

image-20230725182928583

  • 思路

要实现RAM,首先要声明数据的存储空间,例如:[3:0] rom [7:0];变量名称ram之前的[3:0]表示每个数据具有多少位,指位宽;变量名称ram之后的[7:0]表示需要多少个数据,指深度,注意这里深度为8,应该是使用[7:0],而不是[2:0];

​ 声明存储变量之后,需要对ram进行初始化,写入数据,当write_en有效,向write_addr写入write_data,当read_en有效,根据输入的read_addr输出read_data。需要注意的是,题目要求实现真双端口RAM,即可以同时写入和读出,所以需要使用两个always语句块实现写入和读出逻辑,不可以在同一个always块中使用if-else if-else if结果。

  • 代码
`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] myRAM [7:0];
    reg [8:0] i;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (i = 0;i < 256;i = i+1)
                myRAM[i] = 0;
        end
        else begin
            myRAM[write_addr] <= write_en ? write_data:myRAM[write_addr];
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            read_data <= 0;
        end
        else 
            read_data <= read_en?myRAM[read_addr]:read_data;
    end
endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/787877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

需求管理全过程流程图及各阶段核心关注点详解

分析报告指出&#xff0c;多达76%的项目失败是因为差劲的需求管理&#xff0c;这个是项目失败的最主要原因&#xff0c;比落后的技术、进度失控或者混乱的变更管理还要关键。很多项目往往在开始的时候已经决定了失败&#xff0c;谜底就在谜面上&#xff0c;开始就注定的失败&am…

python-基本数据类型

hello&#xff0c;这里是Token_w的文章&#xff0c;主要讲解python的基础学习&#xff0c;希望对大家有所帮助 整理不易&#xff0c;感觉还不错的可以点赞收藏评论支持&#xff0c;感谢&#xff01; 有没有一个人&#xff0c;你想给TA传个小纸条&#xff1f;用恺撒密码一展身手…

【Docker】Docker Compose的配置与部署

文章目录 一、Docker Compose1. Docker Compose 的概述2. Docker Compose 三大的概念3. Docker Compose 环境安装 二、YAML 文件格式及编写注意事项1. YAML 文件格式2. YAML 格式的注意事项3. YAML 数据结构3.1 基本类型3.2 实例3.3 YAML 特殊类型文本块锚点与引用 三、Docker …

【【直流电机驱动PWN】】

直流电机驱动PWN 前面都是沙县小吃&#xff0c;这里才是满汉全席 直流电机是一种电能转化成机械能的装置 直流电机有两个电极 当电机正接 电机正转 当电机负接 电机倒转 电机还有步进电机 舵机 无刷电机 空心杯电机 因为电机是一个大功率器件并不太好直接接在IO端口上所以我…

2023 年牛客多校第一场题解(上)

A Almost Correct 题意&#xff1a;给定长度为 n n n 的 01 01 01 串 s s s&#xff0c;构造一个排序网络&#xff0c;使得能够将除 s s s 之外的任意 01 01 01 序列正确排序&#xff0c;且 s s s 无法被正确排序。 T T T 组测试&#xff0c; 1 ≤ T ≤ 1 0 4 1 \le T \…

ASEMI代理海矽美快恢复二极管SFP6002的特性和应用分析

编辑-Z 二极管SFP6002是一种常见的电子元件&#xff0c;也被称为快恢复二极管。它具有快速恢复时间和低反向恢复电流的特点&#xff0c;适用于高频电路和开关电源等应用。 SFP6002的主要特性包括&#xff1a; 1. 快速恢复时间&#xff1a;SFP6002具有快速的恢复时间&#xff…

Git Gui相关术语

文章目录 Git Gui主界面相关术语- Amend Last Commit&#xff08;修正最后一次提交&#xff09;- Rescan&#xff08;重新扫描&#xff09;- Sign Off&#xff08;签名&#xff09;- Stage Changed Git Gui Commit菜单相关术语- Stage to Commit&#xff08;暂存到提交&#xf…

Ceph组件

Ceph组件 无论是想向云平台提供Ceph 对象存和 Ceph 块设备服务、部署Ceph 文件系统,或者是将 Ceph 用于其他目的,所有 Ceph 存储集群部署都从设置每个 Ceph 节点、网络开始。 一个Ceph 存储集群至少需要一个Ceph Monitor、Ceph Manager和 Ceph OSD (OBJECT STORAGE DAEMON对象存…

【MySQL】十三,索引的代价、MySQL数据结构选择的合理性

索引的代价 空间上的代价 每建立一个索引都要为它建立一棵B树&#xff0c;每一棵B树的每一个节点都是一个数据页&#xff0c;一个页默认会占用 16KB 的存储空间&#xff0c;一棵很大的B树由许多数据页组成&#xff0c;那就是很大的一片存储空间。 时间上的代价 每次对表中的…

前端开发中的常见优化

目录 外观 兼容 不同尺寸&#xff08;包裹&#xff0c;height:100%&#xff09; 不同 浏览器 隐藏滚动条 的 不同属性名 重排->重绘 不显示 display:none->禁用disable 性能 导航重复&#xff08;修改原型push、replace方法&#xff09; 搜索防抖 import { debo…

【Docker】Docker私有仓库管理

目录 一 、Harbor 简介1.1 什么是Harbor1.2Harbor的特性1.3Harbor的构成 二、Harbor部署2.1 部署 Docker-Compose 服务2.2 部署 Harbor 服务2.3启动Harbor2.4 创建一个新项目2.5 在其他客户端上传镜像 三、配置Harbor 高可用四、维护管理Harbor4.1. 通过 Harbor Web 创建项目4.…

提升Web3安全性和用户体验:元事务和加密技术的应用

在Web3中&#xff0c;去中心化应用程序&#xff08;DApps&#xff09;是一种基于区块链技术的应用程序&#xff0c;它们通过智能合约实现透明、安全、去中心化的业务逻辑。然而&#xff0c;DApps的使用门槛比传统的中心化应用程序更高&#xff0c;需要用户具备一定的技术知识&a…

python简单入门

python简单入门 文章目录 python简单入门[toc] 地址链接1. 官网2. 下载地址3. 官方文档 1. 第一章1.1 python解释器1.2 基础语法1.2.1 常见数据类型1.2.2 强制类型转换1.2.3 注释1.2.4 运算符1.2.5 字符串1.2.5.1 字符串的定义1.2.5.2 字符串拼接1.2.5.3 格式化字符串1.2.5.3 精…

profinet 调试记录

一、 树莓派运行codesys runtime Codesys control for Raspberry Pi (外网) 链接&#xff1a;https://pan.baidu.com/s/1vgURlEG_y4C5rj7rALdOdQ?pwdfkhr 提取码&#xff1a;fkhr 1. 用户名称要以 root 登录 若是普通用户&#xff0c;会提示&#xff1a;脚本必须以 root 身…

Facebook Messenger市场营销,跨境电商不可忽略的营销手段

营销始于广告。广告仍然是不可或缺的&#xff0c;但广告的方式正在发生变化。以前商家会使用广告邮件或者直接转到网站上的产品页面&#xff0c;但是这两种方法都存在很大问题。虽然企业可以通过电子邮件与潜在客户保持联系&#xff0c;但不能保证这些潜在客户会真正看广告邮件…

【算法与数据结构】104、111、LeetCode二叉树的最大/最小深度

文章目录 一、题目二、层序遍历法三、递归法四、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、层序遍历法 思路分析&#xff1a;两道题都可以用层序遍历&#xff08;迭代法&#xff09;来做&#xff0c;遍历完…

通付盾获苏州市工业互联网产业联盟“工业互联网看苏州”先锋企业

近日&#xff0c;苏州市工业互联网产业联盟公布2022年度苏州市工业互联网产业联盟系列评选获评名单&#xff0c;通付盾荣获“工业互联网看苏州”先锋企业。 为加快推动工业互联网在数字赋能产业创新集群融合发展中发挥更显著作用&#xff0c;进一步完善苏州市工业互联网产业生态…

Docker Compose 容器编排 + Docker--harbor私有仓库部署与管理

目录 一、Docker Compose简介 1、Docker Compose 的YAML 文件格式及编写注意事项 2、Docker compose 使用的三个步骤 3、 Docker Compose配置常用字段 4、 Docker Compose 常用命令 5、 Docker Compose 文件结构 二&#xff1a; Docker Compose 安装 1、Docker Compose…

【C#】并行编程实战:基于任务的异步编程基础(下)

第八章介绍了 C# 中可用异步编程的实践和解决方案&#xff0c;还讨论了何时适合使用异步编程等。本章主要介绍 async 和 await 关键字。 其实在之前的学习中&#xff0c;大家都已经了解过这两个关键字了&#xff0c;用得非常多。其实我觉得没有必要再赘述了&#xff0c;不过这里…

Git简介与工作原理:了解Git的基本概念、版本控制系统和分布式版本控制的工作原理

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…