Перейти к содержанию
    

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

`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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Друг, зачем в операторе 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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

 

Изменено пользователем stealthisname

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

res_00.thumb.png.d3de56c1459e2649801cce3715221449.png

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

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

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

res_01.thumb.png.3f6b5116824491c89d811dd7b7c71914.png

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...