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

очередь на верилоге

Написал очередь на верилоге. Ни как не могу понять почему она так себя ведёт. Почему были пропущены начальные данные. Результаты в присоединённой картинке. Помогите разобраться

очередь

module queue
#(
	parameter N = 8,  // разрядность данных
	count =16
 )
 (
	input rst,
	input clk,
	input nextRead,
	input writeCMD,
	input reg [N-1:0] dataIn,
	
	output reg [N-1:0] dataOut
	);
	
reg [N-1:0] posRead;
reg [N-1:0] posWrite;	
reg [N-1:0] state;
reg [N-1:0] nextState;
localparam RESET =0;
localparam IDLE = 1;
localparam WORK = 2;

reg [N-1:0] data[count-1 : 0] ;

	//always @(posedge clk)
	always @*
	begin
		case (state)
		RESET:
			begin
				nextState = IDLE;
				posWrite = 0;
				posRead  = 0;
				dataOut = 0;
			end
		IDLE:
			begin
				if (writeCMD)
				begin
					posRead = posWrite;
					nextState = WORK;
					data[posWrite] = dataIn;
					posWrite = posWrite + 1;
				end
				else
				begin
				end
			end
		WORK:
			begin
				if (writeCMD)
				begin
					nextState = WORK;
					data[posWrite] = dataIn;
					posWrite = posWrite + 1;
				end
				if (nextRead)
				begin
					dataOut = data[posRead];
					posRead = posRead + 1;
					if (posRead == posWrite)
						nextState = IDLE;
				end
			
			end
		default:
			nextState = IDLE;
		endcase
	end
	always @(posedge rst or posedge clk)
	begin
	if (rst)
		state <= RESET;
	else 
		state <= nextState;
	end
endmodule
	

тест

module test_queue;

localparam N = 8;
localparam count =16;
localparam cmdCount = 24;

reg clk;
reg reset;
wire res;
reg [3:0]rst_delay = 0;
reg [8:0] cnt =0;
reg writeCmd;
reg readCmd;
reg [N-1:0] data [count -1:0];

reg [N-1:0] writeData;
wire [N-1:0] readData;
reg [cmdCount -1 : 0] doWrite; 
reg [cmdCount -1 : 0] doRead;   
initial
begin
  clk = 0;
  reset =0;
  data[0] = 1;
  data[1] = 2;
  data[2] = 3;
  data[3] = 4;
  data[4] = 5;
  data[5] = 6;
  data[6] = 7;
  data[7] = 8;
  data[8] = 101;
  data[9] = 3;
  data[10] = 6;
  data[11] = 55;
  data[12] = 3;
  data[13] = 2;
  data[14] = 0;
  data[15] = 1;
  doWrite = 24'b1101100111010011100; 
  doRead =  24'b0010001101100111011; 
end
always
begin
  #10 clk = ~clk;
end

always @(posedge clk)
begin
	rst_delay <= { rst_delay[2:0], 1'b1 };
	
	doWrite[cmdCount -1 : 1] <= doWrite[cmdCount -2 : 0];

	doRead[cmdCount -1 : 1] <= doRead[cmdCount -2 : 0];
	writeCmd = doWrite[cmdCount -1];
	readCmd  = doRead[cmdCount -1];
	writeData = data[cnt];
	if (writeCmd)
		cnt = cnt + 1;
end
 
always @*
  reset = rst_delay[2]^rst_delay[3];
  
queue q(reset, clk, writeCmd, readCmd, writeData, readData);  
endmodule

 

quem.jpg

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


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

Вот что странно. А почему сейчас в моде писать на HDL без единого комментария ? Я обычно через два - три месяца напрочь забываю почему было написано именно так. Спасает только бумага, на которой есть структурные схемы + коментарии помогают вспомнить... Неужели это только я страдаю пробелами в памяти ?

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


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

Спешил. У моделсима странные отношения к русским буквам. Те в моделсиме нигде потом не видятся. А обычные (анси, утф8) в нём каракули. 

отмазка не ахти какая. 

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


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

module queue #
(
	parameter N     =  8,           // разрядность данных
    count = 16           
)
(
	input                  rst,
	input                  clk,
	input                  nextRead,
	input                  writeCMD,
	input  reg [N - 1 : 0] dataIn,  // Почему  reg ?
	output reg [N - 1 : 0] dataOut
);
	
	localparam RESET = 0;
	localparam IDLE  = 1;
	localparam WORK  = 2;
	reg [N - 1 : 0] state;        // Текущее состояние атомата 
	reg [N - 1 : 0] nextState;    // Следующее, вычисляемое состояние автомата


	reg [N - 1 : 0] posRead;
	reg [N - 1 : 0] posWrite;	
	reg [N - 1 : 0] data[count - 1 : 0] ; 
	
	always @ (posedge rst or posedge clk) begin
		if (rst)
			state <= RESET;
		else 
			state <= nextState;
	end
	
	//always @(posedge clk)
	always @* begin
		case (state) 
			RESET : begin ////////////////////////////////////////////////////////////////////////////////
						nextState = IDLE;
						posWrite  = 0;
						posRead   = 0;
						dataOut   = 0;
			end
			IDLE : begin  ////////////////////////////////////////////////////////////////////////////////
			
						if (writeCMD) begin                // Пришла команда записи 
							nextState      = WORK;       
							posRead        = posWrite;     // А что будет с сигналом posRead когда writeCMD = 0 ? Это LATCH...
							data[posWrite] = dataIn;       // Типа должны записать данные в память. Вот только без клока это LATCH...
							posWrite       = posWrite + 1; // Предполагается счетчик. Вот только это не счетчик...
						end
						else begin
							// Почему пусто ? 
						end
			end
				
			WORK: begin ////////////////////////////////////////////////////////////////////////////////
			            // Собственно тут та-же фигня: без клока одни латчи.
						if (writeCMD) begin
							nextState      = WORK;
							data[posWrite] = dataIn;
							posWrite       = posWrite + 1; 
						end
						if (nextRead) begin
							dataOut = data[posRead];
							posRead = posRead + 1;  
							if (posRead == posWrite) 
								nextState = IDLE;
						end
			end
				
			default : nextState = IDLE;
				
		endcase
	end
endmodule

Вообще в HDL спешить не стоит. Править и отлаживать баги дольше чем изначально сделать все правильно.....

Слегка поковырял Ваш код. Код не для синтеза... Я бы для начала Вам посоветовал все счетчики и память описать отдельно. На начальном этапе освоения HDL лучше все не сваливать в кучу: автомат, память, счетчики, ибо новичку сложно представить в голове во что этот код выльется. Правильный подход: берете карандаш и листок бумаги и на ней рисуете структурную схему. А потом схему переносите на HDL. Вот когда научитесь понимать во что будет синтезироваться Ваш код, тогда пишите все в куче, главное чтобы было читаемо. P.S. Иногда ради читаемости кода приходится описывать автомат и счетчики в одной куче....

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


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

input  reg [N - 1 : 0] dataIn,  // Почему  reg ?

изначально было wire но тогда не передавались данные. dataIn всё время был в z.

// А что будет с сигналом posRead когда writeCMD = 0 ? Это LATCH... Ну он не должен меняться. LATCH это страшно?. сильно плохо?
posWrite       = posWrite + 1; // Предполагается счетчик. Вот только это не счетчик... а что же тогда? и ведёт себя вроде бы логично
// Собственно тут та-же фигня: без клока одни латчи. клок не поменял поведение модуля

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


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

12 минут назад, nopak сказал:

input  reg [N - 1 : 0] dataIn,  // Почему  reg ?

изначально было wire но тогда не передавались данные. dataIn всё время был в z.


// А что будет с сигналом posRead когда writeCMD = 0 ? Это LATCH... Ну он не должен меняться. LATCH это страшно?. сильно плохо?

posWrite       = posWrite + 1; // Предполагается счетчик. Вот только это не счетчик... а что же тогда? и ведёт себя вроде бы логично

// Собственно тут та-же фигня: без клока одни латчи. клок не поменял поведение модуля

LATCH - это по сути комбинационная петля. Когда Вы с выхода комбинационной схемы сигнал подаете на вход этой же комбинационной схемы. В FPGA в 99,9% случаем LATCH - серьезная ошибка, ибо поведение латчей никак не контролируется синтезатором (Tsetup и Thold не определены для них), соответственно поведение Вашей схемы будет сильно зависеть от фазы луны, и положения солнца на горизонте.... 

Значит вооружаемся ручкой и бумагой и вспоминаем навыки рисования на бумаге :biggrin: Почему у многих такое упорное отрицание ручки и бумаги ?

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


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

18 hours ago, Flip-fl0p said:

Почему у многих такое упорное отрицание ручки и бумаги ?

 

1 hour ago, nopak said:

наверное я что то не то нарисовал

Часто проблема кроется не в том что нарисовал/не нарисовал. А в понимании как это синтезировать/интерпретировать. И посему действительно самое первое и главное правило - не лепить всё в кучу. Отдельно для каждого компонента, вплоть до регистров. А то когда оно всё скопом и вправду чепуха

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


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

Старайтесь придерживаться общеупотребительной терминологии.

FIFO, разумеется, очередь, но не сразу понятно, что имеется в виду.

Сигналы интерфейса тоже желательно преименовать. Посмотрите, например, как они именуются в IP FIFO того вендора, с которым вы работаете.

Конечный автомат (state machine) в FIFO не нужен. Одноклоковое FIFO вещь простая, КА там overdesign.

 

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


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

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

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

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

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

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

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

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

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

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