Jump to content

    

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

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

очередь

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites
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. Иногда ради читаемости кода приходится описывать автомат и счетчики в одной куче....

Share this post


Link to post
Share on other sites
input  reg [N - 1 : 0] dataIn,  // Почему  reg ?

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

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

Share this post


Link to post
Share on other sites
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: Почему у многих такое упорное отрицание ручки и бумаги ?

Share this post


Link to post
Share on other sites
18 hours ago, Flip-fl0p said:

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

 

1 hour ago, nopak said:

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this