EGO-Link FPGA智慧教育社区介绍:用 leetcode 的方式练习 verilog 语言

news2024/11/16 4:25:18

文章目录

  • 介绍
    • FPGA
  • 语法
  • 例1:P1203 1输入1输出
  • 例2:P1204 3输入4输出
  • 例3:P1207 P1208 P1205 与或非门
  • 例4:P1200 半加器
  • 例5:P1201 4位二进制转余3循环码
  • 例6:P1215 2选1多路选择器
  • 例7:P1236 D触发器
  • 例8:P1246 4位移位寄存器

介绍

本课程笔记是基于依元素科技公司与北京邮电大学开展的 FPGA 创新工坊课程学习 verilog 代码。

image-20230408080815380 image-20230408080713484

主要就是在其的社区平台上写 verilog 代码练习。平台链接:https://www.ego-link.com/#/problem-list 注册账号,练习题都在题库里,用类似 leetcode 刷题的方式学习。

FPGA

现场可编程门阵列。可以在芯片内部绘制用编程软件绘制和擦除电路。大概就是编程来决定内部电路结构的芯片。

FPGA 内部有各种各样可编程门电路(如与或非),其编程能力取决于可编程单元的数量。通过阵列的形式排列。

门电路断电后功能擦除,再上电重新写入,因此被称为可擦除。

image-20230408082158373

本次课程更多使用 Verilog 语言。

现在的 FPGA 芯片也不仅仅局限于这些功能,可以有一些网络接口,存储器,DPU(深度学习处理单元,学 AI 用的)等。

image-20230408083957295

如果感兴趣建议入门从 EGO1 开始学习,b站同名up就有相关学习课。

语法

电路主要分为组合逻辑电路(输出仅和现在的输入有关),时序逻辑电路(和输入以及过去电路的历史状态有关)。

首先熟悉一下程序架构:

image-20230409202319152

module:我们写的这一整个内容可以看做是一个函数/模块,module。

输入:input 类型。

输出:output 类型。

我们要做的是把 input 类型转换为想要的 output 结果。

例1:P1203 1输入1输出

题目描述

请构建一个具有一个输入和一个输出的模块,请用组合逻辑实现,其输出端口和输入端口信号关系如下:
out <- in(将in连续赋值给out)

与物理导线不同,Verilog中的导线(和其他信号)是定向的。这意味着信息只在一个方向上流动,从(通常是一个)源到接收器(源通常也称为将值驱动到导线上的驱动程序)。在Verilog的assign语句中,右侧信号的值被驱动到左侧的导线上,其赋值是“连续的”,因为即使右侧的值发生变化,赋值也会一直持续,注意连续分配不是一次性事件。

如下right_side的信号会连续赋值给left_side 。
assign left_side = right_side;

要求很简单,把输入赋值给输出原封不动即可。

主要是语法如何赋值。用 assign 关键词赋值。

assign:连续赋值,比如 in 的值更新了 out 也会实时更新。assign 类似 return。

// Verilog Solution:

module top_module(
    // 输入信号
    input in,
    // 输出信号
    output out
);


// write your code here

assign out=in;//把 in 的值赋给 out

endmodule

类似 leetcode,给定了一些数据结构和函数,我们只需要在需要写代码的地方补充代码即可。

例2:P1204 3输入4输出

请构建一个具有 3 个输入和 4 个输出的模块,请用组合逻辑实现,其行为类似于建立这些连接的导线:
w <- a
x <- b
y <- b
z <- c

在设计实现中你会使用到assign语句,当设计中有多个assign赋值语句时,它们在代码中的显示顺序无关紧要。需要理解的是assign赋值语句(“连续赋值”)是描述事物之间的联系,而不是将值从一个事物复制到另一个事物的操作。
这里还需澄清的一个潜在的混淆:上图的绿色箭头表示电线之间的连接,但本身不是电线。该模块本身已经声明了 7 根导线(命名为 a、b、c、w、x、y 和 z),assign语句不是在创建导线,而是在已存在的7根导线之间创建连接。

image-20230414082453700
和例1很像,主要就是如何正确的把多个 input 按要求赋值给多个 output。

assign w=a;
assign x=b;
assign y=b;
assign z=c;

例3:P1207 P1208 P1205 与或非门

与门(英语:AND gate)又称“与电路”、逻辑“积”、逻辑“与”电路。是执行“与”运算的基本逻辑门电路。有多个输入端,一个输出端。当所有的输入同时为高电平(逻辑1)时,输出才为高电平,否则输出为低电平(逻辑0)。

与门的真值表为:

输入in0输入in1输出out
000
010
100
111

或门(OR gate),又称或电路、逻辑和电路。如果几个条件中,只要有一个条件得到满足,某事件就会发生,这种关系叫做“或”逻辑关系。具有“或”逻辑关系的电路叫做或门。或门有多个输入端,一个输出端,只要输入中有一个为高电平时(逻辑“1”),输出就为高电平(逻辑“1”);只有当所有的输入全为低电平(逻辑“0”)时,输出才为低电平(逻辑“0”)。

或门的真值表:

输入in0输入in1输出out
000
011
101
111

非门(英文:NOT gate)又称非电路、反相器、倒相器、逻辑否定电路,简称非门,是逻辑电路的基本单元。非门有一个输入和一个输出端。当其输入端为高电平(逻辑1)时输出端为低电平(逻辑0),当其输入端为低电平时输出端为高电平。也就是说,输入端和输出端的电平状态总是反相的。非门的逻辑功能相当于逻辑代数中的非,电路功能相当于反相,这种运算亦称非运算。

非门的真值表:

输入in输出out
01
10

这里就是简单的数电概念了,对于2个输入 in0 in1,求其与和或的结果;对于一个输入 in,求其非的结果。

语法:& | ! 是针对单位 bit 的逻辑运算。&& || ~ 是多位的逻辑运算。这里 in0 和 in1 都是单位 bit ,用 & 或 && 都行。(可以试一下 P1206 4位非门,令 out=!in; 就是错误的因为需要有多位取反,~ 就正确。)

assign out=in0&in1;
assign out=in0|in1;
assign out=!in;

还有几道与非,或非,同或的题是根据与或非的结合去计算的,也比较简单可以练手。

例4:P1200 半加器

半加器电路是指对两个输入数据位相加,输出一个结果位和进位,没有进位输入的加法器电路。 是实现两个一位二进制数的加法运算电路,即不考虑低位有无向本位的进位,只将两个本位数相加的运算。

以下是1位半加器的真值表,其中x和y是加数,c_out是向高位的进位信号,sum是和:

输入输出
xysumc_out
0000
0110
1010
1101

也是很简单的电路,就是求x+y。如果进位了,c_out=1。sum =x+y的最低位。比如1+1=10,进位 c_out=1,sum 最低位=0。

可以令 sum=x+y; 因为 sum x y 都是1位的,即使 x=1 y=1,相加后也会溢出,sum 得到的值仍是0. 然后 c_out=x&y; 因为只有两者同时==1 时才会进位。

也可以采用异或运算 sum=x^y; 异或运算是当 x!=y 时,结果=1,否则结果=0,也符合半加器的进位机制。(可以尝试 P1211 异或题。)

例5:P1201 4位二进制转余3循环码

格雷码,又叫循环二进制码或反射二进制码,格雷码是一个有序的2的N次方个二进制码,格雷码是我们在工程中常会遇到的一种编码方式,格雷码的特点是从一个数变为相邻的一个数时,只有一个数据位发生跳变,由于这种特点,就可以避免二进制编码计数组合电路中出现的亚稳态。格雷码常用于通信,FIFO或者RAM地址寻址计数器中。

十进制数binary[3:0](自然二进制数)gray[3:0](格雷码)十进制数binary[3:0](自然二进制数)gray[3:0](格雷码)
000000000810001100
100010001910011101
2001000111010101111
3001100101110111110
4010001101211001010
5010101111311011011
6011001011411101001
7011101001511111000

4位2进制转格雷码方法如下:

img
首先介绍一下 verilog 的多位寄存器定义。这次题目定义如下:

module top_module(
    // 4位二进制数输入
    input [3:0] binary,
    // 4位格雷码输出
    output [3:0] gray
);

前面接触的变量大多数变量都是一位的,比如 input in 就是定义了一个比特的 in 寄存器。如果我们给一位的寄存器赋值会自动截取最低位的值,比如 assign out=2; 2 的二进制是10,也就是 out 得到的值只是末尾的0.

如果 input[3:0] in 是定义了一个4位的寄存器,用法很像 C 语言的数组。4位从高到低分别是 in[3], in[2], in[1], in[0]。

我们可以单独给其中一个或者几个单元赋值,比如 output[3:0] outassign out[2]=1; assign out[0]=0;

也可以比如 out[3:2]=2; 给前两位赋值10.

貌似也可以 output[0:3] out 去定义,连续赋值的时候也必须从小到大,如 out[2:3]=2; .不过约定俗成大家一般都规定高位索引值高,低位索引值低。

这道题根据图片公式,我们给每个位和他左边相邻的位进行异或,求得本位的值。

assign gray[0]=binary[0]^binary[1];
assign gray[1]=binary[1]^binary[2];
assign gray[2]=binary[2]^binary[3];
assign gray[3]=binary[3];

也可以用一个大括号赋值,用逗号分割。

assign gray={binary[3],binary[2]^binary[3],binary[1]^binary[2],binary[0]^binary[1]};

这种赋值方式不是说必须局限于写4个 1bit 的值。可以 assign gray={binary[3:2],binary[1],binary[1]}; 形如这样,相当于把 binary[3:2] 赋值给 gray[3:2],binary[1] 赋值给 gray[1] gray[0]。总长度是一样的就行。

除此以外还可以复制重复多次赋值。

image-20230408144833865

对于常数,可能会看到 4'b1011 类似这样的形式。第一个数字表示:这个常数转换为二进制之后,一共有多少位。然后加一个’,然后是一个字母表示后面的数字是以二进制形式/十进制形式/十六进制形式传入。b是二进制,d是十进制,h是十六进制。

8’b1011_1011: 二进制数 1011 1011,即十进制187。_是分隔每四位数字的符号,写不写都行,就是看起来方便一点。

3’d7:十进制数7,二进制数111.

4’ha:十六进制数a,十进制数10,二进制数1010.

例6:P1215 2选1多路选择器

多路选择器是数据选择器的别称。在多路数据传送过程中,能够根据需要将其中任意一路选出来的电路,叫做数据选择器,也称多路选择器或多路开关。
2选1多路选择器的电路图为
image-20230414082728584>
以下为2选1多路选择器的真值表,其中s为控制信号,d0,d1为两个输入信号,y为输出信号。当s为低电平时,输出y=d0,当s为高电平时,输出y=d1。

输入d0输入d1输入s输出y
0000
0100
1001
1101
0010
1010
0111
1111

请参考真值表构建一个二选一多路选择器,要求组合逻辑实现。

module top_module(
    // 输入信号d0
    input d0,
    // 输入信号d1
    input d1,
    // 选择信号s
    input s,
    // 输出信号y
    output y
);

题目大意:当 s1 时,y=d1. 当 s0 时,y==d0.

也就是说这里需要用到的语法是逻辑判断和条件结构。

先说逻辑判断,和c语言类似,==判断两个变量是否值相等,>= <= < > 判断大小比较,!= 判断是否不相等,表达式返回结果是1 或 0.

再说 if else 条件判断语句。

always @(*) begin	// always 这里是固定语法,if for case 都要嵌套在 always end 里面,先记住就好
    if(condition) begin
        
    end
    else if(condition) begin
        
    end
    else(condition) begin
        
    end
end

如果if 后面只有一个执行语句,可以省去 begin end。

always @(*) begin	
    if(condition) 
    	statement;
    else if(condition) 
        statement;
    else(condition) 
        statement;
end

然后还需要介绍两个数据类型:wire 和 reg。

我们前面赋值基本都是直接给 output 类型输出赋值的,这是没有问题的。但是如果我们需要自己定义一个中间变量,用 assign 赋值,必须定义为 wire 类型,因为规定如此,只有 wire 数据类型可以被 assign 赋值。

wire[3:0] out_temp;
assign out_temp[3]=1;

而在 always end 内部如果我们想给变量赋值,还不太一样。首先,always 内部不能用 assign 赋值。

然后,always 内部只有 reg 数据类型可以被赋值,output 变量都不行。

module top_module(output out);
always @(*) begin
	assign out=1;//wrong
end
endmodule

解决方法如下三种:

module top_module(output out);
reg out_temp;
always @(*) begin
	out_temp=1;//success, 不用 assign 直接赋值
end
    assign out=out_temp;//success
endmodule 
module top_module(output reg out);
    always @(*) begin
	out=1;//success,out 是 output (输出)类型,reg 数据类型的变量
end
endmodule 
module top_module(output out);
reg out;//和第二种方法等效
    always @(*) begin
	out=1;//success
end
endmodule 

所以此题我们可以在 always if 的条件判断里先赋给一个临时变量,always 结束后再赋值给 output y。

命名的话有人用 _r 表示是一个 reg 变量,有人用 _t 代表是一个临时的变量。

  reg y_r;
  always @(*) begin
    if(s==1)
      y_r=d1;
    else 
      y_r=d0;
  end
  assign y=y_r;

除了 if,还可以使用 case。case 重在对于一个数的不同的值的比较。

  reg y_r;
  always @(*) begin
      case(s)//根据s的值判断执行什么语句
      1:y_r=d1;//s==1要执行的内容
      0:y_r=d0;//s==0要执行的内容
      default:;//如果不满足以上情况需要执行的内容。default 必须写
      endcase//结束 case 语句,必须写
  end
  assign y=y_r;

还可以使用三目运算符,这是最简单的一个条件判断式。形如:(condition)?如果condition为true要执行的语句:如果condition为false要执行的语句; 这个语句也不用在 always 里。

assign y=(s)?d1:d0;

例7:P1236 D触发器

D触发器是一个具有记忆功能的,具有两个稳定状态的信息存储器件,是构成多种时序电路的最基本逻辑单元,也是数字逻辑电路中一种重要的单元电路。
因此,D触发器在数字系统和计算机中有着广泛的应用。触发器具有两个稳定状态,即"0"和"1",在一定的外界信号作用下,可以从一个稳定状态翻转到另一个稳定状态。
D触发器有集成触发器和门电路组成的触发器。触发方式有电平触发和边沿触发两种,前者在时钟脉冲=1时即可触发,后者多在时钟脉冲的前沿(正跳变0→1)触发。
D触发器的次态取决于触发前D端的状态,即次态=D。因此,它具有置0、置1两种功能。
对于边沿D触发器,由于在时钟脉冲=1期间电路具有维持阻塞作用,所以在时钟脉冲=1期间,D端的数据状态变化,不会影响触发器的输出状态。
D触发器应用很广,可用做数字信号的寄存,移位寄存,分频和波形发生器等等。

以下1bit D触发器的真值表:

输入输出
dclkq
0上升沿0
1上升沿1
x下降沿保持不变
x0保持不变
x1保持不变

请根据以上真值表构建一个1比特时钟上升沿触发的D触发器。

这里主要是涉及到“上升沿”和“下降沿”信号的处理。

always @(*) begin 的意思是括号内的条件满足时,就会触发。如果是 * ,就是信号变化时就触发后跟的语句。

如果括号内换成上升沿或下降沿的条件,就可以在上升沿和下降沿触发某些指令。

语法:posedge clk,指时钟上升沿触发;negedge clk,指时钟下降沿触发。

module top_module(
    // D触发器数据输入端
    input d,
    // D触发器时钟输入端
    input clk,
    // D触发器数据输出端
    output q
);

	reg tmp;
  	always@(posedge clk) begin
    	tmp \<\= d;
  	end
	assign q = tmp;
    
endmodule

这里可以注意到使用了一个奇怪的赋值符号:<=。他的意思是这个符号赋值的变量不是按顺序赋值的,而是同一时间赋值的。这种赋值叫非阻塞赋值,而=叫阻塞赋值,即串行进行赋值。

例8:P1246 4位移位寄存器

移位寄存器内的数据可以在移位脉冲(时钟信号)的作用下依次左移或右移。移位寄存器不仅可以存储数据,还可以用来实现数据的串并转换、分频,构成序列码发生器、序列码检测器,进行数值运算以及数据处理等,它也是数字系统中应用非常广泛的时序逻辑部件之一。

移位寄存器按数据移位方向分类:可以分为左移寄存器和右移寄存器。请构建一个位宽为4位的移位寄存器,既能实现左移寄存器,又能实现右移寄存器。左移寄存器其功能为当时钟上升沿到达时,输入信号的最高位移位到最低位,其余各位依次向左移动一位。同理,右移寄存器其功能为当时钟上升沿到达时,输入信号的最低位移位到最高位,其余各位依次向右移动一位。

其中ena为移位方向使能信号,当ena值为1时,实现右移寄存器;当ena值为2时,实现左移寄存器。d为输入端数据信号,q为输出端数据信号。
image-20230414082351809

这道题,对于时钟信号的上升沿我们已经学过语法了,难的地方在于怎么实现“移位”。

移位不是单纯的 << >> ,因为这样不会把移溢出的位放到另一侧,而是直接补0或1. 如果想实现循环移位,需要我们手动赋值,比如d[15:0],新赋值后的寄存器值={d[3:0],d[15,4]},左移同理。

module top_module(
    // 输入时钟
    input clk,
    // 全局复位高有效
    input rst,
    // 移位方向使能信号
    input [1:0] ena,
    // 输入数据
    input [3:0] d,
    // 输出数据
    output [3:0] q
);


// write your code here

reg[3:0] q_r;
always @(posedge clk) begin
  	if(rst) q_r<=4'b0;
    else if(!ena) q_r<=4'b0;
    else if(ena==1) begin
    	q_r<={d[0],d[3:1]};
	end
    else if(ena==2) begin
    	q_r<={d[2:0],d[3]};
  	end
end
assign q=q_r;

endmodule

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

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

相关文章

【C语言】浅涉结构体(声明、定义、类型、定义及初始化、成员访问及传参)

简单不先于复杂&#xff0c;而是在复杂之后。 目录 1. 结构体的声明 1.1 结构体的基础知识 1.2 结构的声明 1.3 结构成员的类型 1.4 结构体变量的定义和初始化 2. 结构体成员的访问 3. 结构体传参 1. 结构体的声明 1.1 结构体的基础知识 结构是一些值的集合&…

探索Apache Hudi核心概念 (4) - Clustering

Clustering是Hudi在0.7.0版本引入的一项特性&#xff0c;用于优化文件布局&#xff0c;提升读写性能&#xff0c;现在它已经成为Hudi的一项重要性能优化手段。本文我们会通过Notebook介绍并演示Clustering的运行机制&#xff0c;帮助您理解其工作原理和相关配置。 1. 运行 Not…

RocketMQ 多级存储设计与实现

作者&#xff1a;张森泽 随着 RocketMQ 5.1.0 的正式发布&#xff0c;多级存储作为 RocketMQ 一个新的独立模块到达了 Technical Preview 里程碑&#xff1a;允许用户将消息从本地磁盘卸载到其他更便宜的存储介质&#xff0c;可以用较低的成本延长消息保留时间。本文详细介绍 …

记录贴:EasyPoi word导出问题一览

项目场景&#xff1a; EasyPoi word导出 问题描述1 easypoi 模板导出 我直接在map的value输入空格或"",出来的是{{,两个左花括号,咋解决 解决方案&#xff1a; exportMap.put("key", "\u00A0"); //空格前端效果&#xff1a; 其他无效解决方案…

Redis安装配置操作记录

Redis 官网&#xff1a;https://redis.io/ 中文文档&#xff1a;https://www.redis.com.cn/documentation.html 在线命令参考&#xff1a;http://doc.redisfans.com 一&#xff0c;Redis下载安装与配置 下载网站&#xff0c;可下载安装包然后安装或可使用brew来安装Redis&#…

LeetCode——前K个高频单词

692. 前K个高频单词 给定一个单词列表 words 和一个整数 k &#xff0c;返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c; 按字典顺序 排序。 示例 1&#xff1a; 输入: words [“i”, “love”, “le…

太阳能电池测试解决方案NS-9001

前言 太阳能行业的快速发展提高了对太阳能电池测试和精确测量解决方案要求&#xff0c;伴随着太阳能电池尺寸大小质量的提升&#xff0c;充电电池测试必须更多的电流和更高输出功率水准&#xff0c;这就更加需要灵活多变的测试方案支持。 现阶段&#xff0c;太阳能电池测试 解…

Java学习星球,Java学习路线

目录 一、Java学习路线二、学习计划三、为何会有Java学习星球&#xff1f;四、加入星球后&#xff0c;你可以得到什么&#xff1f;五、如何加入Java学习星球&#xff1f;六、打卡挑战 大家好&#xff0c;我是哪吒&#xff0c;一个靠着热情攀登至C站巅峰的中年男子&#xff0c;C…

【历史上的今天】3 月 20 日:cURL 二十五周年;Docker 发布;思科收购 Linksys

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 3 月 20 日&#xff0c;在 1999 年的今天&#xff0c;人类首次成功乘热气球环球飞行。在 24 年的今天&#xff0c;瑞士人皮尔卡、英国人琼斯经过近 20 天的飞行…

JavaWeb—HTTP协议

目录 1.HTTP协议 1.1 HTTP-概述 1.1.1 介绍 2.1.2 特点 1.2 HTTP-请求协议 HTTP-请求数据格式 GET请求和POST请求的区别&#xff1a; 1.3 HTTP-响应协议 1.3.1 格式介绍 1.3.2 响应状态码 常见响应状态码 1.4 HTTP-协议解析 1.HTTP协议 1.1 HTTP-概述 1.1.1 介绍 HTT…

ModuleNotFoundError: No module named ‘cuda‘、‘tensorrt‘

1、 ModuleNotFoundError: No module named ‘cuda’ python -m pip install --upgrade pip pip install cuda-python2、 ModuleNotFoundError: No module named ‘tensorrt’ 2.1 依赖库 先安装两个TensorRT的依赖库 python -m pip install --upgrade pip pip install nvi…

openstack compute schedulers

https://docs.openstack.org/nova/latest/admin/scheduling.html 在默认的配置中&#xff0c;调度器将考虑如下的几个方面&#xff1a; 请求的是Availability Zonenova-compute服务在目标节点上是启用的满足实例类型的extra specs&#xff08;ComputeCapabilityesFilter&#…

Spring Boot Web

一. 概述 下面我们将进入 SpringBoot 基础阶段的学习。 在没有正式的学习 SpringBoot 之前&#xff0c;我们要先来了解下什么是 Spring 。 我们可以打开 Spring 的官网 ( https://spring.io ) &#xff0c;去看一下 Spring 的简介&#xff1a; Spring makes Java simple 。…

UUID无处不在,你就是唯一(2023.4.16)

六种语言生成UUID 2023.4.16 引言1、UUID简介2、UUID格式和编码3、UUID各历史版本4、UUID代码具体调用实现4.1 C# 生成UUID4.2 Java 生成UUID4.3 Python 生成UUID4.4 C 生成UUID4.5 C 生成UUID4.6 JavaScript 生成UUID&#xff08;较为实用&#xff09;4.6.1 控制台运行&#x…

测绘与设计之间的鸿沟:坐标系,教你如何将CAD与测绘数据准确叠加

一、背景 2008年&#xff0c;我国推出了2000国家大地坐标系&#xff08;以下简称国家2000坐标系&#xff09;&#xff0c;截至2022年&#xff0c;国家2000坐标系在自然资源领域已经取得了较高的普及率&#xff0c;但在工程建设领域的普及率依旧比较低&#xff0c;很多工程项目…

23种设计模式(9)——适配器模式

目录 一、基本介绍 二、demo 2.1、类适配器模式 类适配器模式注意事项和细节 2.2、对象适配器模式 对象适配器模式注意事项和细节 2.3、接口适配器模式 接口适配器模式介绍 三、适配器模式在框架中的应用 3.1在 SpringMVC 框架应用 3.2、spring AOP中的适配器模式 一、…

如何制作实时库存报表

草料二维码暂不支持自动计算功能&#xff0c;无法看到实时的库存数量。但可以使用外部数据分析工具&#xff0c;如百度Sugar&#xff0c;连接草料二维码官方数据库&#xff0c;即可自由实现各类计算&#xff0c;包括实时库存。 一、案例效果 输入物料名称&#xff0c;即可快速…

oracle学习之rownum和rowid

rownum先百度一波https://www.cnblogs.com/xfeiyun/p/16355165.html rownum是oracle特有的一个关键字。 对于基表&#xff0c;在insert记录时&#xff0c;oracle就按照insert的顺序&#xff0c;将rownum分配给每一行记录&#xff0c;因此在select一个基表的时候&#xff0c;r…

Java基础(八)异常处理

1. 异常概述 1.1 什么是生活的异常 男主角小明每天开车上班&#xff0c;正常车程1小时。但是&#xff0c;不出意外的话&#xff0c;可能会出现意外。 出现意外&#xff0c;即为异常情况。我们会做相应的处理。如果不处理&#xff0c;到不了公司。处理完了&#xff0c;就可以…

Ubuntu下打开QtCreator,环境变量(PATH、LD_LIBRARY_PATH等)与预期不一致的问题

现象展示 在Ubuntu中&#xff0c;安装好Qt之后&#xff0c;可以在系统桌面的左下角找到启动图标 但是&#xff0c;这种方式启动的QtCreator所读取到的环境变量和我们从命令行读取到的不一致&#xff1a; 可以看到&#xff0c;明显少了这个&#xff1a;/opt/ros/humble/bin 因…