ZYNQ之FPGA实验记录

参考正点原子的zynq教程

1.led控制:控制底板的两个led灯,在1s内两个灯交叉闪烁,各0.5s

module led_twinkle(
	input clk,//50MHZ,等同于1ns,故有26位来计数,20ns
	input  rst_n,//复位信号
	output [1:0] led
	);


	reg [25:0] cnt;//计数器
	
	assign led=cnt<26'd2500_0000 ? 2'b10:2'b01;
	
	always@ ( posedge clk or negedge st_n) begin
		if(!rst_n)
			cnt <= 26'd0;
		else if(cnt<26'd5000_0000)
			cnt <= cnt+1'b1;
		else
			cnt <= 26'd0;
	end
endmodule

2.led控制,通过按键1和2来控制灯的闪烁实际情况。

module key_led( input clk,
input rst_n,
input [1:0] key,
output reg [1:0] led

    );
	
	reg [24:0] cnt;//25位的cnt
	reg led_control;
	
	always @(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt<=25'd0;
		else if(cnt<25'd2500_0000)
			cnt<=cnt+1'b1;
		else
			cnt<=25'd0;
	end
	
	always @(posedge clk or negedge rst_n)begin
		if(!rst_n)
			led_control<=1'b0;
		else if(cnt==25'd2500_0000)
			led_control<=~led_control;
	end
	
	always @(posedge clk or negedge rst_n)begin
		if(!rst_n)
			led<=2'b11;
		else case(key)
			2'b10: if(led_control==1'b0)//如果按键0按下,交替闪烁
						led<=2'b10;
					else
						led<=2'b01;
			2'b01: if(led_control==1'b0)//如果按键1按下,同时闪烁
						led<=2'b11;
					else 
						led<=2'b00;
			2'b11:
					led<=2'b11;//如果两个按键都没有按下来,则保持两个灯一起亮起来
			default: ;

		endcase
	end
endmodule

3.蜂窝器控制,按下按键后不响,再次按下后响,并且要考虑消抖情况。

top_beep_control.v

module top_beep_debounce(
	input clk,
	input rst_n,
	
	input key,
	output  beep//这里不再需要进行reg
    );
	
wire key_flag;
wire key_value;


deep_debaunce u1(
	.clk         (clk)   ,
	.rst_n       (rst_n) ,
	
	.key         (key)   ,
	.key_value   (key_value) ,
	.key_flag    (key_flag)

    );	

beep_control u2(
	.clk 		(clk), 
	.rst_n		(rst_n),
	.key_value	(key_value),
	.key_flag	(key_flag),
	.beep		(beep)
    );
	
endmodule

deep_debaunce.v

module deep_debaunce(
	input clk,
	input rst_n,
	input key,
	 
	output reg key_value,
	output reg key_flag

    );
	
	reg [19:0] cnt;
	reg  key_reg;
	
	
	always @(posedge clk or negedge rst_n) begin
	
		if(!rst_n) begin
			cnt<=20'd0;
			key_reg<=1'b1;
		end
		else begin
			key_reg<=key;
			
			if(key!=key_reg) begin
				cnt<=20'd1000_000;	
			end
			
			else begin
			
				if(cnt>20'd0)
					cnt<=cnt-1'b1;
				else
					cnt<=20'd0;
			end
			
		end
	end
		

	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) 
			begin
			key_value<=1'b1;
			key_flag<=1'b0;
			end
		else begin
			if(cnt==20'd1) begin
				key_flag  <= 1'b1;
				key_value <= key;
			end
			else begin
				key_flag  <= 1'b0;
				key_value <= key_value;
			end
		end
	end
	
	
	

	
	
endmodule

beep_control.v

module beep_control(
	input clk,
	input rst_n,
	
	input  key_value,
	input key_flag,
	output reg beep

    );
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n)
			beep<=1'b1;
		else if (key_flag && (key_value==0))
			beep<=1'b0;

	end
endmodule

4.呼吸灯:实现类似呼吸灯的效果,控制闪烁的速度

//呼吸灯
module breath_led(
	input clk,
	input rst_n,
	
	output  led
    );
	
	reg [15:0]  period_cnt;       //表示当前的计时
	reg [15:0]  duty_cycle;      //表示调控的多少范围内的具体数值大小
	reg inc_dec_flag;            //0表示增加,1表示减小
	
	assign led = (period_cnt>=duty_cycle)?1'b1:1'b0;//如果大于duty_cycle.则led被放置为0.这个时候灯被点亮的
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n)
			period_cnt<=16'd0;
		else if(period_cnt==16'd50000)
			period_cnt<=16'd0;
	    else 
			period_cnt<=period_cnt+1'b1;
	end
	
	always @(posedge clk or negedge rst_n) 
		begin
			if(!rst_n) 
			begin
				inc_dec_flag<=1'b0;
				duty_cycle<=16'd0;
			end
			else 
				begin
				if(period_cnt==16'd50000)
				begin
					if(inc_dec_flag==1'b0)
					begin
							if(duty_cycle==16'd50000)
								inc_dec_flag<=1'b1;
							else 
								duty_cycle<=duty_cycle+16'd50;		
					end
					else begin
						if(duty_cycle==16'd0)
							inc_dec_flag<=1'b0;
						else	
						duty_cycle<=duty_cycle-16'd50;
					end
				end
				
				end
		end
		
endmodule

5.clock的ip调用

调用ip核 clock_twi

//IP核调用实验 clk_wiz 分频实验

module clock_twi(
    input sys_clk_50M,
    input sys_rst_n,
    output clk_out1_100m,
    output clk_out2_100m_180,
    output clk_out3_50m ,
    output clk_out4_25m  
    );



    wire locked;
    clk_wiz_0  clk_wiz_0
    (
  // Clock out ports
          .clk_out1_100m        (clk_out1_100m),
          .clk_out2_100m_180    (clk_out2_100m_180),
          .clk_out3_50m         (clk_out3_50m),
          .clk_out4_25m         (clk_out4_25m),    
  // Status and control signals
          .reset                (~sys_rst_n),//在clk_wiz_0里面默认是以高电位作为复位的,这里我们用~来转化为取得低电位
          .locked               (locked),
 // Clock in ports
         .clk_in1               (sys_clk_50M)
    );



endmodule

编写testbench
//编写testbench文件

`timescale 1ns / 1ps
module tb_clock_twi();

    reg sys_clk_50M;
    reg sys_rst_n;


    wire clk_out1_100m;
    wire clk_out2_100m_180;
    wire clk_out3_50m ;
    wire clk_out4_25m ;


    clock_twi u
    (
    .sys_clk_50M          (sys_clk_50M),
    .sys_rst_n            (sys_rst_n) ,
    .clk_out1_100m       (clk_out1_100m ),
    .clk_out2_100m_180   (clk_out2_100m_180),
    .clk_out3_50m        (clk_out3_50m),
    .clk_out4_25m        (clk_out4_25m )
    );

    always #10 sys_clk_50M = ~sys_clk_50M;
    initial begin
        sys_clk_50M=1'b0;
        sys_rst_n=1'b0;//低电位复位
        #200
        sys_rst_n=1'b1;
    end
endmodule

结果生成了四个不同的时钟
在这里插入图片描述

6.RAM的ip核调用,RAM能够调用内存,这个实验暂时还没有上板。

1.ip_ram.v(top)

module ip_ram(
    input sys_clk
    //input sys_rst_n
    );


wire sys_rst_n;        //zcu106的rst_n在哪里呢
wire ram_en;
wire rw;
wire [4:0] ram_addr;
wire [7:0] ram_wr_data;
wire [7:0] douta;

 ram_rw   u1(
    .rst_n          (sys_rst_n),
    .clk            (sys_clk),

    .ram_en         (ram_en),          //使能信号
    .rw             (rw),              //读状态还是写状态
    .ram_addr       (ram_addr),
    .ram_wr_data    (ram_wr_data)
    );

blk_mem_gen_0 u2 (
  .clka(sys_clk),    // input wire clka
  .ena(ram_en),      // input wire ena
  .wea(rw),      // input wire [0 : 0] wea
  .addra(ram_addr),  // input wire [4 : 0] addra
  .dina(ram_wr_data),    // input wire [7 : 0] dina
  .douta(douta)  // output wire [7 : 0] douta
);



ila_0 u3 (
	.clk(sys_clk), // input wire clk
	.probe0(ram_en), // input wire [0:0]  probe0  
	.probe1(rw), // input wire [0:0]  probe1 
	.probe2(ram_addr), // input wire [4:0]  probe2 
	.probe3(ram_wr_data), // input wire [7:0]  probe3 
	.probe4(douta) // input wire [7:0]  probe4
);
endmodule

2.ram_rw.v 设置读写数据的过程。

//ram的ip核调用


module ram_rw(
    input rst_n,
    input clk,

    output reg ram_en,          //使能信号
    output reg rw,              //读状态还是写状态
    output reg [4:0] ram_addr,
    output reg [7:0] ram_wr_data

    );

    reg [5:0] cnt;             //定义计数器

    always @(posedge clk or negedge rst_n) begin      //使能信号
        if(!rst_n)
            ram_en<=1'b0;
        else
            ram_en<=1'b1;
    end



    always @(posedge clk or negedge rst_n) begin   //0到31写,32到63读
        if(!rst_n)
            cnt<=6'd0;
        else if(cnt==6'd63)
            cnt<=6'd0;
        else
            cnt<=cnt+6'd1;
    end



    always @(posedge clk or negedge rst_n) begin  //低31位写入数据
        if(!rst_n)
            ram_wr_data<=8'd0;
        else if (cnt<=6'd31&&ram_en)
             ram_wr_data<=ram_wr_data+8'd1;
        else 
            ram_wr_data<=8'd0;
    end



    always @(posedge clk or negedge rst_n) begin //0到31只写,rw为1,只写模式
        if(!rst_n)
            rw<=1'b1;
        else if (cnt<=6'd31)
            rw<=1'b1;
        else
            rw<=1'b0;
    end



     always @(posedge clk or negedge rst_n) begin //取cnt的低五位就是对应的地址大小
        if(!rst_n)
            ram_addr<=5'd0;
        else 
            ram_addr<=cnt[4:0];         //低5位数据对应的就是地址大小
     end

endmodule

7.FIFO的ip核实验

fifo_ip.v

module fifo_ip(
  input     sys_clk,
  input     sys_rst_n

    );



  wire almost_empty;
  wire almost_full;
  wire  fifo_wr_en;
  wire [7:0]  fifo_wr_data;
  wire fifo_rd_en;
  wire dout;
  wire full;
  wire empty;
  wire [7:0] rd_data_count;
  wire [7:0] wr_data_count;
  

    fifo_wr  fifo_wr_u(
    . rst_n           (sys_rst_n),
    . clk             (sys_clk),

    . almost_empty    (almost_empty),
    . almost_full     (almost_full),

    . fifo_wr_en      (fifo_wr_en ),
    . fifo_wr_data    (fifo_wr_data)
    );




    fifo_rd  fifo_rd_u(
    . rst_n           (sys_rst_n),
    . clk             (sys_clk),

    . almost_empty    (almost_empty),
    . almost_full     (almost_full),

    . fifo_rd_en      (fifo_rd_en)
    

    );

    


  fifo_generator_0  fifo_generator_0_u (
  .wr_clk(sys_clk),                // input wire wr_clk
  .rd_clk(sys_clk),                // input wire rd_clk
  .din(fifo_wr_data),                      // input wire [7 : 0] din
  .wr_en(fifo_wr_en),                  // input wire wr_en
  .rd_en(fifo_rd_en),                  // input wire rd_en
  .dout(dout),                    // output wire [7 : 0] dout
  .full(full),                    // output wire full
  .almost_full(almost_full),      // output wire almost_full
  .empty(empty),                  // output wire empty
  .almost_empty(almost_empty),    // output wire almost_empty
  .rd_data_count(rd_data_count),  // output wire [7 : 0] rd_data_count
  .wr_data_count(wr_data_count)  // output wire [7 : 0] wr_data_count
);

  ila_0 ila_0_u(
	.clk(sys_clk), // input wire clk


	.probe0(empty), // input wire [0:0]  probe0  
	.probe1(full), // input wire [0:0]  probe1 
	.probe2(almost_full), // input wire [0:0]  probe2 
	.probe3(almost_empty), // input wire [0:0]  probe3 
	.probe4(fifo_wr_data), // input wire [7:0]  probe4 
	.probe5(dout), // input wire [7:0]  probe5 
	.probe6(rd_data_count), // input wire [7:0]  probe6 
	.probe7(wr_data_count), // input wire [7:0]  probe7 
	.probe8(rd_data_count), // input wire [0:0]  probe8 
	.probe9(wr_data_count) // input wire [0:0]  probe9
);

endmodule

fifo_wr.v 写模块

//fifo写模块,这里还使用了状态机的功能

module fifo_wr(
    input                   rst_n           ,
    input                   clk             ,

    input                   almost_empty    ,
    input                   almost_full     ,

    output reg              fifo_wr_en      ,
    output reg [7:0]        fifo_wr_data

    );
    
    reg almost_empty_d0;
    reg almost_empty_syn;
    wire syn;
    reg [1:0] state;
    reg [3:0] dly_cnt;

    assign syn=~almost_empty_syn & almost_empty_d0;

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           almost_empty_d0<=1'b0;
           almost_empty_syn<=1'b0;  
        end
        else begin
           almost_empty_d0<=almost_empty;
           almost_empty_syn<=almost_empty_d0;  
        end 
    end

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            fifo_wr_en<=1'b0;
            fifo_wr_data<=8'd0;
            state<=2'd0;
            dly_cnt<=4'b0;   //延迟的时拍
        end

        else begin

        case(state)
            2'd0:begin
                if(syn) begin
                    state<=2'd1;
                end
                else
                    state<=state;
            end

            2'd1:begin
                if(dly_cnt==4'd10)begin
                    dly_cnt<=4'b0;
                    state<=2'd2;
                    fifo_wr_en<=1'b1;
                end
                else
                    dly_cnt<=dly_cnt+1'b1;
            end

            2'd2:begin
                if(almost_full)begin
                    fifo_wr_en<=1'b0;
                    fifo_wr_data<=8'd0;
                    state<=2'b0;
                end
                else begin
                    fifo_wr_en<=1'b1;
                    fifo_wr_data<=fifo_wr_data+1'd1;
                end
            end

            default: state<=2'b0;
        endcase
        end
    end

endmodule

fifo_rd.v 读模块

//fifo读模块,这里还使用了状态机的功能

module fifo_rd(
    input                   rst_n           ,
    input                   clk             ,

    input                   almost_empty    ,
    input                   almost_full     ,

    output reg              fifo_rd_en      
    

    );
    
    reg almost_full_d0;
    reg almost_full_syn;
    wire syn;
    reg [1:0] state;
    reg [3:0] dly_cnt;

    assign syn=~almost_full_syn & almost_full_d0;

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           almost_full_d0<=1'b0;
           almost_full_syn<=1'b0;  
        end
        else begin
           almost_full_d0<=almost_full;
           almost_full_syn<=almost_full_d0;  
        end 
    end

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            fifo_rd_en<=1'b0;
           
            state<=2'd0;
            dly_cnt<=4'b0;   //延迟的时拍
        end

        else begin

        case(state)
            2'd0:begin
                if(syn) begin
                    state<=2'd1;
                end
                else
                    state<=state;
            end

            2'd1:begin
                if(dly_cnt==4'd10)begin
                    dly_cnt<=4'b0;
                    state<=2'd2;
                
                end
                else
                    dly_cnt<=dly_cnt+1'b1;
            end

            2'd2:begin
                if(almost_empty)begin
                    fifo_rd_en<=1'b0;
                    
                    state<=2'b0;
                end
                else begin
                    fifo_rd_en<=1'b1;
                   //只要有写使能,会自动读取文件
                end
            end

            default: state<=2'b0;
        endcase
        end
    end

endmodule

8.uart串口接收实验

top_uart.v

module top_uart(
       input sys_clk,
       input sys_rst_n,

       input  uart_rxd,
       output uart_txd 



    );

    wire [7:0] uart_data;
    wire uart_done;

    uart_recv uart_recv_u(
    .uart_rxd                   (uart_rxd),
    .sys_clk                    (sys_clk),
    .sys_rst_n                  (sys_rst_n),
    .uart_data                  (uart_data),
    .uart_done                  (uart_done)

    );

    uart_send uart_send_u(
    .uart_en                    (uart_done),
    .sys_clk                    (sys_clk),
    .sys_rst_n                  (sys_rst_n),
    .uart_din                   (uart_data),
    .uart_txd                   (uart_txd)

    );
endmodule

uart_rece.v
在这里插入图片描述

module uart_recv(
    input    uart_rxd,
    input sys_clk,
    input sys_rst_n,
    output reg [7:0] uart_data,
    output reg uart_done

    );
    parameter CLK_FREQ = 50_000_000;
    parameter UART_BPS = 115200;
    parameter BPS_CNT = CLK_FREQ/UART_BPS;

    reg uart_rxd_d0;
    reg uart_rxd_d1;
    reg rx_flag;
    reg [3:0] rx_cnt;
    reg [15:0] clk_cnt;

    reg [8:0]  rx_data;

    wire start_flag;

    assign start_flag=~uart_rxd_d0 & uart_rxd_d1;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n) begin
            uart_rxd_d0<=1'b0;
            uart_rxd_d1<=1'b0;
        end
        else begin
            uart_rxd_d0<=uart_rxd;
            uart_rxd_d1<=uart_rxd_d0;
        end
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            rx_flag<=1'b0;
        else if(start_flag)
            rx_flag<=1'b1;
        else if((rx_cnt==4'd9)&&(clk_cnt==BPS_CNT/2-1'b1))   //最后一个周期,必须要提前结束半个周期结束,为下一个周期收听信号留下准备作用
            rx_flag<=1'b0;     
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            clk_cnt<=16'd0;
        else if(rx_flag) begin
            if(clk_cnt<BPS_CNT-1'b1)
                clk_cnt<=clk_cnt+1'b1;
            else
                clk_cnt<=16'd0;
        end
        else
                clk_cnt<=16'd0;
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           rx_cnt<=4'd0;
        else if(rx_flag) begin
            if(clk_cnt==BPS_CNT-1'b1)
                rx_cnt<=rx_cnt+1'b1;
            else 
                rx_cnt<=rx_cnt;
        end
        else
            rx_cnt<=4'd0;
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           rx_data<=8'd0;
           else if(rx_flag && (clk_cnt==BPS_CNT/2) ) begin    //在中间一半的地方来进行存储数据
               case(rx_cnt)
               4'd1: rx_data[0]<=uart_rxd_d1;                 //不同使用异步信号,使用同步之后的同步信号uart_rxd_d1而不是uart_rxd
               4'd2: rx_data[1]<=uart_rxd_d1;
               4'd3: rx_data[2]<=uart_rxd_d1;
               4'd4: rx_data[3]<=uart_rxd_d1;
               4'd5: rx_data[4]<=uart_rxd_d1;
               4'd6: rx_data[5]<=uart_rxd_d1;
               4'd7: rx_data[6]<=uart_rxd_d1;
               4'd8: rx_data[7]<=uart_rxd_d1;
                
               endcase
           end
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n) begin
            uart_done<=1'b0;
            uart_data<=8'd0;
        end
        else if(rx_cnt==4'd9) begin
            uart_done<=1'b1;
            uart_data<=rx_data;
        end
        else begin
            uart_done<=1'b0;
            uart_data<=8'd0; 
        end
    end

endmodule

uart_send.v
在这里插入图片描述

module uart_send(
    input    uart_en,
    input    sys_clk,
    input    sys_rst_n,
    input  [7:0] uart_din,
    output  reg  uart_txd

    );
    parameter CLK_FREQ = 50_000_000;
    parameter UART_BPS = 115200;
    parameter BPS_CNT = CLK_FREQ/UART_BPS;

    reg uart_en_d0;
    reg uart_en_d1;
    reg tx_flag;
    reg [3:0] tx_cnt;
    reg [15:0] clk_cnt;

    reg [8:0]  tx_data;

    wire en_flag;

    assign en_flag=(~uart_en_d1) & uart_en_d0;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n) begin
           uart_en_d0<=1'b0;
           uart_en_d1<=1'b0;
        end
        else begin
           uart_en_d0<=uart_en;
        uart_en_d1<=uart_en_d0;
        end
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
                tx_data<=8'd0;
        else if(en_flag ) begin
                tx_data<=uart_din;
        end
        else
                tx_data<=tx_data;
        
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            tx_flag<=1'b0;
        else if(en_flag)
            tx_flag<=1'b1;
        else if((tx_cnt==4'd9)&&(clk_cnt==BPS_CNT/2-1'b1))   //最后一个周期,必须要提前结束半个周期结束,为下一个周期收听信号留下准备作用
            tx_flag<=1'b0;     
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            clk_cnt<=16'd0;
        else if(en_flag) begin
            if(clk_cnt<BPS_CNT-1'b1)
                clk_cnt<=clk_cnt+1'b1;
            else
                clk_cnt<=16'd0;
        end
        else
                clk_cnt<=16'd0;
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           tx_cnt<=4'd0;
        else if(en_flag) begin
            if(clk_cnt==BPS_CNT-1)
                tx_cnt<=tx_cnt+1'b1;
            else 
               tx_cnt<=tx_cnt;
        end
        else
             tx_cnt<=4'd0;
    end




    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           uart_txd<=1'b1;
           else if(en_flag && (clk_cnt==16'd0) ) begin    //在中间一半的地方来进行存储数据
               case(tx_cnt)
               4'd0: uart_txd<=1'b0;
               4'd1: uart_txd<=tx_data[0];                 //不同使用异步信号,使用同步之后的同步信号uart_rxd_d1而不是uart_rxd
               4'd2: uart_txd<=tx_data[1];
               4'd3: uart_txd<=tx_data[2];
               4'd4: uart_txd<=tx_data[3];
               4'd5: uart_txd<=tx_data[4];
               4'd6: uart_txd<=tx_data[5];
               4'd7: uart_txd<=tx_data[6];
               4'd8: uart_txd<=tx_data[7];
                
               endcase
           end
    end


    // always @(posedge sys_clk or negedge sys_rst_n) begin
    //     if(!sys_rst_n) begin
    //         uart_done<=1'b0;
    //         uart_data<=8'd0;
    //     end
    //     else if(rx_cnt==4'd9) begin
    //         uart_done<=1'b1;
    //         uart_data<=rx_data;
    //     end
    //     else begin
    //         uart_done<=1'b0;
    //         uart_data<=8'd0; 
    //     end
    // end

endmodule

9.uart串口接收实验,加入一个loop来防止连续传送带来的数据丢失问题

在这里插入图片描述
top_uart_loop.v

module top_uart(
       input sys_clk,
       input sys_rst_n,

       input  uart_rxd,
       output uart_txd 



    );

    // wire [7:0] uart_data;
    // wire uart_done;

    wire [7:0] uart_recv_data;
    wire [7:0] uart_send_data;
    wire uart_send_en;
    wire uart_tx_busy;
    wire uart_recv_done;


    uart_recv uart_recv_u(
    .uart_rxd                   (uart_rxd),
    .sys_clk                    (sys_clk),
    .sys_rst_n                  (sys_rst_n),
    .uart_data                  (uart_recv_data),
    .uart_done                  (uart_recv_done)

    );

    uart_send uart_send_u(
    .uart_en                    (uart_send_en),
    .sys_clk                    (sys_clk),
    .sys_rst_n                  (sys_rst_n),
    .uart_din                   (uart_send_data),
    .uart_txd                   (uart_txd),
    .uart_tx_busy               (uart_tx_busy)

    );

    //串口的环回模块

     uart_loop uart_loop_u(
         .sys_clk  (sys_clk),
         .sys_rst_n(sys_rst_n),

         .recv_done(uart_recv_done),
         .recv_data(uart_recv_date),

         .tx_busy(uart_tx_busy),
         .send_en(uart_send_en),
         .send_data(uart_send_data)

     ); 

endmodule

top_uart_recv.v

module uart_recv(
    input    uart_rxd,
    input sys_clk,
    input sys_rst_n,
    output reg [7:0] uart_data,
    output reg uart_done

    );
    parameter CLK_FREQ = 50_000_000;
    parameter UART_BPS = 115200;
    parameter BPS_CNT = CLK_FREQ/UART_BPS;

    reg uart_rxd_d0;
    reg uart_rxd_d1;
    reg rx_flag;
    reg [3:0] rx_cnt;
    reg [15:0] clk_cnt;

    reg [8:0]  rx_data;

    wire start_flag;

    assign start_flag=~uart_rxd_d0 & uart_rxd_d1;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n) begin
            uart_rxd_d0<=1'b0;
            uart_rxd_d1<=1'b0;
        end
        else begin
            uart_rxd_d0<=uart_rxd;
            uart_rxd_d1<=uart_rxd_d0;
        end
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            rx_flag<=1'b0;
        else if(start_flag)
            rx_flag<=1'b1;
        else if((rx_cnt==4'd9)&&(clk_cnt==BPS_CNT/2-1'b1))   //最后一个周期,必须要提前结束半个周期结束,为下一个周期收听信号留下准备作用
            rx_flag<=1'b0;     
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            clk_cnt<=16'd0;
        else if(rx_flag) begin
            if(clk_cnt<BPS_CNT-1'b1)
                clk_cnt<=clk_cnt+1'b1;
            else
                clk_cnt<=16'd0;
        end
        else
                clk_cnt<=16'd0;
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           rx_cnt<=4'd0;
        else if(rx_flag) begin
            if(clk_cnt==BPS_CNT-1'b1)
                rx_cnt<=rx_cnt+1'b1;
            else 
                rx_cnt<=rx_cnt;
        end
        else
            rx_cnt<=4'd0;
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           rx_data<=8'd0;
           else if(rx_flag && (clk_cnt==BPS_CNT/2) ) begin    //在中间一半的地方来进行存储数据
               case(rx_cnt)
               4'd1: rx_data[0]<=uart_rxd_d1;                 //不同使用异步信号,使用同步之后的同步信号uart_rxd_d1而不是uart_rxd
               4'd2: rx_data[1]<=uart_rxd_d1;
               4'd3: rx_data[2]<=uart_rxd_d1;
               4'd4: rx_data[3]<=uart_rxd_d1;
               4'd5: rx_data[4]<=uart_rxd_d1;
               4'd6: rx_data[5]<=uart_rxd_d1;
               4'd7: rx_data[6]<=uart_rxd_d1;
               4'd8: rx_data[7]<=uart_rxd_d1;
                
               endcase
           end
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n) begin
            uart_done<=1'b0;
            uart_data<=8'd0;
        end
        else if(rx_cnt==4'd9) begin
            uart_done<=1'b1;
            uart_data<=rx_data;
        end
        else begin
            uart_done<=1'b0;
            uart_data<=8'd0; 
        end
    end

endmodule

top_uart_send.v

module uart_send(
    input    uart_en,
    input    sys_clk,
    input    sys_rst_n,
    input  [7:0] uart_din,
    output  reg  uart_txd,
    output       uart_tx_busy

    );
    parameter CLK_FREQ = 50_000_000;
    parameter UART_BPS = 115200;
    parameter BPS_CNT = CLK_FREQ/UART_BPS;
    

    reg uart_en_d0;
    reg uart_en_d1;
    reg tx_flag;
    reg [3:0] tx_cnt;
    reg [15:0] clk_cnt;

    reg [8:0]  tx_data;

    wire en_flag;

    assign en_flag=(~uart_en_d1) & uart_en_d0;
    assign uart_tx_busy = tx_flag;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n) begin
           uart_en_d0<=1'b0;
           uart_en_d1<=1'b0;
        end
        else begin
           uart_en_d0<=uart_en;
        uart_en_d1<=uart_en_d0;
        end
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
                tx_data<=8'd0;
        else if(en_flag ) begin
                tx_data<=uart_din;
        end
        else
                tx_data<=tx_data;
        
    end


    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            tx_flag<=1'b0;
        else if(en_flag)
            tx_flag<=1'b1;
        else if((tx_cnt==4'd9)&&(clk_cnt==BPS_CNT/2-1'b1))   //最后一个周期,必须要提前结束半个周期结束,为下一个周期收听信号留下准备作用
        //但是效果不是很好。可以考虑增加半个周期,改为4/5周期,也可以考虑增加一个uart_loop缓冲的模块
            tx_flag<=1'b0;     
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            clk_cnt<=16'd0;
        else if(en_flag) begin
            if(clk_cnt<BPS_CNT-1'b1)
                clk_cnt<=clk_cnt+1'b1;
            else
                clk_cnt<=16'd0;
        end
        else
                clk_cnt<=16'd0;
    end

    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           tx_cnt<=4'd0;
        else if(en_flag) begin
            if(clk_cnt==BPS_CNT-1)
                tx_cnt<=tx_cnt+1'b1;
            else 
               tx_cnt<=tx_cnt;
        end
        else
             tx_cnt<=4'd0;
    end




    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
           uart_txd<=1'b1;
           else if(en_flag && (clk_cnt==16'd0) ) begin    //在中间一半的地方来进行存储数据
               case(tx_cnt)
               4'd0: uart_txd<=1'b0;
               4'd1: uart_txd<=tx_data[0];                 //不同使用异步信号,使用同步之后的同步信号uart_rxd_d1而不是uart_rxd
               4'd2: uart_txd<=tx_data[1];
               4'd3: uart_txd<=tx_data[2];
               4'd4: uart_txd<=tx_data[3];
               4'd5: uart_txd<=tx_data[4];
               4'd6: uart_txd<=tx_data[5];
               4'd7: uart_txd<=tx_data[6];
               4'd8: uart_txd<=tx_data[7];
                
               endcase
           end
    end


    // always @(posedge sys_clk or negedge sys_rst_n) begin
    //     if(!sys_rst_n) begin
    //         uart_done<=1'b0;
    //         uart_data<=8'd0;
    //     end
    //     else if(rx_cnt==4'd9) begin
    //         uart_done<=1'b1;
    //         uart_data<=rx_data;
    //     end
    //     else begin
    //         uart_done<=1'b0;
    //         uart_data<=8'd0; 
    //     end
    // end

endmodule

uart_loop.v

module uart_loop(
         input sys_clk  ,
         input sys_rst_n,

         input recv_done,
         input [7:0] recv_data,

         input tx_busy,
         output reg send_en,
         output reg [7:0] send_data
    );

    reg recv_done_d0;
    reg recv_done_d1;
    reg tx_ready;

    wire recv_done_flag;

    //边缘检测信号
    assign recv_done_flag= (~recv_done_d1)&recv_done_d0;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)begin
            recv_done_d0<=1'b0;
            recv_done_d1<=1'b0;
        end
        else begin
            recv_done_d0<=recv_done;
            recv_done_d1<=recv_done_d0;
        end 
    end

     always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)begin
            tx_ready<=1'b0;
            send_en<=1'b0;
            send_data<=8'd0;
        end
        else begin
        if(recv_done_flag)begin
            tx_ready<=1'b1;
            send_en<=1'b0;
            send_data<=recv_data;
        end
        else if (tx_ready && (~tx_busy)) begin         //检测串口的发送模块,拉高来发送使能信号的大小
            tx_ready<=1'b0;
            send_en<=1'b1;
        end
    end
    end

endmodule

10.LCD点亮RGB色条

在这里插入图片描述
lcd_rgb_clolorbar.v(top)

module lcd_rgb_clolorbar(
    input       sys_clk,
    input       sys_rst_n,

    //RGB LCD
    output              lcd_de,
    output              lcd_hs,
    output              lcd_vs,
    output              lcd_bl,
    output              lcd_clk,
    inout      [23:0]   lcd_rgb  //既要输入也需要输出的端口,我们把他改成inout的端口类型

    );


    wire  [23:0] lcd_rgb_i;
    wire  [15:0] lcd_id;

    wire         lcd_pclk;

    wire [10:0]       pixel_xpos;   //显示周期大小设置
    wire [10:0]       pixel_ypos;
    wire [10:0]       h_disp;       //分辨率
    wire [10:0]       v_disp;

    wire [23:0]       pixel_data; //颜色
    wire [23:0]   lcd_rgb_o ;

    assign lcd_rgb_i = lcd_rgb;
    assign lcd_rgb   = lcd_de ? lcd_rgb_o: {24{1'bz}};             //24位全部是最高位的大小,即为白色的结果????

    rd_id rd_id_u(
    .clk            (sys_clk),
    .rst_n          (sys_rst_n),
    .lcd_rgb        (lcd_rgb_i),    
    .lcd_id         (lcd_id)
    );

    CLOCK_DIV CLOCK_DIV_u(
    .clk(sys_clk),
    .rst_n(sys_rst_n),
    .lcd_id(lcd_id),
    .lcd_plck(lcd_plck)
    );

    lcd_display lcd_display_u(
   .lcd_pclk         (lcd_pclk)                   ,
   .rst_n            (sys_rst_n)                  ,
   .pixel_xpos       (pixel_xpos)                 ,   //显示周期大小设置
   .pixel_ypos       (pixel_ypos)                 ,
   .h_disp           (h_disp)                     ,       //分辨率
   .v_disp           (v_disp)                     ,

   .pixel_data       (pixel_data)                   //颜色
    );

    lcd_driver lcd_driver_u(
    .lcd_pclk(lcd_pclk),
    .rst_n(sys_rst_n),
    .lcd_id(lcd_id),
    .pixel_data(pixel_data),

    .pixel_xpos(pixel_xpos),  //显示周期大小设置
    .pixel_ypos(pixel_ypos),
    .h_disp(h_disp),      //分辨率
    .v_disp(v_disp),
    //RGB LCD
    .lcd_de(lcd_de),
    .lcd_hs(lcd_hs),
    .lcd_vs(lcd_vs),
    .lcd_bl(lcd_bl),
    .lcd_clk(lcd_clk),
    .lcd_rgb(lcd_rgb_o)
    );
endmodule

rd_id.v

//LCD读取id的那个模块
module rd_id(
    input clk,
    input rst_n,
    input [23:0] lcd_rgb,
    output reg [15:0] lcd_id
    );

    reg rd_flag; //获取id的标志

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            rd_flag<=1'b0;
            lcd_id<=16'd0;
        end
        else begin
            if(rd_flag==1'b0) begin
                rd_flag<=1'b1;
                case({lcd_rgb[7],lcd_rgb[15],lcd_rgb[23]})  //M2:B7,M1:G7,M0:R7
                3'b000: lcd_id<=16'h4342; //4.3寸
                3'b001: lcd_id<=16'h7084; //4.3寸
                3'b010: lcd_id<=16'h7016; //4.3寸
                3'b100: lcd_id<=16'h4384; //4.3寸
                3'b101: lcd_id<=16'h1018; //4.3寸
                default:  lcd_id<=16'd0;
                endcase
        end
        end 
    end
endmodule

CLOCK_DIV.v

//对时钟进行一个分频的操作
module CLOCK_DIV(
    input  clk,
    input rst_n,
    input  [15:0] lcd_id,
    output  reg lcd_pclk

    );

    reg clk_25m;
    reg clk_12_5m;
    reg div_4_cnt;

//2分频
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            clk_25m <= 1'b0;
        end
        else
            clk_25m <= ~clk_25m; 
    end

//4分频
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            clk_12_5m <= 1'b0;
            div_4_cnt <= 1'b0;
        end
        else begin
            div_4_cnt <= div_4_cnt + 1'b1;
            if(div_4_cnt == 1'b1)
                clk_12_5m<=~clk_12_5m;
    end
    end

    always @(*) begin
        case(lcd_id)
        16'h4342:  lcd_pclk <= clk_12_5m;
        16'h7084:  lcd_pclk <= clk_25m;
        16'h7016:  lcd_pclk <= clk;
        16'h4384:  lcd_pclk <= clk_25m;
        16'h1018:  lcd_pclk <= clk;
        default:   lcd_pclk <= 1'b0;
        endcase
        
    end



endmodule

lcd_display.v

//显示模块
module lcd_display(
    input                   lcd_pclk,
    input                   rst_n,
    input      [10:0]       pixel_xpos,   //显示周期大小设置
    input      [10:0]       pixel_ypos,
    input      [10:0]       h_disp,       //分辨率
    input      [10:0]       v_disp,

    output reg [23:0]       pixel_data //颜色
    );

    parameter WHITE = 24'hffffff;
    parameter BLACK = 24'h000000;
    parameter RED   = 24'hff0000;
    parameter GREEN = 24'h00ff00;
    parameter BLUE  = 24'h0000ff;

    always @(posedge lcd_pclk or negedge rst_n) begin
        if(!rst_n)
            pixel_data <= BLACK ;
        else begin
            if((pixel_xpos >= 11'd0) && (pixel_xpos < h_disp/5*1))            //第一个彩条 白色
               pixel_data <= WHITE ;
            else if((pixel_xpos >= h_disp/5*1) && (pixel_xpos < h_disp/5*2))  //第二个彩条 黑色
               pixel_data <= BLACK ;
            else if((pixel_xpos >= h_disp/5*2) && (pixel_xpos < h_disp/5*3))  //第三个彩条 红色
               pixel_data <= RED ;
            else if((pixel_xpos >= h_disp/5*3) && (pixel_xpos < h_disp/5*4))  //第四个彩条 绿色
               pixel_data <= GREEN ;
            else                                                              //第五个彩条 蓝色
               pixel_data <= BLUE ;
        end
        
    end






endmodule

lcd_driver.v

//驱动操作
module lcd_driver(
    input               lcd_pclk,
    input               rst_n,
    input       [15:0]  lcd_id,
    input       [23:0]  pixel_data,

    output      [10:0]  pixel_xpos,  //显示周期大小设置
    output      [10:0]  pixel_ypos,
    output      reg [10:0]  h_disp,      //分辨率
    output      reg [10:0]  v_disp,
    //RGB LCD
    output              lcd_de,
    output              lcd_hs,
    output              lcd_vs,
    output              lcd_bl,
    output              lcd_clk,
    output      [23:0]  lcd_rgb
    );

    //4.3' 480x472
    parameter H_SYNC_4342 = 11'd41;         //行同步
    parameter H_BACK_4342 = 11'd2;          //行显示后延
    parameter H_DISP_4342 = 11'd480;        //行显示区域
    parameter H_FRONT_4342 = 11'd2;         //行显示前沿
    parameter H_TOTAL_4342 = 11'd525;       //行总计

    parameter V_SYNC_4342 = 11'd10;         //列同步
    parameter V_BACK_4342 = 11'd2;          //列显示后延
    parameter V_DISP_4342 = 11'd272;        //列显示区域
    parameter V_FRONT_4342 = 11'd2;         //列显示前沿
    parameter V_TOTAL_4342 = 11'd286;       //列总计


    // 7' 800*480   
    parameter  H_SYNC_7084   =  11'd128;    
    parameter  H_BACK_7084   =  11'd88;     
    parameter  H_DISP_7084   =  11'd800;    
    parameter  H_FRONT_7084  =  11'd40;     
    parameter  H_TOTAL_7084  =  11'd1056;   
    
    parameter  V_SYNC_7084   =  11'd2;      
    parameter  V_BACK_7084   =  11'd33;     
    parameter  V_DISP_7084   =  11'd480;    
    parameter  V_FRONT_7084  =  11'd10;     
    parameter  V_TOTAL_7084  =  11'd525;     
    
    // 7' 1024*600   
    parameter  H_SYNC_7016   =  11'd20;     
    parameter  H_BACK_7016   =  11'd140;    
    parameter  H_DISP_7016   =  11'd1024;   
    parameter  H_FRONT_7016  =  11'd160;    
    parameter  H_TOTAL_7016  =  11'd1344;   
    
    parameter  V_SYNC_7016   =  11'd3;      
    parameter  V_BACK_7016   =  11'd20;     
    parameter  V_DISP_7016   =  11'd600;    
    parameter  V_FRONT_7016  =  11'd12;     
    parameter  V_TOTAL_7016  =  11'd635;    
    
    // 10.1' 1280*800   
    parameter  H_SYNC_1018   =  11'd10;     
    parameter  H_BACK_1018   =  11'd80;     
    parameter  H_DISP_1018   =  11'd1280;   
    parameter  H_FRONT_1018  =  11'd70;     
    parameter  H_TOTAL_1018  =  11'd1440;   
    
    parameter  V_SYNC_1018   =  11'd3;      
    parameter  V_BACK_1018   =  11'd10;     
    parameter  V_DISP_1018   =  11'd800;    
    parameter  V_FRONT_1018  =  11'd10;     
    parameter  V_TOTAL_1018  =  11'd823;    

    // 4.3' 800*480   
    parameter  H_SYNC_4384   =  11'd128;    
    parameter  H_BACK_4384   =  11'd88;     
    parameter  H_DISP_4384   =  11'd800;    
    parameter  H_FRONT_4384  =  11'd40;     
    parameter  H_TOTAL_4384  =  11'd1056;   
    
    parameter  V_SYNC_4384   =  11'd2;      
    parameter  V_BACK_4384   =  11'd33;     
    parameter  V_DISP_4384   =  11'd480;    
    parameter  V_FRONT_4384  =  11'd10;     
    parameter  V_TOTAL_4384  =  11'd525;        


    reg [10:0]  h_sync;
    reg [10:0]  h_back;
    reg [10:0]  h_total;

    reg [10:0]  v_sync;
    reg [10:0]  v_back;
    reg [10:0]  v_total;

    reg [15:0]  h_cnt;
    reg [15:0]  v_cnt;



    wire lcd_en;
    wire data_req;

    assign lcd_hs =1'b1;
    assign lcd_vs =1'b1;
    assign lcd_bl =1'b1;
    assign lcd_clk =lcd_pclk;
    assign lcd_de = lcd_en;

    assign lcd_en= ( h_cnt >= h_sync + h_back ) && ( h_cnt < h_sync + h_back + h_disp)
                    &&( v_cnt >= v_sync +v_back ) && ( v_cnt < v_sync + v_back + v_disp)
                    ? 1'b1 : 1'b0 ;

    assign lcd_rgb = lcd_en ? pixel_data : 24'd0 ;

    assign data_req= ( h_cnt >= h_sync + h_back -1'b1) && ( h_cnt < h_sync + h_back + h_disp -1'b1)
                    &&( v_cnt >= v_sync +v_back ) && ( v_cnt < v_sync + v_back + v_disp)
                    ? 1'b1 : 1'b0 ; 
                    
    //  提前一个时钟周期发送确定位置(坐标)的信号大小

    assign pixel_xpos = data_req ? ( h_cnt - ( h_sync + h_back -1'b1 )) : 11'd0;  //垂直方向的有效坐标
    assign pixel_ypos = data_req ? ( v_cnt - ( v_sync + v_back -1'b1 )) : 11'd0;  //水平方向的有效坐标





    always @(*) begin
        case(lcd_id)
            16'h4342: begin
                h_sync  = H_SYNC_4342;
                h_back  = H_BACK_4342;
                h_total = H_TOTAL_4342;
                v_sync  = V_SYNC_4342;
                v_back  = V_BACK_4342;
                v_total = V_TOTAL_4342;
            end
            16'h7084 : begin
                h_sync  = H_SYNC_7084; 
                h_back  = H_BACK_7084; 
                h_disp  = H_DISP_7084; 
                h_total = H_TOTAL_7084;
                v_sync  = V_SYNC_7084; 
                v_back  = V_BACK_7084; 
                v_disp  = V_DISP_7084; 
                v_total = V_TOTAL_7084;        
            end
            16'h7016 : begin
                h_sync  = H_SYNC_7016; 
                h_back  = H_BACK_7016; 
                h_disp  = H_DISP_7016; 
                h_total = H_TOTAL_7016;
                v_sync  = V_SYNC_7016; 
                v_back  = V_BACK_7016; 
                v_disp  = V_DISP_7016; 
                v_total = V_TOTAL_7016;            
            end
            16'h4384 : begin
                h_sync  = H_SYNC_4384; 
                h_back  = H_BACK_4384; 
                h_disp  = H_DISP_4384; 
                h_total = H_TOTAL_4384;
                v_sync  = V_SYNC_4384; 
                v_back  = V_BACK_4384; 
                v_disp  = V_DISP_4384; 
                v_total = V_TOTAL_4384;             
            end        
            16'h1018 : begin
                h_sync  = H_SYNC_1018; 
                h_back  = H_BACK_1018; 
                h_disp  = H_DISP_1018; 
                h_total = H_TOTAL_1018;
                v_sync  = V_SYNC_1018; 
                v_back  = V_BACK_1018; 
                v_disp  = V_DISP_1018; 
                v_total = V_TOTAL_1018;        
            end
            default : begin
                h_sync  = H_SYNC_4342; 
                h_back  = H_BACK_4342; 
                h_disp  = H_DISP_4342; 
                h_total = H_TOTAL_4342;
                v_sync  = V_SYNC_4342; 
                v_back  = V_BACK_4342; 
                v_disp  = V_DISP_4342; 
                v_total = V_TOTAL_4342;          
            end
        endcase  
    end



    //h_cnt 行的计数器
    always @(posedge lcd_pclk or negedge rst_n) begin
        if(!rst_n)
            h_cnt <=16'd0;
        else begin
            if(h_cnt == h_total-1'b1)
                 h_cnt <=16'd0;
            else
                 h_cnt <= h_cnt + 1'b1;
        end
    end

    //V_cnt 列的计数器
    always @(posedge lcd_pclk or negedge rst_n) begin
        if(!rst_n)
            v_cnt <=16'd0;
        else begin
            if(h_cnt == h_total-1'b1) begin
                if(v_cnt == v_total-1'b1)
                    v_cnt <= 16'd0;
                else
                     v_cnt <= v_cnt+1'b1;
        end
    end
    end


endmodule
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jun_luo_yu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值