Jump to content

    
Sign in to follow this  
flammmable

Вложенные циклы на Verilog

Recommended Posts

1 hour ago, RobFPGA said:

Удивительно что только один латч

А сори, опечатка. Там нормально всё было кроме одного состояния кейса. Это я когда писал под вечер уже невнимательный стал)

Share this post


Link to post
Share on other sites

Приветствую!

24 minutes ago, Nick_K said:

А сори, опечатка. Там нормально всё было кроме одного состояния кейса. Это я когда писал под вечер уже невнимательный стал)

Тогда  тем более непонятно  как при чисто синхронном always @(posedge clk)  можно сгенерить латч? 

 

 

Удачи! Rob.

Share this post


Link to post
Share on other sites
8 hours ago, RobFPGA said:

Тогда  тем более непонятно  как при чисто синхронном always @(posedge clk)  можно сгенерить латч? 

Наличие дефолтного состояния подсказало синтезатору. Не забывайте, что синтезатор не Ква/Хилых и целевай борда не плис. В прототипе на Альтере всё было ок, кстати.

Share this post


Link to post
Share on other sites
13 hours ago, des00 said:

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

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

Стиль, lint, разбиение - это всё понятно. Непонятно другое.

Чтобы сдвиговый регистр с обратной связью работал надо:
1) Запомнить его старший бит
2) Сдвинуть сдвиговый регистр на один бит
3.1) Если запомненный бит равен 1, то сделать XOR некоторых бит (например 15-ого и 2-ого для CRC-16 modbus) с единицей.
3.2) Если запомненный бит равен 0, то сделать XOR некоторых бит (например 15-ого и 2-ого для CRC-16 modbus) с нулем.

В вашем варианте:
1) "запоминание" старшего бита - есть
2) сдвиг - есть
3.1) Если старший бит - 1, то производится XOR некоторых бит с единицей (согласно полиному) и XOR всех остальных с нулем.
3.2) Если старший бит - 0, то производится XOR  всех бит с нулем.

Это вообще законно? :)

Share this post


Link to post
Share on other sites
Just now, flammmable said:

Это вообще законно? :)

таблица истиности

0 ^ 0 = 0

1 ^ 0 = 1

0 ^ 1 = 1

1 ^ 1 = 0

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

ЗЫ. Для тренировки, вот вам классическая задача, времен когда МК были маленькие и мелкие: Нужно обменять значения между двумя переменными, без использования третьей ;)

Share this post


Link to post
Share on other sites
7 minutes ago, des00 said:

таблица истиности

0 ^ 0 = 0

1 ^ 0 = 1

0 ^ 1 = 1

1 ^ 1 = 0

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

ЗЫ. Для тренировки, вот вам классическая задача, времен когда МК были маленькие и мелкие: Нужно обменять значения между двумя переменными, без использования третьей ;)

А и правда! Спасибо!

Share this post


Link to post
Share on other sites

Модуль вычисления CRC:

module main 
	#(		
	parameter IS_CRC_REVERSED	= 1,
	parameter IS_DATA_REVERSED	= 1,
	parameter DATA_SIZE		= 8,	
	parameter CRC_SIZE		= 16,
	parameter START_VALUE		= 'hFFFF,
	parameter POLYNOME		= 'h8005)
	(
	input		clk,	
	input		n_reset,	
	input		[DATA_SIZE-1:0]data_in,
	output reg	[CRC_SIZE-1	:0]crc_out);	
	
	reg [CRC_SIZE-1 :0]crc_internal;
	reg [DATA_SIZE-1:0]data_internal;
	reg msb;
	reg [CRC_SIZE-1 :0]crc_shift;
	reg [CRC_SIZE-1 :0]crc_lfsr;	
	
	always @(posedge clk) begin
		if(n_reset) begin
			// data reverse
			if(IS_DATA_REVERSED) begin
				for(int i = 0; i < DATA_SIZE; i++) begin
					data_internal[i] = data_in[DATA_SIZE - 1 - i];
				end
			end
			else begin
				data_internal = data_in; 
			end		
			// CRC calculating
			crc_shift = crc_internal ^ (data_internal << (CRC_SIZE - DATA_SIZE));			
			for(int data_index = 0; data_index < DATA_SIZE; data_index++) begin
				msb = crc_shift[CRC_SIZE-1];
				crc_lfsr = (crc_shift << 1);					
				crc_lfsr = crc_lfsr ^ ({CRC_SIZE{msb}} & POLYNOME);
				crc_lfsr[0] = msb;					
				crc_shift = crc_lfsr;
			end			
			crc_internal = crc_shift;
			// CRC reverse
			if(IS_CRC_REVERSED) begin
				for(int i = 0; i < CRC_SIZE; i++) begin
					crc_out[i] = crc_shift[CRC_SIZE - 1 - i];
				end
			end
			else begin
				crc_out = crc_shift; 
			end
		end
		else begin
			crc_internal =	START_VALUE;
		end
	end
endmodule

Тестбенч к нему:

`timescale 1ns/1ns

module main_tb();

	reg	clk;
	reg	n_reset;
	reg	[7:0]data;	
	wire	[15:0]crc;

	main crc16(
	.clk		(clk),
	.n_reset	(n_reset),
	.data_in	(data),
	.crc_out	(crc));	
	
	initial begin
		#10;
		clk <= 0;
		while(1) begin	
			#5
			clk <= ~clk;
		end	
	end	
	initial begin
		#18;
		n_reset <= 0;
		#14
		n_reset <= 1;	
		#87
		n_reset <= 0;
	end	
	initial begin
		#31;
		data <= 'h12;
		#10
		data <= 'h34;
		#10
		data <= 'h56;
		#10
		data <= 'h78;
		#10
		data <= 'h90;
		#10
		data <= 'hAB;
		#10
		data <= 'hCD;
		#10
		data <= 'hEF;
		#10
		data <= 'hAA;
		#10
		data <= 'h55;
	end
endmodule


Контрольная сумма из этого калькулятора для CRC-16 MODBUS и данных hex-1234567890ABCDEFAA совпадает с контрольной суммой, выдаваемой модулем.

 

 

Edited by flammmable

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