SystemVerilog学习笔记(十一):接口

在Verilog中,模块之间的通信是使用模块端口指定的。

Verilog模块连接的缺点

  • 声明必须在多个模块中重复。
  • 存在声明不匹配的风险。
  • 设计规格的更改可能需要修改多个模块。

接口

SystemVerilog引入了 interface 结构,它封装了模块之间的通信。一个 interface 是一组信号或线路,通过它测试台与设计进行通信。

序号数据类型
1.接口
2.参数化接口
3.Modports
4.时钟块
5.虚拟接口

interface1

接口结构用于连接设计和测试台。

不使用Interface的Systemverilog

下图显示了不使用接口连接设计和测试台的情况。

int Diagram

SystemVerilog接口

下图显示了使用接口连接设计和测试台的情况。

interface Diagram


语法:

interface (interface_name) ([port_list]);  
 [list_of_signals]    
endinterface  

示例:

接口声明

interface and_if; 
 logic input_a,input_b,output_y;      
endinterface    

int

这里的接口由一组信号组成,在测试模块中,我们调用接口句柄,但我们没有声明信号的方向。在测试模块中,我们将 a_input 和 b_input 的值传递给接口。在顶层模块中,我们使用接口实例化 DUT 信号。DUT 的输出 ‘y’ 通过接口发送到测试模块。接口中没有使用 modport。我们可以通过在信号上声明 ‘/’ 来声明每个信号的大小。这用于知道信号的矢量大小。

AND门的顶层模块

    //Here the interface,testbench,design module are called.
    module top();
    
    //interface module
    and_if inf();
    
    //design module instantiate
    andg a1(.input_a(inf.input_a), .input_b(inf.input_b), .output_y(inf.output_y));
    
    //testbench
    tb a2(inf);
    
    endmodule:top

Design code for AND gate

     //module declaration  
     module andg(input_a,input_b,output_y);  
     input input_a,input_b;  
     output output_y;  
     //assign output  
     assign output_y=input_a&input_b;  
     endmodule:andg  

Testbench for AND gate

     //testbench for and gate  
     module tb(and_if inf);  
     initial begin  
     $display("\n// and gate output");  
     $monitor("\ninput_a=%b\t input_b=%b\t output_y=%b",inf.input_a,inf.input_b,inf.output_y);  
     inf.input_a = 0; inf.input_b = 0;  
     #1;  
     inf.input_a = 1; inf.input_b = 0;  
     #1;  
     inf.input_a = 0; inf.input_b = 1;  
     #1;  
     inf.input_a = 1; inf.input_b = 1;  
     end  
     endmodule:tb  

下图显示了使用接口的AND门的输出。

interface 1png

SystemVerilog接口的优点

  • 在Verilog中,添加新信号时,必须手动更改模块实例化的每个地方。SystemVerilog使得在接口块中为现有连接添加新信号变得更加容易。
  • 它增加了跨项目的可重用性。
  • 一组信号可以通过其句柄轻松共享在组件之间传递。
  • 它提供方向信息(modports)和时序信息(时钟块)。

参数化接口

可以在接口中使用参数,使用Verilog的参数重新定义构造使接口内部的向量大小和其他声明可重新配置。

语法:

interface (interface_name) #(parameter parameter_name = initialize);
 [list_of_signals]    
endinterface

示例:

interface count_if #(parameter N=2) ;  
logic reset,clk;  
logic [N:0] counter;
endinterface:count_if

计数器的顶层模块

    //Here the interface,testbench,design module are called.
     module top();
   
    //parameterised interface
     count_if inf();
  
    //design code of up_counter
    up_counter u1(.clk(inf.clk), .reset(inf.reset), .counter(inf.counter));
 
    //testbench for up_counter
    upcounter_testbench u2(inf);
 
    endmodule:top

计数器的设计代码

     //Design code for up counter
     module up_counter(clk,reset,counter);
     input clk, reset;
     output [2:0] counter;
     reg [2:0] counter_up;
     //up counter
     always @(posedge clk or posedge reset)
     begin
     //if reset=0 count will be incremented
     if(reset)
       counter_up <= 3'd0;
       else
       counter_up <= counter_up + 3'd1;
     end 
     assign counter = counter_up;
     endmodule:up_counter

计数器的测试台(Test bench)

     //testbench for up counter
     module upcounter_testbench(count_if inf);
     initial begin
     $display("\n // Parameterised interface example");
     //used to monitor the count values
     $monitor("\ncount=%0d",inf.counter);
     inf.clk=0;
     forever #5 inf.clk=~inf.clk;
     end
     initial begin
     inf.reset=1;
     #20;
     inf.reset=0;
     #70 $finish;
     end
     endmodule:upcounter_testbench

这里我们考虑了3位输出,其中计数器从0计数到7。

下图显示了带有参数化接口的计数器的输出。

para_interf1


通过两种方式可以更新参数值

  • 传递常量值
  • 使用‘defparam’关键字

传递常量值

在这种情况下,参数的值通过顶层模块实例化接口传递给接口。
例如: count_if#(2) intf();
count_if 是接口名称。
#(2)- 是传递给接口模块的参数值。

示例:

接口模块

     interface count_if #(parameter N);
     logic rst,clk;  
     logic [N:0] counter;  
     logic [N:0] counter_up;   
     endinterface:count_if  

顶层模块

     module top();  

    //parameterised interface  
    //pass by constant value  
    count_if#(2) intf();  

    //design code of up_counter  
    up_counter u1(intf);  

    //testbench for up_counter  
    upcounter_testbench u2(intf);  

    endmodule:top  

输出

下图中的图,up_counter的输出从0计数到7。这里参数的值通过顶层模块实例化中的接口传递。

pass_value


使用‘defparam’关键字

defparam 用于通过使用层次名称实例来覆盖参数值。defparam允许在编译时更改参数值。

例如: defparam intf.N=1;
这里intf是接口的句柄。
N是参数。
接口模块

     interface count_if #(parameter N=4);
     // declaration of design signals
     logic rst,clk;
     logic [N:0] counter;
     logic [N:0] counter_up;
     endinterface:count_if

顶层模块

     module top();

     //parameterised interface
     count_if intf();

     //Declaration of defparam 
     defparam intf.N=1;

     //instantiation of design module
     up_counter u1(intf);

     //testbench for up_counter
     upcounter_testbench u2(intf);

     endmodule:top

输出:

下图中的图8显示,接口参数值N=4。但是通过使用关键字defparam,在顶层模块实例化时,我们可以覆盖参数的值。

defparam_output


模块端口

  • Modport 用于指定在接口内声明的信号的端口方向。modport 在接口内部用关键字 modport 声明。
  • Modport 是模块端口的缩写。

Modport 的特点:

  • 可以具有输入、双向和输出。
  • 通过指定端口方向,modport 为信号提供访问限制。
  • 接口可以有任意数量的 modport,接口中声明的信号可以分组在多个 modport 中。
  • modport 可综合化。

语法:

modport identifier (input <port_list>, output<port_list>);

示例:

interface and_intr;    
  logic p,q;  
  logic r;  
  modport DUT_MP(input p,input q,output r);   
  modport TB_MP(output p,output q,input r);  
endinterface : and_intr  

AND 门的顶层模块,在测试台和设计文件中调用 modport 名称:

     // creating top module 
     // in this file design,testbench,interface modules are called
     module top();
     // interfce module called
     and_intr inf();
     // design module called
     and_gate a1(inf);
     // testbench module called   
     tb a2(inf);
     endmodule : top

AND 门的设计文件:

     // and gate design file  
     // module defination for and gate with interface instanciation  
     module and_gate(and_intr inf);
     // assign the output using continuous assignment
       assign inf.DUT_MP.r = (inf.DUT_MP.p) & (inf.DUT_MP.q); 
     endmodule : and_gate   

AND 门的测试台文件:

    // testbench file for and gate design
    // module defination for testbench with interface instanciation
    module tb(and_intr inf);

     initial
        begin
          $display("// and gate output using modports\n");
          repeat(5)
            begin
              inf.TB_MP.p = $random;
              #1;
              inf.TB_MP.q = $random;
              #1;
              $display("input_p=%b\t input_q=%b\t output_r=%b",inf.TB_MP.p,inf.TB_MP.q,inf.TB_MP.r);
            end
        end
    endmodule : tb

使用接口中的 modport,在上述提到的两种方式下,AND 门的输出保持不变。如下图所示。

modport_andgate


时钟块

时钟块被定义为一种机制,用于将输入和输出信号的采样和驱动与时钟事件同步。在测试台内使用时钟块非常有用,可以避免模拟中的竞态条件。我们可以明确地指定信号与特定时钟同步时的时间。时钟块只能在模块、接口内声明。时钟块只涉及输入和输出如何进行采样和同步。将值分配给变量是由模块、接口而不是时钟块完成的。

时钟块术语

1. 时钟事件

clocking  时钟块名称  @(posedge clk);

事件规范用于同步时钟块,@(posedge clk) 是时钟事件。

2. 时钟信号

input  from_Dut;  
output to_Dut; 

时钟块采样和驱动的信号,from_DUT 和 to_DUT 是时钟信号。

3. 时钟偏移

时钟偏移指定了在哪个输入和输出时钟信号要被采样或驱动。偏移必须是一个常量表达式,并且可以指定为参数。

输入和输出偏移

default input #1step output #0;

默认输入偏移和输出偏移声明如下,default input #1step output #0;。这里默认输入偏移需要 #1step 延迟来获取稳定输入的采样过程。输出偏移仅需要 #0 延迟,这意味着我们在当前时间段内得到稳定的输出。

下图显示了默认的输入和输出偏移。

image

下图显示了输入偏移和输出偏移。

image

输入信号相对于时钟事件进行采样。如果指定了输入偏移,则信号在时钟事件之前的偏移时间单位被采样。然后,输出信号在相应的时钟事件之后的偏移时间单位被驱动。输入偏移隐式为负,因为它发生在时钟之前。

例如,default input #3ps output #2

语法:

clocking cb @(posedge clk); 
default input #1step output #0;
input  from_Dut; 
output to_Dut; 
endclocking     

示例:D_flipflop

clocking block (1)

上图显示了 d_ff 的设计模块图。接口连接了 DUT 和测试。测试提供随机值 d,通过接口驱动到 DUT。DUT 给出采样值 q。采样值 q 被给定为测试的输入。在这里,顶层模块包括所有块,如测试、接口和 DUT。每个块的实例在顶层模块中创建。


posedge_df_cb

在这个例子中,DUT(时钟块时钟)和测试都在正边沿(接口时钟)触发。在这种情况下,波形输出和显示语句输出不匹配。输出显示在下图中。

示例代码:

DUT 代码:

     // module:d_flipflop   
     module d_flipflop(dff.dut intf);  
 
       //clocking block cd  
       always @(intf.cd)  

       //Non-Blocking assignment   
       intf.cd.q <= intf.cd.d;  
 
     endmodule : d_flipflop    

Interface 代码:

     //module: Interface  
     interface dff(input clk);    

       //declare the signals    
       logic d;   
       logic q;   

       //Clocking block for dut    
       clocking cd @(posedge clk);   
         default input #1step output #0;   
         output q;   
         input d;    
       endclocking     
  
       //modport for dut    
       modport dut(clocking cd);    
       //modport for tb     
       modport tb(input q, output d, input clk);`   
   
     endinterface: dff    

测试代码:

     //module: test
     module test(dff.tb intf);
  
       //task:drv
       task drv;
         //loop
         repeat(10)
           begin
           //test triggering at posedge
           @(posedge intf.clk )

           //randomzing the d
           intf.d <= $random;
           $display("test side[%0t]=d_tb_drive:%d q_dut_sample:%d",$time,intf.d, intf.q);
         end
         $finish;
       endtask 
  
       //calling the task drv
       initial begin
         drv();
       end 
     endmodule :test

顶层模块

     //including the file test.sv and interface.sv  
     `include "test.sv"      
     `include "interface.sv"    
 
     module top;
       bit clk=1;
       initial
         forever #5 clk = ~clk;

       //creating interface instance
       dff intf(clk);

       //d_flipflop instance
       d_flipflop t1(intf);  

       //test Instance
       test t2(intf);

       initial
         $monitor("DUT side [%0t]=d_tb_drive:%d q_dut_sample:%d",$time,intf.cd.d, intf.cd.q);
     endmodule : top

在下面的输出中,首先给出DUT和测试的正边沿。在这个例子中,在0时间,DUT和测试的输出都是x,然后在10纳秒时,测试随机化d值x为0,这时DUT得到0并给出采样q输出为0,这个时钟周期测试(tb)只随机化值d = 0,但测试(tb)采样了先前的值q = x。在10纳秒时,我的DUT给出输出d = 0和q = 0,而此时我的测试(tb)给出输出d = 0和q = x。现在,在20纳秒时,测试将d值从0随机化为1,此时DUT得到1并给出采样的q输出为1,这个时钟周期测试(tb)只随机化值d = 1,但测试(tb)采样了先前的值q = 0。在20纳秒时,我的DUT给出输出d = 1和q = 1,而此时我的测试给出输出d = 1和q = 0。

输出记录

下图14显示了 d 触发器的输出。

case_t1

所有时钟周期的 d_ff 输出

下图15显示了 d 触发器的输出波形。

case1


时钟块的优势

  • 时钟块提供了测试台和DUT之间无竞争条件。
  • 时钟块可以在接口、模块内声明。
  • 时钟块帮助用户以更高层次的抽象编写测试台。
  • 仿真速度更快。
  • 将设计的时钟活动与数据分配活动分离。
  • 在设计执行中节省了大量的代码和时间。

虚拟接口

  • 虚拟接口是表示接口实例的变量。

  • 虚拟接口用于在类中创建接口实例,因为接口是静态组件,而SystemVerilog测试台是动态组件。我们不能直接在类中声明接口,但使用变量 virtual,我们可以在类中声明接口实例。

    语法:virtual interface_name instance_name;

interface_name:接口的名称
instance_name:虚拟接口实例的名称,可以在类中使用变量 Ex: vif.variable;

  • 虚拟接口必须在类中初始化,指向实际接口。 在类中声明虚拟接口 例如:Virtual intf vif;

  • 访问未初始化的虚拟接口会导致致命错误。

  • 虚拟接口可以作为任务和函数方法的参数传递。

  • 虚拟接口可以是类的属性,并且可以通过使用函数参数进行初始化,即它可以在特定类中调用实际接口并在该类中创建接口实例。

    例如:function new(virtual intf vif);

  • 虚拟接口可以作为函数方法的参数传递。 通过使用 new() 构造,在类中调用实际接口 ‘intf’ 来声明虚拟接口,可以在类中的过程或函数参数中使用。

  • 在类函数和任务方法内部,可以通过虚拟接口句柄访问接口变量,如 virtual_instance_name.variable;

Example : vif.a

vif 是虚拟实例名称;
a 是类的变量/属性

  • 关键字/信号虚拟接口变量在整个仿真时间内表示不同的接口实例。

    语法:

interface <interface_name>(); 
               <port_list>; 
                .......... 
                endmodule 
           To connect static(interface module) to
           to dynamic(class) we use virtual interface  
            class clase_name;  
             virtual <interface_name> <interface_instance>;  
             ....... 
           properties; 
             ..... 
           function() 
            .....
          endfunction 
            task();  
             ...... 
             endtask 
             endclass   

Example1: Fulladder

全加器的设计代码

    //Module:fullinput_adder  
    module fulladder(in_a,in_b,in_c,out_sum,out_carry) ;    
    //Declaration of input variables
     input in_a,in_b,in_c;
     //Declaration of output variables
      output out_sum;
      output out_carry;
    //continuous input_assignment statement
     assign out_sum = in_a^in_b^in_c;
     assign out_carry = (in_a&in_b)|(in_b&in_c)| (in_c&in_a);  
      endmodule:fulladder  

全加器的接口模块

     interface adder();
     //declaring the signals
      logic in_a,in_b,in_c;
      logic out_sum,out_carry;
     endinterface

类内的虚拟接口声明

     //class:driver  
     class driver;  
      //Declaration of virtual interface  
      //syntax: virtual interface_name interface_instance;
      virtual adder vif;
      //constructor  
      function new(virtual adder vif);  
      //this.vif refer to class driver  
      //vif refer to the function argument  
      this.vif = vif;  
      endfunction  
      //task  
      task run();  
      repeat(10) begin  
      //interface_instance.variable  
      vif.in_a = $random;  
      vif.in_b = $random;  
      vif.in_c = $random;  
      $display("");  
      $display("//INPUT:Inputs of full adder  \n a=%0b, b=%0b, cin =%0b", vif.in_a,vif.in_b, vif.in_c);  
      #5;  
      $display("");  
      $display("//OUTPUT:Outputs of full adder \n sum=%0b, carry = %0b\n", vif.out_sum, vif.out_carry);  
      end  
      endtask  
     endclass  

全加器的测试模块

    `//include the driver file  
      include "driver.sv"  
      //module:test  
     module test(adder intf);  
    //declaring the driver instance  
     driver drv;  
     initial  
     begin  
     //creating the driver instance  
     drv = new(intf);  
    //calling the task run  
     drv.run();  
     end  
    endmodule:test  

全加器的顶层模块

      //including the test.sv and interface.sv files
    `include "test.sv"
    `include "interface.sv"
 
     //module:top
     module top;
    //creating  an instance of interface
     adder intf();
 
    // the instance of test  t1.
     test t1(intf);
 
    //fulladder DUT instance , connecting the interface signal to instance DUT
    fulladder dut(.in_a(intf.in_a), .in_b(intf.in_b), .in_c(intf.in_c), .out_sum(intf.out_sum), .out_carry(intf.out_carry));
    endmodule

下图显示了代码的设计块:

fulladder

在图16中,驱动器是一个类,在这里我们声明了虚拟接口,因为在类内部我们不能直接调用接口,因为接口是静态组件而类是动态组件。所以这个虚拟关键字被用来在类内部创建实例(它将创建虚拟接口)。在驱动器中,我们生成随机刺激并发送到接口,DUT连接到接口。DUT的输出给予接口。测试块包括类组件,即(driver.sv),顶层模块包括所有组件,如测试、接口和DUT。所有组件的实例都在顶层模块/块中创建。

下图显示了全加器的输出:
在图17中显示了全加器的输出,其中 a、b 和 cin 是全加器的输入,sum 和 carry 是全加器的输出。

fulladder2

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

el-input 正则表达式校验输入框不能输入汉字

<el-form :model"data1" :rules"rules" ref"ruleForm" label-width"210px" class"demo-ruleForm"><el-form-item label"锯路&#xff1a;" prop"sawKref"><el-input class"inptWid…

Pikachu[暴力破解:token防爆破]

暴力破解:token防爆破 校验方式&#xff1a; 请求中添加token防止爆破&#xff0c;登录时需携带服务器上一次加载时发送的token进行校验 解决&#xff1a; burp--intruder模块设置中使用Grep-Extract功能提取页面中的token&#xff0c;并将载荷类型更改为递归查询[Recursiv…

Springboot如何打包部署服务器

文章目的&#xff1a;java项目打包成jar包或war包&#xff0c; 放在服务器上去运行 一、编写打包配置 1. pom.xml 在项目中的pom.xml文件里面修改<build>...</build>的代码 >> 简单打包成Jar形式&#xff0c;参考示例&#xff1a; <build><fina…

flink 同步oracle11g数据表到pg库

1. 关闭防火墙和selinux systemctl stop firewalld systemctl disable firewalld systemctl status firewalldvi /etc/selinux/config 修改为disabled2.安装java8 yum list java-1.8* yum install java-1.8.0-openjdk* -yjava -version3.下载和部署postgresql 看需求安装pg库…

机器学习: LightGBM模型(优化版)——高效且强大的树形模型

LightGBM&#xff08;Light Gradient Boosting Machine&#xff09;是一种基于梯度提升决策树&#xff08;GBDT&#xff09;的框架&#xff0c;由微软提出。它具有高效的训练速度、低内存占用、支持并行和GPU加速等特点&#xff0c;非常适合大规模数据的训练任务&#xff0c;尤…

mysql中的EXISTS和NOT EXISTS使用详解

本文来编写一个实例说下mysql中的EXISTS和NOT EXISTS使用详解 文章目录 exists用法SQL中in, not in, exists, not exists的区别使用实例本文小结 exists用法 exists: 如果括号内子查询语句返回结果不为空&#xff0c;说明where条件成立&#xff0c;就会执行主SQL语句。如果括号…

idea 弹窗 delete remote branch origin/develop-deploy

想删除远程分支&#xff0c;就选delete&#xff0c;仅想删除本地分支&#xff0c;选cancel&#xff1b; 在 IntelliJ IDEA 中遇到弹窗提示删除远程分支 origin/develop-deploy&#xff0c;这通常是在 Git 操作过程中出现的情况&#xff0c;可能是在执行如 git branch -d 或其他…

基于微信小程序的高校实习管理系统设计与实现,LW+源码+讲解

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自…

Spring Boot 牛刀小试 org.springframework.boot:spring-boot-maven-plugin:找不到类错误

今天看了下书翻了下Spring Boot的用法&#xff0c;下载idea后&#xff0c; 反复出现org.springframework.boot:spring-boot-maven-plugin:找不到类错误&#xff0c;后来看了下调试窗口&#xff0c;发现是连不上maven的网站443错误&#xff0c;解决思路很简单&#xff0c;把ide连…

k-近邻算法(K-Nearest Neighbors, KNN)详解:机器学习中的经典算法

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

UE5 umg学习(四) 将UI控件显示到关卡中

视频资料 7、将UI控件渲染到关卡_哔哩哔哩_bilibili 在前三节里&#xff0c;创建了用户的控件蓝图Widget_BP 目标是运行的时候&#xff0c;开始运行这个蓝图&#xff0c;因此需要在开始事件触发运行 首先&#xff0c;回到主页&#xff0c;点击关卡蓝图 要从事件开始运行时 …

StarRocks Summit Asia 2024 全部议程公布!

随着企业数字化转型深入&#xff0c;云原生架构正成为湖仓部署的新标准。弹性扩展、资源隔离、成本优化&#xff0c;帮助企业在云上获得了更高的灵活性和效率。与此同时&#xff0c;云原生架构也为湖仓与 AI 的深度融合奠定了基础。 在过去一年&#xff0c;湖仓技术与 AI 的结…

【CSS】opacity 影响 z-index 不生效

准备知识 一般来说&#xff0c;z-index 不生效的原因有&#xff1a; 父元素的 position 属性&#xff1a; z-index 只对 position 属性为 relative、absolute 或 fixed 的元素有效。 其他元素的 z-index&#xff1a; 如果页面中有其他元素也设置了较高的 z-index&#xff0c;…

2024 年(第 7 届)“泰迪杯”数据分析技能赛B 题 特殊医学用途配方食品数据分析 完整代码 结果 可视化分享

一、背景特殊医学用途配方食品简称特医食品&#xff0c;是指为满足进食受限、消化吸收障碍、代谢素乱或者特定疾病状态人群对营养素或者膳食的特殊需要&#xff0c;专门加工配置而成的配方食品&#xff0c;包括0月龄至12月龄的特殊医学用途婴儿配方食品和适用于1岁以上的特殊医…

【MYSQL】数据库日志 (了解即可)

一、错误日志 可以通过 tail查看文件的日志的&#xff0c;如果发生错误&#xff0c;就会在日志里出现问题。 二、二进制日志&#xff08;binlog&#xff09; BINLOG记录了insert delete update 以及 alter create drop 等语句。作用是灾难时的数据恢复&#xff0c;还有就是主…

STM32 创建一个工程文件(寄存器、标准库)

首先到官网下载对应型号的固件包&#xff1a; 像我的STM32F103C8T6的就下载这个&#xff1a; 依次打开&#xff1a; .\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm 可以看到&#xff1a; 这…

C语言 char 字符串 - C语言零基础入门教程

目录 一.char 字符串简介 二.字符和字符串区别 1.取值范围相同2.字符串由多个字符构成3.字符串和字符使用 printf 函数 三.char 字符串遍历四.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.char 字符串简介 在C 语言中&#xff0c;除了前面介绍…

Python——NumPy库的简单用法,超级详细教程使用

一、什么是NumPy库 NumPy&#xff1a;它是python的一个科学计算库函数&#xff0c;它是由c语言编写的 它应用于数据处理、机器学习、图像处理、文件操作等等 二、array函数 这里导入库numpy&#xff0c;命名为np&#xff0c;后面的np都是代表着是numpy函数 array函数表示创建…

Python学习26天

集合 # 定义集合 num {1, 2, 3, 4, 5} print(f"num&#xff1a;{num}\nnum数据类型为&#xff1a;{type(num)}") # 求集合中元素个数 print(f"num中元素个数为&#xff1a;{len(num)}") # 增加集合中的元素 num.add(6) print(num) # {1,2,3,4,5,6} # 删除…

【数字图像处理+MATLAB】基于 Sobel 算子计算图像梯度并进行边缘增强:使用 imgradientxy 函数

引言 在图像处理中&#xff0c;边缘通常是图像中像素强度变化最大的地方&#xff0c;这种变化可以通过计算图像的梯度来量化。梯度是一个向量&#xff0c;它的方向指向像素强度增加最快的方向&#xff0c;它的大小&#xff08;或者说幅度&#xff09;表示像素强度增加的速度。…