Jump to content

    
Sign in to follow this  
p0lar1zee

Обработка оператором собеля матрицы 8 на 8

Recommended Posts

`timescale 1ns / 1ns

module Top(
	clk,
	data_in,
	data_out,
	element,
	outmatrix
);
input clk, data_in, data_out;
input [7:0] element;
output reg [7:0] outmatrix;

reg [7:0] mem [63:0];
reg [7:0] result [63:0];
wire [7:0] wres [63:0];
wire [7:0] Wadr, Radr;

counter countin(
	.clk(clk),
	.reset(!data_in),
	.counter(Wadr)
);

counter countout(
	.clk(clk),
	.reset(!data_out),
	.counter(Radr)
);

genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : first_6_sobels
	sobel Sobel(
		.clk(clk),
		.p0(mem[i]), 
		.p1(mem[i+1]), 
		.p2(mem[i+2]), 
		.p3(mem[i+8]), 
		.p4(mem[i+9]),
		.p5(mem[i+10]), 
		.p6(mem[i+16]), 
		.p7(mem[i+17]), 
		.p8(mem[i+18]), 
		.out(wres[i+9])
	);
end endgenerate

generate for(i = 8; i < 14; i = i + 1) begin : second_6_sobels
	sobel Sobel(
		.clk(clk),
		.p0(mem[i]), 
		.p1(mem[i+1]), 
		.p2(mem[i+2]), 
		.p3(mem[i+8]), 
		.p4(mem[i+9]),
		.p5(mem[i+10]), 
		.p6(mem[i+16]), 
		.p7(mem[i+17]), 
		.p8(mem[i+18]), 
		.out(wres[i+9])
	);
end endgenerate

generate for(i = 16; i < 22; i = i + 1) begin : third_6_sobels
	sobel Sobel(
		.clk(clk),
		.p0(mem[i]), 
		.p1(mem[i+1]), 
		.p2(mem[i+2]), 
		.p3(mem[i+8]), 
		.p4(mem[i+9]),
		.p5(mem[i+10]), 
		.p6(mem[i+16]), 
		.p7(mem[i+17]), 
		.p8(mem[i+18]), 
		.out(wres[i+9])
	);
end endgenerate

generate for(i = 24; i < 30; i = i + 1) begin : fourth_6_sobels
	sobel Sobel(
		.clk(clk),
		.p0(mem[i]), 
		.p1(mem[i+1]), 
		.p2(mem[i+2]), 
		.p3(mem[i+8]), 
		.p4(mem[i+9]),
		.p5(mem[i+10]), 
		.p6(mem[i+16]), 
		.p7(mem[i+17]), 
		.p8(mem[i+18]), 
		.out(wres[i+9])
	);
end endgenerate

generate for(i = 32; i < 38; i = i + 1) begin : fifth_6_sobels
	sobel Sobel(
		.clk(clk),
		.p0(mem[i]), 
		.p1(mem[i+1]), 
		.p2(mem[i+2]), 
		.p3(mem[i+8]), 
		.p4(mem[i+9]),
		.p5(mem[i+10]), 
		.p6(mem[i+16]), 
		.p7(mem[i+17]), 
		.p8(mem[i+18]), 
		.out(wres[i+9])
	);
end endgenerate

generate for(i = 40; i < 46; i = i + 1) begin : last_6_sobels
	sobel Sobel(
		.clk(clk),
		.p0(mem[i]), 
		.p1(mem[i+1]), 
		.p2(mem[i+2]), 
		.p3(mem[i+8]), 
		.p4(mem[i+9]),
		.p5(mem[i+10]), 
		.p6(mem[i+16]), 
		.p7(mem[i+17]), 
		.p8(mem[i+18]), 
		.out(wres[i+9])
	);
end endgenerate

always @(posedge clk)begin
	if(data_in)
		mem[Wadr] <= element;
	else if(data_out)
		outmatrix <= result[Radr];
end

always @(posedge clk)
begin	
	result[0] = wres[0]; result[16] = wres[16]; result[32] = wres[32]; result[48] = wres[48];
	result[1] = wres[1]; result[17] = wres[17]; result[33] = wres[33]; result[49] = wres[49];
	result[2] = wres[2]; result[18] = wres[18]; result[34] = wres[34]; result[50] = wres[50];
	result[3] = wres[3]; result[19] = wres[19]; result[35] = wres[35]; result[51] = wres[51];
	result[4] = wres[4]; result[31] = wres[31]; result[36] = wres[36]; result[52] = wres[52];
	result[5] = wres[5]; result[20] = wres[20]; result[37] = wres[37]; result[53] = wres[53];
	result[6] = wres[6]; result[21] = wres[21]; result[38] = wres[38]; result[54] = wres[54];
	result[7] = wres[7]; result[22] = wres[22]; result[39] = wres[39]; result[55] = wres[55];
	result[8] = wres[8]; result[23] = wres[23]; result[40] = wres[40]; result[56] = wres[56];
	result[9] = wres[9]; result[24] = wres[24]; result[41] = wres[41]; result[57] = wres[57];
	result[10] = wres[10]; result[25] = wres[25]; result[42] = wres[42]; result[58] = wres[58];
	result[11] = wres[11]; result[26] = wres[26]; result[43] = wres[43]; result[59] = wres[59];
	result[12] = wres[12]; result[27] = wres[27]; result[44] = wres[44]; result[60] = wres[60];
	result[13] = wres[13]; result[28] = wres[28]; result[45] = wres[45]; result[61] = wres[61];
	result[14] = wres[14]; result[29] = wres[29]; result[46] = wres[46]; result[62] = wres[62];
	result[15] = wres[15]; result[30] = wres[30]; result[47] = wres[47]; result[63] = wres[63];
end
endmodule

Мне нужно как-то обработать матрицу 8 на 8 оператором собеля, элементы на границе остаются равными 0, в середине обрабатываются собелем. Не могу написать тест бенч, в верилоге новичок. Как провести симуляцию и написать тест бенч? После всяких питонов и с++ эта штука выглядит очень тяжёлой и непонятной, простите за глупости, если таковы написал.
Вот описание оператора собеля. И вообще, всё ли правильно я сделал? Код выглядит не особо красиво, примеры выглядели лучше.
 

module sobel( 
	clk,
	p0, 
	p1, 
	p2, 
	p3, 
	p4,
	p5, 
	p6, 
	p7, 
	p8, 
	out);

input clk;
input  [7:0] p0,p1,p2,p3,p4,p5,p6,p7,p8;	// 8 бит входные пиксели
output [7:0] out;					// 8 бит выходной пиксели

reg [10:0] gx,gy;    //11 бит потому что максимальное значение gx и gy 255*4. 
//Последний бит под знак				 
reg [10:0] abs_gx,abs_gy;	//Абсолютное значение gx и gy
reg [10:0] sum;			//Маскимальное значение 255*8. Здесь знак не нужен
always @(posedge clk) 
begin
	 gx <=((p2-p0)+((p5-p3)<<1)+(p8-p6));//Градиент по горизонтали
	 gy <=((p0-p6)+((p1-p7)<<1)+(p2-p8));//Градиент по вертикали
	 //Вообще на хабре было, что лучше по другому, типа так:
	 //gx <= (p4-p3);
	 //gy <= (p4-p1);
	 //но я на p4 даже не смотрю, он не нужен т.к. там всегда 0 по честному собелю
	 abs_gx <= (gx[10]? ~gx+1 : gx);	// абсолютное значение gx
	 abs_gy <= (gy[10]? ~gy+1 : gy);	// абсолютное значение gy
	 sum <= (abs_gx+abs_gy);				// нахождение суммы
end
	assign out = (|sum[10:8])?8'hff : sum[7:0];	// чтоб не вылезло за 0-255.
endmodule

Вот мой счётчик.

module counter(
	clk,
	reset,
	counter
);
input clk, reset;
output reg [7:0] counter;

always @(negedge clk) begin
	if(reset)
		counter <= 8'd0;
	else
		counter <= counter + 8'd1;
end
endmodule

 

Share this post


Link to post
Share on other sites

Друг, зачем в операторе always @ Собеля юзаешь , просто сделай

module sobel( p0, p1, p2, p3, p5, p6, p7, p8, out);

input  [7:0] p0,p1,p2,p3,p5,p6,p7,p8;    // 8 bit pixels inputs 
output [7:0] out;                    // 8 bit output pixel 

wire signed [10:0] gx,gy;    //11 bits because max value of gx and gy is
//2554 and last bit for sign
wire signed [10:0] abs_gx,abs_gy;    //it is used to find the absolute value of gx and gy 
wire [10:0] sum;            //the max value is 2558. here no sign bit needed. 

assign gx=((p2-p0)+((p5-p3)<<1)+(p8-p6));//sobel mask for gradient in horiz. direction 
assign gy=((p0-p6)+((p1-p7)<<1)+(p2-p8));//sobel mask for gradient in vertical direction 

assign abs_gx = (gx[10]? ~gx+1 : gx);    // to find the absolute value of gx. 
assign abs_gy = (gy[10]? ~gy+1 : gy);    // to find the absolute value of gy. 

assign sum = (abs_gx+abs_gy);                // finding the sum 
assign out = (|sum[10:8])?8'hff : sum[7:0];    // to limit the max value to 255

endmodule

 

Share this post


Link to post
Share on other sites
On 11/13/2020 at 2:26 AM, p0lar1zee said:

Мне нужно как-то обработать матрицу 8 на 8 оператором собеля, элементы на границе остаются равными 0, в середине обрабатываются собелем. Не могу написать тест бенч, в верилоге новичок. Как провести симуляцию и написать тест бенч? После всяких питонов и с++ эта штука выглядит очень тяжёлой и непонятной, простите за глупости, если таковы написал.

необходимо написать тестбенч для разрабатываемого модуля.

в тетбенче будет установлен проверяемый модуль и сформированы все входные сигналы для проверки работы разрабатываемого модуля
(у меня тут проверяемый модуль называется sobel_8x8_top)

`timescale 1 ns / 1 ps

module sobel_8x8_top_tb();

reg clk = 0;

always #(10.0/2)
begin
    clk = ~clk;
end

reg         data_in   ;
reg         data_out  ;
reg  [7:0]  element   ;
wire [7:0]  outmatrix ;

sobel_8x8_top sobel_8x8_top_i
(
    .clk      (clk),
    .data_in  (data_in   ),
    .data_out (data_out  ),
    .element  (element   ),
    .outmatrix(outmatrix )
);

initial
begin

    ...
    // формирование входных сигналов

    ...
end

endmodule

в разрабатываемом модуле сигналы загрузки данных используются для сброса счетчиков, поэтому перед загрузкой они выдерживаются с большим запасом

    // инициализация, сброс счетчиков модуля
    data_in  = 0;
    data_out = 0;
    element  = 0;
    repeat(5) @(posedge clk);

в самом простом случае для проверки загрузки-выгрузки данных, загружаем рандомные числа

    // загрузка данных
    data_in  = 1;
    data_out = 0;
    repeat(64)
    begin
        element  = $random;
        @(posedge clk);
    end

в разрабатываемом модуле расчеты зарегистрены в несколько стадий, поэтому ждем с запасом завершения всех расчетов

    // ожидание рассчета
    data_in  = 0;
    data_out = 0;
    element  = 0;
    repeat(10) @(posedge clk);

после завершения расчетов выгружаем данные

    // выгрузка рассчитанных данных
    data_in  = 0;
    data_out = 1;
    element  = 0;
    repeat(64)
    begin
        @(posedge clk);
    end

так как тест очень простой и данные загружались рандомные, тут скорее проверяется сам механизм загрузки-выгрузки и выполнения внутренних операций по тактам

 

весь такой простой тестбенч получился примерно таким

Spoiler

`timescale 1 ns / 1 ps

module sobel_8x8_top_tb();

reg clk = 0;

always #(10.0/2)
begin
    clk = ~clk;
end

reg         data_in   ;
reg         data_out  ;
reg  [7:0]  element   ;
wire [7:0]  outmatrix ;

sobel_8x8_top sobel_8x8_top_i
(
    .clk      (clk),
    .data_in  (data_in   ),
    .data_out (data_out  ),
    .element  (element   ),
    .outmatrix(outmatrix )
);

initial
begin
    // инициализация, сброс счетчиков модуля
    data_in  = 0;
    data_out = 0;
    element  = 0;
    repeat(5) @(posedge clk);
    
    // загрузка данных
    data_in  = 1;
    data_out = 0;
    repeat(64)
    begin
        element  = $random;
        element  = element<<1;
        element  = element>>2;
        @(posedge clk);
    end
    
    // ожидание рассчета
    data_in  = 0;
    data_out = 0;
    element  = 0;
    repeat(10) @(posedge clk);
    
    // выгрузка рассчитанных данных
    data_in  = 0;
    data_out = 1;
    element  = 0;
    repeat(64)
    begin
        @(posedge clk);
    end
    
    // завершение выгрузки, остановка симуляции
    data_in  = 0;
    data_out = 0;
    element  = 0;
    repeat(10) @(posedge clk);
    $stop;
    
end

endmodule

 

 

Edited by stealthisname

Share this post


Link to post
Share on other sites

вот такие результаты моделирования получились

res_00.thumb.png.d3de56c1459e2649801cce3715221449.png

элементы на границе матрицы не должны рассчитываться по алгоритму и они действительно выдаются не определенными в выходных данных с проверяемого модуля

но среди тех значений, которые должны рассчитываться по алгоритму, самый первый рассчитывается точно с ошибкой

по сигналам внутри проверяемого модуля видно, что так происходит потому что не загружается нулевой элемент в память входных данных, поэтому не происходит расчета по этому элементу

res_01.thumb.png.3f6b5116824491c89d811dd7b7c71914.png

если исправить загрузку входных данных в память, то дальше останется только проверят непосредственно математику расчетов

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this