Sobel算子实现(思路):串口传图并图像处理

1.图像转十六进制。

2.串口发送,通过串口接收模块接收。

3.串口接受模块把数据传递给图像处理模块,图像处理模块对图像数据进行“逐行处理”,例如:

FPGA图像处理基础~sobel算子_NoNoUnknow的博客-CSDN博客

        当然实现这个操作需要依赖两个FIFO来缓存一行数据,也有其他的方法可以实现。

4.处理好的数据传输到RAM里,RAM可以放在图像显示模块里。

        这是因为:串口传图的速度很慢!调到比较快的参数也只有115200比特/秒,只能输入到RAM里,再通过显示协议的时钟需求去读取!

一些工程细节:

        1.RAM取出数据的时间是在输入读取地址的1~3个时钟周期以后(需要关注是否配置了寄存器,不配置默认是1),所以我们需要在需要读取数据的前1一个时钟周期去输入读取地址。

        2.这里的代码仅仅是“单通道的sobel”,还是那个原因!串口发送速率太慢了!多通道会更复杂!

    assign RD_EN = (((H_cnt >  (H_Sync + H_backporch +  H_left -2'd2) + H_cnt_move))
                 && ((H_cnt <= (H_Sync + H_backporch +  H_left -2'd2) + H_cnt_move + window))
                 && ((V_cnt >  (V_Sync + V_backporch +  V_left -1'b1) + V_cnt_move))
                 && ((V_cnt <= (V_Sync + V_backporch +  V_left -1'b1) + V_cnt_move + window)));

        这个操作将读取操作放在了显示操作(PIXAL)前,保证了对齐。

        同时我把之前的视频输出代码进行了修改:(时序电路改成组合电路)

    // always@(posedge Sys_clk or negedge Rst_n) begin
    //     if(Rst_n == 0) begin
    //         set_sign <= 0;
    //     end else if(Pixl_avai) begin
    //         if((H_addr <= H_cnt_move + window -1'b1) 
    //         && (H_addr >= H_cnt_move) 
    //         && (V_addr <= V_cnt_move + window -1'b1) 
    //         && (V_addr >= V_cnt_move))  begin
    //             set_sign <= 1'b1;
    //         end else begin
    //             set_sign <= 0;
    //         end
    //     end else begin
    //         set_sign <= 0;
    //     end
    // end
    assign set_sign = (Pixl_avai)?((((H_addr <= H_cnt_move + window -1'b1) 
                                 && (H_addr >= H_cnt_move) 
                                 && (V_addr <= V_cnt_move + window -1'b1) 
                                 && (V_addr >= V_cnt_move)))
                                 ?(1'b1):(1'b0))
                                 :1'b0;
    assign rgb = (set_sign)?(RD_DATA):(black);
    // always@(posedge Sys_clk or negedge Rst_n) begin
    //     if(Rst_n == 0) begin
    //         rgb <= black;
    //     end else if(set_sign) begin
    //         rgb <= white;
    //     end else begin
    //         rgb <= black;
    //     end
    // end
///

        这是为了让“开窗”这个操作能够对准时序,否则会丢失第一行和最后一行的显示。

穿插一些小知识:

        FPGA内部的RAM资源分为Block RAM 和分布式 RAM,在调用FIFO,RAM等IP核的时候都可以进行选择,其中Block RAM性能更好,也不需要占用逻辑资源(LUT),但是资源有限,而且总是会调用一整块的RAM,比如存储哪怕一个数据的RAM也需要占用一个9K的BRAM,在这个基础上,我们可以“时分复用”地调用相关的IP核,但也会带来开发上的困难(时钟变复杂了)。

部分代码:

        色彩协议:FPGA:参数化的VGA控制器,可用于DVI/HDMI。_NoNoUnknow的博客-CSDN博客

        TX&RX:

        可参考:串口收发与RAM读写_NoNoUnknow的博客-CSDN博客

        下面也是一种实现方法,大同小异,但是参数化了!可以随便改,真好。

module  tx_driver#(
    parameter  Sys_clk_frq = 50_000_000 ,
    parameter  bot         = 115200       ,
    parameter  div_cnt_max = Sys_clk_frq/bot,
    parameter  cnt_width   = $clog2(div_cnt_max)
)(
    input   wire        Sys_clk ,
    input   wire        Rst_n   ,
    input   wire [7:0]  data_in ,
    input   wire        uart_en ,
    output  reg         data_out,
    output  wire        done_flag
);
    localparam start_flag = 1'b0;
    localparam end_flag   = 1'b1;
            reg [cnt_width-1:0] div_cnt  ;
            reg [7:0]           r_data_in;
            reg [3:0]           baud_cnt ;
            reg                 baud_flag;
            reg                 uart_state;
    assign done_flag = (baud_flag && baud_cnt == 4'd8)?1'b1:1'b0;
    
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            r_data_in <= 8'd0;
        end else if(uart_en == 1'b1) begin
            r_data_in <= data_in;
        end else begin
            r_data_in <= r_data_in;
        end
    end
//uart_state
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            uart_state <= 1'b0;
        end else if(uart_en == 1'b1) begin
            uart_state <= 1'b1;
        end else if(done_flag == 1'b1) begin
            uart_state <= 1'b0;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            div_cnt <= 0;
        end else if(uart_state == 1'b1) begin
            if(div_cnt == div_cnt_max -1'b1) begin
                div_cnt <= 0;
            end else begin
                div_cnt <= div_cnt + 1'b1;
            end
        end else begin
            div_cnt <= 0;
        end
    end
//baud_cnt
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            baud_flag <= 1'b0;
        end else if(div_cnt == (div_cnt_max -1'b1)) begin
            baud_flag <= 1'b1;
        end else begin
            baud_flag <= 1'b0;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            baud_cnt <= 4'd0;
        end else if(baud_flag && baud_cnt == 4'd8) begin
            baud_cnt <= 4'd0;
        end else if(baud_flag) begin
            baud_cnt <= baud_cnt + 1'b1;
        end else begin
            baud_cnt <= baud_cnt;
        end
    end
//tx
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            data_out <= 1'b1;
        end else if(uart_en ) begin
            data_out <= 1'b0;
        end else if (baud_cnt <= 4'd7 && baud_flag) begin
            data_out <= r_data_in[baud_cnt];
        end else if(baud_flag && baud_cnt == 4'd8) begin
            data_out <= 1'b1;
        end else begin
            data_out <= data_out;
        end
    end
endmodule
module rx_teach #(
    parameter   Sys_clk_frq = 50_000_000,
    parameter   baud_frq    = 115200      ,
    parameter   div_cnt_max = Sys_clk_frq/baud_frq,
    parameter   cnt_width   = $clog2(div_cnt_max)
)(
    input   wire            Sys_clk,
    input   wire            Rst_n  ,
    input   wire            data_in,
    output  reg   [7:0]     data_receive,
    output  reg             rx_done
);
            reg   [cnt_width-1:0]  div_cnt;
            reg                    reg_data_A;
            reg                    reg_data_B;
            reg                    uart_state;
            reg                    receive_flag ;
            reg   [3:0]            bit_cnt   ;
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            {reg_data_A,reg_data_B} <= 2'b00;
        end else begin
            {reg_data_A,reg_data_B} <= {data_in,reg_data_A};
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            rx_done <= 1'b0;
        end else if(bit_cnt == 4'd8 && receive_flag) begin
            rx_done <= 1'b1;
        end else begin
            rx_done <=  1'b0;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            uart_state <= 1'b0;
        end else if((!reg_data_A)&&(reg_data_B)) begin
            uart_state <= 1'b1;
        end else if(rx_done) begin
            uart_state <= 1'b0;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            div_cnt <= 'd0;
        end else if(uart_state == 1'b1) begin
            if(div_cnt == div_cnt_max -1'b1) begin
                div_cnt <= 'd0;
            end else begin
                div_cnt <= div_cnt + 1'b1;
            end
        end else begin
            div_cnt <= 'd0;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            receive_flag <= 1'b0;
        end else if(div_cnt == (div_cnt_max - 1'b1)>>1) begin
            receive_flag <= 1'b1;
        end else begin
            receive_flag <= 1'b0;
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            bit_cnt <= 'd0;
        end else if(bit_cnt == 4'd8 && receive_flag) begin
            bit_cnt <= 'd0;
        end else if(receive_flag) begin
            bit_cnt <= bit_cnt + 1'b1;
        end else
            bit_cnt <= bit_cnt;
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            data_receive <= 8'd0;
        end else if(bit_cnt >= 1'b1 &&  receive_flag) begin
            data_receive <= {reg_data_B,data_receive[7:1]};
            // case (bit_cnt)
            //     4'd0:data_receive   <= data_receive;
            //     4'd1:data_receive[0] <= reg_data_B;
            //     4'd2:data_receive[1] <= reg_data_B;
            //     4'd3:data_receive[2] <= reg_data_B;
            //     4'd4:data_receive[3] <= reg_data_B;
            //     4'd5:data_receive[4] <= reg_data_B;
            //     4'd6:data_receive[5] <= reg_data_B;
            //     4'd7:data_receive[6] <= reg_data_B;
            //     4'd8:data_receive[7] <= reg_data_B;
            //     default:data_receive <= data_receive;
            // endcase
        end
    end
endmodule

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值