只调用加法模块的仿真图:

(注:alu_control 为十六进制

001高位加载 src2的低16位加载到高16位上

002算数右移 src1算数右移  (高位补1)

004逻辑右移 src1逻辑右移 (逻辑右移直接补0)

008逻辑左移 src1逻辑左移

010异或 020或 040或非 080与

100 无符号比较 小于置位

200 有符号比较 小于置位

400 减法

800 加法

没有调用乘法器的ALU (下面那个调用了)

alu.v

`timescale 1ns / 1psmodule alu(input  [11:0] alu_control, input  [31:0] alu_src1, input  [31:0] alu_src2,output   [31:0] alu_result );reg [31:0] alu_result;wire alu_add;   //加法wire alu_sub;   //减法wire alu_slt;   //有符号比较,小于置位wire alu_sltu;  //无符号比较,小于置位wire alu_and;   //按位与wire alu_nor;   //按位或非wire alu_or;    //按位或 wire alu_xor;   //按位异或wire alu_sll;   //逻辑左移wire alu_srl;   //逻辑右移wire alu_sra;   //算数右移wire alu_lui;   //高位加载assign alu_mult = alu_control[11];assign alu_add  = alu_control[11];assign alu_sub  = alu_control[10];assign alu_slt  = alu_control[ 9];assign alu_sltu = alu_control[ 8];assign alu_and  = alu_control[ 7];assign alu_nor  = alu_control[ 6];assign alu_or   = alu_control[ 5];assign alu_xor  = alu_control[ 4];assign alu_sll  = alu_control[ 3];assign alu_srl  = alu_control[ 2];assign alu_sra  = alu_control[ 1];assign alu_lui  = alu_control[ 0];wire [31:0] add_sub_result; //加减结果,减法用加法来实现wire [31:0] slt_result;     //wire [31:0] sltu_result;    //wire [31:0] and_result;wire [31:0] nor_result;wire [31:0] or_result;wire [31:0] xor_result;wire [31:0] sll_result;wire [31:0] srl_result;wire [31:0] sra_result;     wire [31:0] lui_result;wire signed [31:0] temp_src1;   //带符号数的临时变量assign temp_src1 = alu_src1;    //方便后面对alu_src1进行算数右移assign and_result = alu_src1 & alu_src2;        //按位与assign or_result  = alu_src1 | alu_src2;        //按位或assign nor_result = ~or_result;                 //或非assign xor_result = alu_src1 ^ alu_src2;        //异或assign lui_result = {alu_src2[15:0], 16'd0};    //高位加载,第二个操作数的低十六位加载到高十六位上assign sll_result = alu_src1 << alu_src2;       //逻辑左移assign srl_result = alu_src1 >> alu_src2;       //逻辑右移assign slt_result = adder_result[31] ? 1'b1 : 1'b0;   // 带符号数小于置位assign sltu_result = adder_cout ? 1'b0 : 1'b1;     //无符号数小于置位assign sra_result = temp_src1 >>> alu_src2;     //算数右移wire [31:0] adder_operand1;wire [31:0] adder_operand2;wire        adder_cin     ;wire [31:0] adder_result  ;wire        adder_cout    ;assign adder_operand1 = alu_src1; assign adder_operand2 = alu_add ? alu_src2 : ~alu_src2;     //默认进行减法,为slt和sltu服务assign adder_cin      = ~alu_add;  //巧妙到我都以为代码有bugadder adder_module(     //调用加法模块.A(adder_operand1),.B(adder_operand2),.Cin     (adder_cin     ),.S  (adder_result  ),.Cout    (adder_cout    ));
assign add_sub_result = adder_result;always@(*)beginif(alu_add | alu_sub)alu_result <= add_sub_result;else if(alu_slt)alu_result <= slt_result;else if(alu_sltu)alu_result <= sltu_result;else if(alu_and)alu_result <= and_result;else if(alu_nor)alu_result <= nor_result;else if(alu_or)alu_result <= or_result;else if(alu_xor)alu_result <= xor_result;else if(alu_sll)alu_result <= sll_result;else if(alu_srl)alu_result <= srl_result;else if(alu_sra)alu_result <= sra_result;else if(alu_lui)alu_result <= lui_result;end
endmodule

testbench.v

`timescale 1ns / 1psmodule tb;// Inputsreg clk;reg [11:0] alu_control;reg [31:0] alu_src1;reg [31:0] alu_src2;// Outputswire [31:0] alu_result;// Instantiate the Unit Under Test (UUT)
//alu al(
//    input  [11:0] alu_control,
//    input  [31:0] alu_src1,
//    input  [31:0] alu_src2,
//    output [31:0] alu_result
//    );
alu alu_module(.alu_control(alu_control),.alu_src1   (alu_src1   ),.alu_src2   (alu_src2   ),.alu_result (alu_result ));initial begin// Initialize Inputsclk = 0;alu_control = 0;alu_src1 = 32'H10001111;alu_src2 = 32'H00000004;// Wait 100 ns for global reset to finish#100;alu_control = 12'b0000_0000_0001;#400;alu_control = 12'b0000_0000_0010;#500;alu_control = 12'b0000_0000_0100;#400;alu_control = 12'b0000_0000_1000;#500;alu_control = 12'b0000_0001_0000;#400;alu_control = 12'b0000_0010_0000;#500;alu_control = 12'b0000_0100_0000;#400;alu_control = 12'b0000_1000_0000;#400;alu_control = 12'b0001_0000_0000;#400;alu_control = 12'b0010_0000_0000;#400;alu_control = 12'b0100_0000_0000;#400;alu_control = 12'b1000_0000_0000;// Add stimulus hereendalways #5 clk = ~clk;
endmodule

alu_display.v

module alu_display(//时钟与复位信号input clk,input resetn,    //后缀"n"代表低电平有效//拨码开关,用于选择输入数input [1:0] input_sel, //00:输入为控制信号(alu_control)//10:输入为源操作数1(alu_src1)//11:输入为源操作数2(alu_src2)//触摸屏相关接口,不需要更改output lcd_rst,output lcd_cs,output lcd_rs,output lcd_wr,output lcd_rd,inout[15:0] lcd_data_io,output lcd_bl_ctr,inout ct_int,inout ct_sda,output ct_scl,output ct_rstn);
//-----{调用ALU模块}beginreg   [11:0] alu_control;  // ALU控制信号reg   [31:0] alu_src1;     // ALU操作数1reg   [31:0] alu_src2;     // ALU操作数2wire  [31:0] alu_result;   // ALU结果alu alu_module(.alu_control(alu_control),.alu_src1   (alu_src1   ),.alu_src2   (alu_src2   ),.alu_result (alu_result ));
//-----{调用ALU模块}end//---------------------{调用触摸屏模块}begin--------------------//
//-----{实例化触摸屏}begin
//此小节不需要更改reg         display_valid;reg  [39:0] display_name;reg  [31:0] display_value;wire [5 :0] display_number;wire        input_valid;wire [31:0] input_value;lcd_module lcd_module(.clk            (clk           ),   //10Mhz.resetn         (resetn        ),//调用触摸屏的接口.display_valid  (display_valid ),.display_name   (display_name  ),.display_value  (display_value ),.display_number (display_number),.input_valid    (input_valid   ),.input_value    (input_value   ),//lcd触摸屏相关接口,不需要更改.lcd_rst        (lcd_rst       ),.lcd_cs         (lcd_cs        ),.lcd_rs         (lcd_rs        ),.lcd_wr         (lcd_wr        ),.lcd_rd         (lcd_rd        ),.lcd_data_io    (lcd_data_io   ),.lcd_bl_ctr     (lcd_bl_ctr    ),.ct_int         (ct_int        ),.ct_sda         (ct_sda        ),.ct_scl         (ct_scl        ),.ct_rstn        (ct_rstn       ));
//-----{实例化触摸屏}end//-----{从触摸屏获取输入}begin
//根据实际需要输入的数修改此小节,
//建议对每一个数的输入,编写单独一个always块//当input_sel为00时,表示输入数控制信号,即alu_controlalways @(posedge clk)beginif (!resetn)beginalu_control <= 12'd0;endelse if (input_valid && input_sel==2'b00)beginalu_control <= input_value[11:0];endend//当input_sel为10时,表示输入数为源操作数1,即alu_src1always @(posedge clk)beginif (!resetn)beginalu_src1 <= 32'd0;endelse if (input_valid && input_sel==2'b10)beginalu_src1 <= input_value;endend//当input_sel为11时,表示输入数为源操作数2,即alu_src2always @(posedge clk)beginif (!resetn)beginalu_src2 <= 32'd0;endelse if (input_valid && input_sel==2'b11)beginalu_src2 <= input_value;endend
//-----{从触摸屏获取输入}end//-----{输出到触摸屏显示}begin
//根据需要显示的数修改此小节,
//触摸屏上共有44块显示区域,可显示44组32位数据
//44块显示区域从1开始编号,编号为1~44,always @(posedge clk)begincase(display_number)6'd1 :begindisplay_valid <= 1'b1;display_name  <= "SRC_1";display_value <= alu_src1;end6'd2 :begindisplay_valid <= 1'b1;display_name  <= "SRC_2";display_value <= alu_src2;end6'd3 :begindisplay_valid <= 1'b1;display_name  <= "CONTR";display_value <={20'd0, alu_control};end6'd4 :begindisplay_valid <= 1'b1;display_name  <= "RESUL";display_value <= alu_result;enddefault :begindisplay_valid <= 1'b0;display_name  <= 40'd0;display_value <= 32'd0;endendcaseend
//-----{输出到触摸屏显示}end
//----------------------{调用触摸屏模块}end---------------------//
endmodule

调用乘法器的ALU(代码扔到末尾)

这里结果我不知道怎么只显示希望的结果(出现了0,这个是个过程值,当时做乘法器的时候,看仿真的时候是配合着mult_end信号看的,我也不会把这个end信号调出来)


slt sltu没看明白:(手册里有以后看 挖坑)

指令(SLT,SLTI,SLTU,SLTIU)比较两个操作数然后设置目的寄存器,

如果就设置为1,否则就将目的寄存器设置为0。


alu.v

`timescale 1ns / 1psmodule alu(input clk,input  [12:0] alu_control, input  [31:0] alu_src1, input  [31:0] alu_src2,output   [31:0] alu_result );reg [31:0] alu_result;wire alu_mul;//乘法wire alu_add;   //加法wire alu_sub;   //减法wire alu_slt;   //有符号比较,小于置位wire alu_sltu;  //无符号比较,小于置位wire alu_and;   //按位与wire alu_nor;   //按位或非wire alu_or;    //按位或 wire alu_xor;   //按位异或wire alu_sll;   //逻辑左移wire alu_srl;   //逻辑右移wire alu_sra;   //算数右移wire alu_lui;   //高位加载assign alu_mul = alu_control[12];assign alu_add  = alu_control[11];assign alu_sub  = alu_control[10];assign alu_slt  = alu_control[ 9];assign alu_sltu = alu_control[ 8];assign alu_and  = alu_control[ 7];assign alu_nor  = alu_control[ 6];assign alu_or   = alu_control[ 5];assign alu_xor  = alu_control[ 4];assign alu_sll  = alu_control[ 3];assign alu_srl  = alu_control[ 2];assign alu_sra  = alu_control[ 1];assign alu_lui  = alu_control[ 0];wire [31:0] mul_result;wire [31:0] add_sub_result; //加减结果,减法用加法来实现wire [31:0] slt_result;     wire [31:0] sltu_result;    wire [31:0] and_result;wire [31:0] nor_result;wire [31:0] or_result;wire [31:0] xor_result;wire [31:0] sll_result;wire [31:0] srl_result;wire [31:0] sra_result;     wire [31:0] lui_result;wire signed [31:0] temp_src1;   //带符号数的临时变量assign temp_src1 = alu_src1;    //方便后面对alu_src1进行算数右移assign and_result = alu_src1 & alu_src2;        //按位与assign or_result  = alu_src1 | alu_src2;        //按位或assign nor_result = ~or_result;                 //或非assign xor_result = alu_src1 ^ alu_src2;        //异或assign lui_result = {alu_src2[15:0], 16'd0};    //高位加载,第二个操作数的低十六位加载到高十六位上assign sll_result = alu_src1 << alu_src2;       //逻辑左移assign srl_result = alu_src1 >> alu_src2;       //逻辑右移assign slt_result = adder_result[31] ? 1'b1 : 1'b0;   // 带符号数小于置位assign sltu_result = adder_cout ? 1'b0 : 1'b1;     //无符号数小于置位assign sra_result = temp_src1 >>> alu_src2;     //算数右移wire [31:0] adder_operand1;wire [31:0] adder_operand2;wire        adder_cin     ;wire [31:0] adder_result  ;wire        adder_cout    ;assign adder_operand1 = alu_src1; assign adder_operand2 = alu_add ? alu_src2 : ~alu_src2;     //默认进行减法,为slt和sltu服务assign adder_cin      = ~alu_add;  //巧妙到我都以为代码有bugadder adder_module(     //调用加法模块.A(adder_operand1),.B(adder_operand2),.Cin     (adder_cin     ),.S  (adder_result  ),.Cout    (adder_cout    ));
assign add_sub_result = adder_result;wire         clk;      // 时钟//   wire        mult_begin; // 乘法开始信号wire  [31:0] mult_op1;  // 乘法源操作数1wire [31:0] mult_op2;  // 乘法源操作数2wire [63:0] product;   // 乘积wire        mult_end ;  // 乘法结束信号assign mult_op1 = alu_src1; assign mult_op2 =alu_src2;assign mult_begin=1;multiply multiply_module//调用乘法模块  (     .clk(clk),.mult_begin(mult_begin),.mult_op1     (alu_src1 ),.mult_op2  (alu_src2 ),.product    ( product ),.mult_end ());assign mul_result =product ;always@(*)beginif(alu_add | alu_sub)alu_result <= add_sub_result;else if(alu_mul)alu_result =mul_result;else if(alu_slt)alu_result <= slt_result;else if(alu_sltu)alu_result <= sltu_result;else if(alu_and)alu_result <= and_result;else if(alu_nor)alu_result <= nor_result;else if(alu_or)alu_result <= or_result;else if(alu_xor)alu_result <= xor_result;else if(alu_sll)alu_result <= sll_result;else if(alu_srl)alu_result <= srl_result;else if(alu_sra)alu_result <= sra_result;else if(alu_lui)alu_result <= lui_result;end
endmodule

alu.display (就改了个信号数组的范围)

module alu_display(//时钟与复位信号input clk,input resetn,    //后缀"n"代表低电平有效//拨码开关,用于选择输入数input [1:0] input_sel, //00:输入为控制信号(alu_control)//10:输入为源操作数1(alu_src1)//11:输入为源操作数2(alu_src2)//触摸屏相关接口,不需要更改output lcd_rst,output lcd_cs,output lcd_rs,output lcd_wr,output lcd_rd,inout[15:0] lcd_data_io,output lcd_bl_ctr,inout ct_int,inout ct_sda,output ct_scl,output ct_rstn);
//-----{调用ALU模块}beginreg   [12:0] alu_control;  // ALU控制信号reg   [31:0] alu_src1;     // ALU操作数1reg   [31:0] alu_src2;     // ALU操作数2wire  [31:0] alu_result;   // ALU结果alu alu_module(.alu_control(alu_control),.alu_src1   (alu_src1   ),.alu_src2   (alu_src2   ),.alu_result (alu_result ));
//-----{调用ALU模块}end//---------------------{调用触摸屏模块}begin--------------------//
//-----{实例化触摸屏}begin
//此小节不需要更改reg         display_valid;reg  [39:0] display_name;reg  [31:0] display_value;wire [5 :0] display_number;wire        input_valid;wire [31:0] input_value;lcd_module lcd_module(.clk            (clk           ),   //10Mhz.resetn         (resetn        ),//调用触摸屏的接口.display_valid  (display_valid ),.display_name   (display_name  ),.display_value  (display_value ),.display_number (display_number),.input_valid    (input_valid   ),.input_value    (input_value   ),//lcd触摸屏相关接口,不需要更改.lcd_rst        (lcd_rst       ),.lcd_cs         (lcd_cs        ),.lcd_rs         (lcd_rs        ),.lcd_wr         (lcd_wr        ),.lcd_rd         (lcd_rd        ),.lcd_data_io    (lcd_data_io   ),.lcd_bl_ctr     (lcd_bl_ctr    ),.ct_int         (ct_int        ),.ct_sda         (ct_sda        ),.ct_scl         (ct_scl        ),.ct_rstn        (ct_rstn       ));
//-----{实例化触摸屏}end//-----{从触摸屏获取输入}begin
//根据实际需要输入的数修改此小节,
//建议对每一个数的输入,编写单独一个always块//当input_sel为00时,表示输入数控制信号,即alu_controlalways @(posedge clk)beginif (!resetn)beginalu_control <= 12'd0;endelse if (input_valid && input_sel==2'b00)beginalu_control <= input_value[11:0];endend//当input_sel为10时,表示输入数为源操作数1,即alu_src1always @(posedge clk)beginif (!resetn)beginalu_src1 <= 32'd0;endelse if (input_valid && input_sel==2'b10)beginalu_src1 <= input_value;endend//当input_sel为11时,表示输入数为源操作数2,即alu_src2always @(posedge clk)beginif (!resetn)beginalu_src2 <= 32'd0;endelse if (input_valid && input_sel==2'b11)beginalu_src2 <= input_value;endend
//-----{从触摸屏获取输入}end//-----{输出到触摸屏显示}begin
//根据需要显示的数修改此小节,
//触摸屏上共有44块显示区域,可显示44组32位数据
//44块显示区域从1开始编号,编号为1~44,always @(posedge clk)begincase(display_number)6'd1 :begindisplay_valid <= 1'b1;display_name  <= "SRC_1";display_value <= alu_src1;end6'd2 :begindisplay_valid <= 1'b1;display_name  <= "SRC_2";display_value <= alu_src2;end6'd3 :begindisplay_valid <= 1'b1;display_name  <= "CONTR";display_value <={20'd0, alu_control};end6'd4 :begindisplay_valid <= 1'b1;display_name  <= "RESUL";display_value <= alu_result;enddefault :begindisplay_valid <= 1'b0;display_name  <= 40'd0;display_value <= 32'd0;endendcaseend
//-----{输出到触摸屏显示}end
//----------------------{调用触摸屏模块}end---------------------//
endmodule

testbench.v

`timescale 1ns / 1psmodule tb;// Inputsreg clk;reg [12:0] alu_control;reg [31:0] alu_src1;reg [31:0] alu_src2;// Outputswire [31:0] alu_result;// Instantiate the Unit Under Test (UUT)
//alu al(
//    input  [11:0] alu_control,
//    input  [31:0] alu_src1,
//    input  [31:0] alu_src2,
//    output [31:0] alu_result
//    );
alu alu_module(.clk(clk),.alu_control(alu_control),.alu_src1   (alu_src1   ),.alu_src2   (alu_src2   ),.alu_result (alu_result ));initial begin// Initialize Inputsclk = 0;alu_control = 0;alu_src1 = 32'H10001111;alu_src2 = 32'H00000004;// Wait 100 ns for global reset to finish#100;alu_control = 13'b00000_0000_0001;#400;alu_control = 13'b00000_0000_0010;#500;alu_control = 13'b00000_0000_0100;#400;alu_control = 13'b00000_0000_1000;#500;alu_control = 13'b00000_0001_0000;#400;alu_control = 13'b00000_0010_0000;#500;alu_control = 13'b00000_0100_0000;#400;alu_control = 13'b00000_1000_0000;#400;alu_control = 13'b00001_0000_0000;#400;alu_control = 13'b00010_0000_0000;#400;alu_control = 13'b00100_0000_0000;#400;alu_control = 13'b01000_0000_0000;#400;alu_control = 13'b10000_0000_0000;// Add stimulus hereendalways #5 clk = ~clk;
endmodule

multiply.v 和 add.v 之前的记录里有。


一般认为“>>>”在Verilog里是算术右移指令,但实操中发现它有时会在右移时仍然补零,即使符号位为1。这是因为“>>>”会先判断这个操作数是否有符号数。如果是无符号数,则补零,是有符号数,才会补符号位。而一般使用的reg operand; 这种变量定义法默认所定义的变量为无符号数,因此只补零。

Result = operandB >>> operandA;  //错误示范

解决办法是利用Verilog的内置函数$signed(),将被移位的操作数转为有符号数类型。

Result = ($signed(operandB)) >>> operandA;  //更正后

ALU——调用加法乘法模块相关推荐

  1. java 乘法_java大数加法乘法

    java大数加法乘法 前言 正常情况下我们调用加法乘法使用符号就行了,但是如果超出限制了,那就只能调用BigDecimal里面的函数了,但是有的时候oj考察的就是希望自己实现,所以就可以采用别的方法. ...

  2. Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

    由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二 ...

  3. SpringCloud实现一个模块调用另一个模块的服务

    SpringCloud实现一个模块调用另一个模块的服务 简介 基于SpringCloud框架搭建的项目,不同模块之间是无法调用各自的服务的,但是经常我们需要使用这样的模式去开发,那么如何实现不同模块之 ...

  4. Python笔记(二)——python调用C/C++模块

    前一篇讲了简单的C/C++调用Python脚本模块(.py).既然是用于诸多游戏程序的脚本语言,那肯定是缺不了互调(礼尚往来).因此,本篇讲一个简单的python调用C/C++写的DLL模块,对Pyt ...

  5. react-native调用Android原生模块

    今天学习了一下在react-native中调用原生安卓模块的使用,发现很多网上的文章都是直接照抄的文档,这样会有一些坑,导致最后无法运行或者成功调用,所以写下这个博客来分享,同时也记录一下学习过程,内 ...

  6. Lua脚本如何调用C/C++模块,Windows以及Linux版本演示

    Windows下 我用的是vs2019,由于Windows下不像Linux可以直接直接安装lua程序直接运行lua代码,所以这里我们演示的是,通过c/c++调用lua脚本,lua脚本再调用其他的C/C ...

  7. Python + opencv 调用工业相机对模块进行拍照扫描并分析内容(一)

    ** Python + opencv 调用工业相机对模块进行拍照扫描并分析内容(一) ** 利用厂家提供的文档和资料,安装好SDK,将dll文件放入系统位置: 1)Windows 将 JHCap2.d ...

  8. 计算机用加法乘法实现除法运算的数学原理

    数学原理:迭代序列 本篇只讨论加法乘法实现除法的数学原理,并不涉及数据结构. 设已知  c > 0 ,任取     数学归纳法我们有       0 < <1  ,  0 <  ...

  9. 计算机底层加法/乘法实现

    计算机底层加法/乘法实现 存储方式 原理 加法 乘法 除法 代码实现 加法 乘法 存储方式 计算机底层中存放数字使用二进制形式,负数使用补码(反码+1)来存放. 原理 加法 两个二进制的相加结果是用一 ...

最新文章

  1. 构建一个分布式操作系统的简单方案—答陈硕的“分布式系统中的进程标识”一文...
  2. .net中的认证和授权(学习笔记)
  3. 被围绕的区域(dfs)
  4. LeetCode 336. 回文对(哈希map/Trie树)
  5. php生成静态html分页实现方法
  6. Flutter之_slot 插槽属性详解
  7. Qt QTableView样式设置
  8. python写入文件出现空行
  9. 实时单目物体SLAM Real-time Monocular Object SLAM
  10. java数组的实例化
  11. Win10使用说明 - 任务栏设置、触摸板手势和使用偏好
  12. KUKA机器人资料下载
  13. Windows 和 Linux 的免费媒体播放器 - SMPlayer
  14. Excel必知必会——count,counta,countif,countifs
  15. ArcGIS教程:太阳辐射建模
  16. 计算机时间怎么改24小时模式,怎么修改电脑的时间为24小时制啊?
  17. NVIDIA GeForce Experience无法登录
  18. 电脑开机停在主板logo画面
  19. oracle linux6 u盘安装,用U盘安装Oracle Linux 6.2
  20. 138+134 新手寻星,三分钟搞定,呵呵,我明天才!!

热门文章

  1. 创优翼首页HTML,新手与大神就在一念之间,论HTML5的正确使用姿势。创优翼教育...
  2. 借助 ServerChan 实现个人微信通知推送
  3. Linux高级指令(二)
  4. 匹配电阻帮助提高放大器性能-电子技术方案
  5. ping不通Linux服务器怎么办?
  6. 实现同时控制施耐德(Schneider Electric)和西门子(Siemens)PLC WCS系统
  7. caoz:创业公司如何做好信息安全
  8. CH583 南京沁恒WCH 无线MCU BLE 5.3
  9. MAX之不关闭MAX脚本开发
  10. 鼠标跟随案例:用js实现盒子跟随鼠标移动