FPGA project : sobel

实验目标:

sobel算法,处理100X100灰度图像:野火logo

边缘检测:

边缘检测,针对的是灰度图像,顾名思义,检测图像的边缘,是针对图像像素点的一种计算,目的是标识数字图像中灰度变化明显的点,图像的边缘检测,在保留了图像的重要结构信息的同时,剔除了可以认为不相关的信息,大幅度减少了数据量,便于图像的传输和处理。

什么是sobel算法:

 算出来的Gxy与一个数据T比较大小,大于T则b2像素点赋值为黑色,小于赋值白色。

我踩得坑:

vga_pic模块,调用的时候由于图片大小需要更改,当初写vga_pic模块的时候,没有把代码中的一些数,用parameter表示,在修改的时候很麻烦。所以以后写代码的时候,大于2的参数一定要重新定义一下,代码写的应该更具复用性。

代码复用性也是代码质量的体现。

经验总结:

想要沉浸式写代码,就要清清楚楚的画好时序图。在写代码之前就应该想清楚用到的每个信号的时序图应该是什么样的。

fpga开发一大部分时间花在整体(顶层)设计上,一部分时间花在如何把想法转换为Verilog语言,一部分时间花在仿真调试上。

我认为最重要的就是整体设计,以及画好时序图。或者有流程图或者相关的辅助你把想法转换为代码的图。

模块框图:

时序图: 

特别大

代码:

 就放sobel算法部分,和顶层。

module sobel(
    input		wire 			clk_50		,
    input 		wire 			sys_rst_n 	,
    input 		wire	[7:0]	pi_data		,
    input 		wire 			pi_flag 	,
    
    output 		reg  			po_flag		,
    output		reg  	[7:0]	po_data 
);
    // parameter
    parameter	MAX_LINE = 8'd100 		 ,
                MAX_COL  = 8'd100 		 ,
                THR      = 8'b0000_1100  ,
                BLACK    = 8'b0000_0000  ,
                WHITE    = 8'b1111_1111  ;
                
    // reg signal define
    reg 	[7:0]	cnt_line	;
    reg 	[7:0]	cnt_col		;
    reg 			wrreq1		;
    reg		[7:0]	dataf1_in	;
    reg 			rdreq		;
    reg				wrreq2		;
    reg 	[7:0]	dataf2_in	;
    reg  	[7:0]	pi_data_reg1;
    reg     [7:0]	cnt_read 	; // 对从FIFO中读出的数据个数计数。
    reg 			dataRegFlag ;
    reg 	[7:0]	fifo1_reg   ;
    reg		[7:0]	fifo2_reg	;
    reg  	[7:0]	pi_data_reg2;
    reg  	[7:0]	pi_data_reg3; // 用来保存pi_data以进行sobel运算。不是单纯的对pi_data_reg2打拍。
    reg 			flag_abc	;
    reg		[7:0]	a3			;
    reg 	[7:0]	b3			;
    reg		[7:0]	c3			;
    reg		[7:0]	a2			;
    reg 	[7:0]	b2			;
    reg		[7:0]	c2			;
    reg		[7:0]	a1			;
    reg 	[7:0]	b1			;
    reg		[7:0]	c1			;
    reg  			arithmetic  ; // 进行sobel算法的标志。
    reg 	[8:0]	gx			; // 因为有符号位,所以运算过后要多加一位。
    reg		[8:0]	gy			; // 因为有符号位,所以运算过后要多加一位。
    reg 			flag_gxy	;
    reg		[8:0]	gxy			;
    reg				answer_flag ;
    
    // wire signal define
    wire            rdreq_w     ;    
    wire 			wrreq1_w	;
    wire 	[7:0]	dataf1_in_w ;
    wire	[7:0]	dataf1_out	;
    wire    [9:0]   usedw_f1    ;
    wire            full_f1     ;
    wire            empty_f1    ;
    wire			wrreq2_w	;
    wire	[7:0]	dataf2_in_w ;
    wire	[7:0]	dataf2_out	;
    wire    [9:0]   usedw_f2    ;
    wire            full_f2     ;
    wire            empty_f2    ;

/*********************************************************************/
// 	reg 	[7:0]	cnt_line	;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_line <= 8'd0 ;
        else if(pi_flag && cnt_col == MAX_COL - 1 && cnt_line == MAX_LINE - 1)
            cnt_line <= 8'd0 ;
        else if(pi_flag && cnt_col == MAX_COL - 1)
            cnt_line <= cnt_line + 1'b1 ;
        else 
            cnt_line <= cnt_line ;
    end
// 	reg 	[7:0]	cnt_col		;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_col <= 8'd0 ;
        else if(pi_flag && cnt_col == MAX_COL - 1)
            cnt_col <= 8'd0 ;
        else if(pi_flag)
            cnt_col <= cnt_col + 1'b1 ;
        else 
            cnt_col <= cnt_col ;
    end
// 	reg 			wrreq1		;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            wrreq1 <= 1'b0 ;
        else if(cnt_line == 0)
            wrreq1 <= pi_flag ;
        else if(((cnt_line == 2) && (cnt_col != 0)) 
                || ((cnt_line) > 2 && (cnt_line < MAX_LINE - 1)) 
                || ((cnt_line == MAX_LINE - 1) && (cnt_col == 0))) 
            wrreq1 <= wrreq2 ;
        else 
            wrreq1 <= 1'b0 ;
    end
// 	reg		[7:0]	dataf1_in	;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            dataf1_in <= 8'd0 ;
        else if(cnt_line == 0)
            dataf1_in <= pi_data ;
        else if(((cnt_line == 2) && (cnt_col != 0)) 
                || ((cnt_line) > 2 && (cnt_line < MAX_LINE - 1)) 
                || ((cnt_line == MAX_LINE - 1) && (cnt_col == 0))) 
            dataf1_in <= dataf2_out ;
        else 
            dataf1_in <= dataf1_in ;
    end
// 	reg 			rdreq		;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            rdreq <= 1'b0 ;
        else if(cnt_line >= 2)
            rdreq <= pi_flag ;
        else 
            rdreq <= 1'b0 ; 
    end
// 	reg				wrreq2		;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            wrreq2 <= 1'b0 ;
        else if(cnt_line == 1)
            wrreq2 <= pi_flag ;
        else if((cnt_line >= 2 && cnt_line <= (MAX_LINE - 1)) 
                || (cnt_line == (MAX_LINE - 1) && (cnt_col == 0)) ) 
            wrreq2 <= rdreq ;
        else 
            wrreq2 <= 1'b0 ;
    end
// 	reg 	[7:0]	dataf2_in	;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            dataf2_in <= 8'd0 ;
        else if(cnt_line == 1)
            dataf2_in <= pi_data ;
        else if((cnt_line >= 2 && cnt_line <= (MAX_LINE - 1)) 
                || (cnt_line == (MAX_LINE - 1) && (cnt_col == 0)) ) 
            dataf2_in <= pi_data_reg1 ;
        else 
            dataf2_in <= dataf2_in ;
    end
// 	reg  	[7:0]	pi_data_reg1;
// 	reg  	[7:0]	pi_data_reg2;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            pi_data_reg1 <= 8'd0 ;
            pi_data_reg2 <= 8'd0 ;
        end else begin
            pi_data_reg1 <= pi_data      ;
            pi_data_reg2 <= pi_data_reg1 ;
        end
    end
// 	reg     [7:0]	cnt_read 	;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_read <= 8'd0 ;
        else if(rdreq && cnt_read == MAX_COL - 1)
            cnt_read <= 8'd0 ;
        else if(rdreq)
            cnt_read <= cnt_read + 1'b1 ;
        else 
            cnt_read <= cnt_read ;            
    end
// 	reg 			dataRegFlag ;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            dataRegFlag <= 1'b0 ;
        else 
            dataRegFlag <= rdreq ; 
    end
// 	reg 	[7:0]	fifo1_reg   ;
// 	reg		[7:0]	fifo2_reg	;
// 	reg  	[7:0]	pi_data_reg3;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            fifo1_reg    <= 8'd0 ;
            fifo2_reg    <= 8'd0 ;
            pi_data_reg3 <= 8'd0 ;
        end else begin
            if(dataRegFlag) begin
                fifo1_reg    <= dataf1_out   ;
                fifo2_reg    <= dataf2_out   ;
                pi_data_reg3 <= pi_data_reg2 ;
            end else begin
                fifo1_reg    <= fifo1_reg    ;
                fifo2_reg    <= fifo2_reg    ;
                pi_data_reg3 <= pi_data_reg3 ;
            end
        end
    end
// 	reg 			flag_abc	;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            flag_abc <= 1'b0 ;
        else 
            flag_abc <= dataRegFlag ;
    end
// 	reg		[7:0]	a3			;
// 	reg 	[7:0]	b3			;
// 	reg		[7:0]	c3			;
// 	reg		[7:0]	a2			;
// 	reg 	[7:0]	b2			;
// 	reg		[7:0]	c2			;
// 	reg		[7:0]	a1			;
// 	reg 	[7:0]	b1			;
// 	reg		[7:0]	c1			;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            a3 <= 8'd0 ;
            b3 <= 8'd0 ;
            c3 <= 8'd0 ;
            a2 <= 8'd0 ;
            b2 <= 8'd0 ;
            c2 <= 8'd0 ;
            a1 <= 8'd0 ;
            b1 <= 8'd0 ;
            c1 <= 8'd0 ;
        end else begin
            if(flag_abc) begin
                a3 <= fifo1_reg    ;
                b3 <= fifo2_reg    ;
                c3 <= pi_data_reg3 ;
                a2 <= a3 ;
                b2 <= b3 ;
                c2 <= c3 ;
                a1 <= a2 ;
                b1 <= b2 ;
                c1 <= c2 ;
            end else begin
                a3 <= a3 ;
                b3 <= b3 ;
                c3 <= c3 ;
                a2 <= a2 ;
                b2 <= b2 ;
                c2 <= c2 ;
                a1 <= a1 ;
                b1 <= b1 ;
                c1 <= c1 ;
            end
        end
    end
// 	reg  			arithmetic  ;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            arithmetic <= 1'b0 ;
        else if(cnt_col != 1 && cnt_col != 2)
            arithmetic <= flag_abc ;
        else 
            arithmetic <= 1'b0 ;
    end
// 	reg 	[8:0]	gx			;
// 	reg		[8:0]	gy			;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            gx <= 9'd0 ;
            gy <= 9'd0 ;
        end else begin
            if(arithmetic) begin
                gx <= (a3-a1)+((b3-b1) << 1)+(c3-c1) ; // 向左移动1bit相当于扩大二倍。
                gy <= (a1-c1)+((a2-c2) << 1)+(a3-c3) ; // 向左移动1bit相当于扩大二倍。
            end else begin
                gx <= gx ;
                gy <= gy ;
            end
        end
    end
// 	reg 			flag_gxy	;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n)
            flag_gxy <= 1'b0 ;
        else 
            flag_gxy <= arithmetic ;
    end

// 	reg		[8:0]	gxy			;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            gxy <= 8'd0 ;
        else if(flag_gxy) begin
            case ({gx[8],gy[8]})
            2'b00  : gxy <=  gx[7:0] +  gy[7:0]        ;
            2'b01  : gxy <=  gx[7:0] + ~gy[7:0] + 1'b1 ;
            2'b10  : gxy <= ~gx[7:0] +  gy[7:0] + 1'b1 ;
            2'b11  : gxy <= ~gx[7:0] + ~gy[7:0] + 2'd2 ;
            default: gxy <= gxy ;
            endcase
        end //    gxy <= {1'b0,gx[7:0]} + {1'b0,gy[7:0]} ; // 取其绝对值相加。也就是说最高位应该为0.
    end
// 	reg				answer_flag ;
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            answer_flag <= 1'b0 ;
        else 
            answer_flag <= flag_gxy ; 
    end
// output signal
// reg  			po_flag		
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_flag <= 1'b0 ;
        else if(answer_flag)
            po_flag <= 1'b1 ;
        else 
            po_flag <= 1'b0 ;
    end
// reg  	[7:0]	po_data 
    always @(posedge clk_50 or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data <= 8'd0 ;
        else if(answer_flag && (gxy >  THR))
            po_data <= BLACK ;
        else if(answer_flag && (gxy <= THR))
            po_data <= WHITE ;
        else 
            po_data <=  po_data ;
    end
/*************************************************************/
    // 例化
    assign  dataf1_in_w = dataf1_in ;
    assign  dataf2_in_w = dataf2_in ;
    assign  rdreq_w     = rdreq     ; 
    assign  wrreq1_w    = wrreq1    ;
    assign  wrreq2_w    = wrreq2    ;
    
fifo fifo_f1(
	.clock                  ( clk_50        ) ,
	.data                   ( dataf1_in_w   ) ,
	.rdreq                  ( rdreq_w       ) ,
	.wrreq                  ( wrreq1_w      ) ,
	.empty                  ( empty_f1      ) ,
	.full                   ( full_f1       ) ,
	.q                      ( dataf1_out    ) ,
	.usedw                  ( usedw_f1      ) 
);

fifo fifo_f2(
	.clock                  ( clk_50        ) ,
	.data                   ( dataf2_in_w   ) ,
	.rdreq                  ( rdreq_w       ) ,
	.wrreq                  ( wrreq2_w      ) ,
	.empty                  ( empty_f2      ) ,
	.full                   ( full_f2       ) ,
	.q                      ( dataf2_out    ) ,
	.usedw                  ( usedw_f2      ) 
);

endmodule

 

module top(
    input		wire			sys_clk 	,
    input 		wire			sys_rst_n 	,
    input 		wire 			rx 			,
    
    output 		wire 			hsync 		,
    output		wire			vsync  		,
    output		wire	[7:0]	rgb			,
    output		wire			tx 
);

    // 例化间连线
    wire			clk_50     ;
    wire			clk_25     ;
    wire			rst_n      ;
    wire  			po_flag_rx ;
    wire	[7:0]	po_data_rx ;
    wire  			po_flag_so ;
    wire	[7:0]	po_data_so ;

pll pll_50_25(
    .sys_rst_n		( sys_rst_n  ) ,
    .areset			( ~sys_rst_n ) ,
    .inclk0			( sys_clk 	 ) ,
    .c0				( clk_50 	 ) ,
    .c1				( clk_25 	 ) ,
    .locked			( rst_n 	 ) 
);

uart_rx uart_rx_inst(
    .sys_clk		( clk_50     ) ,
    .sys_rst_n		( rst_n      ) ,
    .rx				( rx         ) ,

    .po_flag		( po_flag_rx ) ,
    .po_data		( po_data_rx )    
);

sobel sobel_inst(
    .clk_50			( clk_50     ) ,
    .sys_rst_n		( rst_n      ) ,
    .pi_data		( po_data_rx ) ,
    .pi_flag		( po_flag_rx ) ,
        
   .po_flag         ( po_flag_so ) ,
   .po_data         ( po_data_so ) 
);

uart_tx uart_tx_inst(
    .sys_clk        ( clk_50     ) ,
    .sys_rst_n      ( rst_n      ) ,
    .pi_flag        ( po_flag_so ) ,
    .pi_data        ( po_data_so ) ,

    .tx             ( tx         )          
);

vga vga_inst(
    .clk_25         ( clk_25     ) ,
    .clk_50         ( clk_50     ) ,
    .rst_n          ( rst_n      ) ,
    .pi_data        ( po_data_so ) ,
    .pi_flag        ( po_flag_so ) ,

    .hsync          ( hsync      ) ,
    .vsync          ( vsync      ) ,
    .rgb            ( rgb        )    
);

endmodule

 仿真图忘记截屏了。

上板验证:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值