清霜一梦

sobel流水线操作Verilog程序

0
阅读(1694)

sobel算子的verilog实现,采用了流水线操作。

module sobel_computer (
                        clock ,
                        reset,
                        OrigDataEn,
                        //SobelAluEn,
                        OrigData,
                        SobelData
                        );
    input clock ,reset;
    input OrigDataEn ; 
    //input SobelAluEn ; 
    input [63:0] OrigData ; 
    output reg [63:0] SobelData ; 

    
reg [63:0] prev_row, curr_row, next_row ; 
reg [1:0] data_state ; 
reg [7:0]abs_D ;
//*****************OrigDataEn 维持三个周期,将数据保存到三个reg 中****************
always @ (posedge clock or negedge reset )
    if(!reset)
        begin 
                data_state <= 2'b00 ; 
                prev_row   <= 64'd0 ; 
                curr_row   <= 64'd0 ; 
                next_row   <= 64'd0 ; 
        end 
    else if(OrigDataEn)
        begin 
                case (data_state)
                    2'b00 :
                        begin 
                                prev_row   <= OrigData ; 
                                data_state <= 2'b01 ;  
                        end 
                    2'b01  :
                        begin 
                                curr_row   <= OrigData ; 
                                data_state <= 2'b10 ;  
                        end 
                    2'b10  : 
                        begin 
                                next_row   <= OrigData ; 
                                //data_state <= 2'b01 ;  
                        end 
                endcase 
        end 
    else 
        begin 
                data_state     <= 2'b00 ; 
                prev_row <= prev_row << 8 ; 
                curr_row <= curr_row << 8 ; 
                next_row <= next_row << 8  ; 
        end 
//----------------------------------------------------------------    
//function : 函数名= 内部reg,并返回。不包含 # @ wait,至少一个输入参数
function [9:0] abs (input signed[10:0] data);
    abs = data[10]? (~data[9:0]+1): data[9:0];
endfunction 

reg signed [10:0] Dx,Dy ;     //8'b1111_1111 * 6 = 11'd1530 所以采用11bit的Dx 和Dy
reg [7:0]Orig [-1:1][-1:1];

/*
分段方式:[63:56]  [55:48]  [47:40]  [39:32]  [31:24]  [23:16]  [15:8]  [7:0] 
sobel   Dx  -1       0         +1 
            -2       0         +2
            -1       0         +1
            
        Dy  +1       +2        +1
            0         0          0 
            -1       -2        -1            
*/
//**************************************************************
always @ (posedge clock or negedge reset)    
    if(!reset)
        begin 
                abs_D <= 8'd0 ; 
                Dx    <= 11'd0 ;
                Dy    <= 11'd0 ; 
                SobelData  <= 64'd0 ; 
        end 
    else  if(!OrigDataEn) //if(SobelAluEn )
        begin 
                Dx <=     $signed (~{3'b000,Orig[-1][-1]}+1)        // * -1
                        + $signed(~({3'b00,Orig[0][-1]}<<1)+1)  // * -2
                        + $signed(~{3'b000,Orig[1][-1]}+1)      // * -1
                        
                        + $signed({3'b000,Orig[-1][1]})            // * 1
                        + $signed({3'b00,Orig[0][1]}<<1)         // * 2
                        + $signed ({3'b000,Orig[1][1]})  ;        // * 1
                        
                Dy <=     $signed ({3'b000,Orig[-1][-1]})            // * 1
                        + $signed ({3'b00,Orig[-1][0]}<<1)        // * 2
                        + $signed({3'b000,Orig[-1][1]})          // * 1
                        
                        + $signed(~{3'b000,Orig[1][-1]}+1)      // * -1
                        + $signed(~({3'b00,Orig[1][0]}<<1)+1) // * -2
                        + $signed(~{3'b000,Orig[1][1]}+1) ;   // * -1
                        
                abs_D <= (abs(Dx) + abs(Dy))>> 2;
                SobelData      <= {SobelData[55:0],abs_D};
                
                Orig[-1][-1] <= Orig[-1][0];   Orig[-1][0] <= Orig[-1][1];  Orig[-1][1] <= prev_row[63:56]; 
                Orig[0][-1]  <= Orig[0][0];    Orig[0][0]  <= Orig[0][1];   Orig[0][1]  <= curr_row[63:56]; 
                Orig[1][-1]  <= Orig[1][0];    Orig[1][0]  <= Orig[1][1];   Orig[1][1]  <= next_row[63:56];                 
        end 
    
endmodule