Tengo algunos problemas con un búfer que recibe una entrada de 192 bits y se lee 72 bits. Suponer que escribir_es y leer_es son asíncronos, pero el búfer no se llena ni se vacía.
He probado el módulo y parece que está funcionando según lo diseñado, pero hay un punto en el que cuando ambos escribir_es y leer_es son ciertas, deja de funcionar. Creo que está relacionado con el contador, pero no puedo entenderlo. ¿Ves algo que me perdí?
Agrego el módulo Verilog como referencia:
module variable_buffer #(parameter WORD_SIZE_IN = 192, WORD_SIZE_OUT = 72)(
input wire clk250, rst, write_en, read_en,
input wire [0:WORD_SIZE_IN-1] data_in,
output reg [0:WORD_SIZE_OUT-1] data_out_buffer,
output reg [0:8] data_count,
output reg full, empty, error);
//-------- internal variable declaration -------------------------------------------
reg [0:WORD_SIZE_IN*2-1] buffer_reg; // 368 = WORD_SIZE_IN*2-1
reg [0:8] counter, aux_counter;
reg flag_buffer_full, flag_buffer_empty, aux_flag_buffer_full, aux_flag_buffer_empty;
reg count_add, count_sub;
//-------------------------------------------------------------------------------------
//-------- update states -----------------------------------------------------------
always @(posedge clk250) begin: update_registers
if(rst == 1'b0) begin
counter <= 0;
flag_buffer_full <= 1'b0;
flag_buffer_empty <= 1'b1;
end
else begin
counter <= aux_counter;
flag_buffer_full <= aux_flag_buffer_full;
flag_buffer_empty <= aux_flag_buffer_empty;
end
end
//-------------------------------------------------------------------------------------
//-------- control full/empty flags and counter --------------------------------------
always @(write_en, read_en, counter, flag_buffer_empty, flag_buffer_full) begin: flag_control
aux_flag_buffer_full = flag_buffer_full;
aux_flag_buffer_empty = flag_buffer_empty;
count_sub = 1'b0;
count_add = 1'b0;
// write attempt
if(write_en && !read_en && !flag_buffer_full) begin
if(counter + WORD_SIZE_IN <= WORD_SIZE_IN*2) begin
count_add = 1'b1;
aux_flag_buffer_empty = 1'b0;
if(counter + WORD_SIZE_IN == WORD_SIZE_IN*2) aux_flag_buffer_full = 1'b1;
end else aux_flag_buffer_full = 1'b1;
end
// read attempt
if(read_en && !write_en && !flag_buffer_empty) begin
if(counter + WORD_SIZE_OUT > WORD_SIZE_OUT) begin
count_sub = 1'b1;
aux_flag_buffer_full = 1'b0;
end else count_sub = 1'b0;
if(counter - WORD_SIZE_OUT < WORD_SIZE_OUT) begin
aux_flag_buffer_empty = 1'b1;
end
end
// read & write attempt
if(read_en && write_en) begin
if(counter + WORD_SIZE_IN <= WORD_SIZE_IN*2) begin
count_add = 1'b1;
aux_flag_buffer_empty = 1'b0;
if(counter + WORD_SIZE_IN == WORD_SIZE_IN*2) aux_flag_buffer_full = 1'b1;
end else aux_flag_buffer_full = 1'b1;
if(counter + WORD_SIZE_OUT > WORD_SIZE_OUT) begin
count_sub = 1'b1;
aux_flag_buffer_full = 1'b0;
end else count_sub = 1'b0;
if(counter - WORD_SIZE_OUT < WORD_SIZE_OUT) begin
aux_flag_buffer_empty = 1'b1;
end
end
end
//-------------------------------------------------------------------------------------
//-------- data operations --------------------------------------------------------
always @(posedge clk250) begin: data_update
if(rst == 1'b0) begin
buffer_reg <= 0;
data_out_buffer <= 0;
error <= 1'b0;
end
if(write_en && !flag_buffer_full) begin // writing to buffer and is not full
buffer_reg[counter +: WORD_SIZE_IN] <= data_in;
error <= 1'b0;
end
else if (write_en && flag_buffer_full) error <= 1'b1; // error when trying to write in full buffer
if(read_en && !flag_buffer_empty) begin // reading from non-empty buffer
data_out_buffer <= buffer_reg[0:WORD_SIZE_OUT-1];
buffer_reg <= buffer_reg << WORD_SIZE_OUT;
error <= 1'b0;
end
else if(read_en && flag_buffer_empty) error <= 1'b1; // error when reading from empty buffer
if(read_en && write_en && !flag_buffer_empty && !flag_buffer_full) begin
data_out_buffer <= buffer_reg[0:WORD_SIZE_OUT-1];
buffer_reg <= buffer_reg << WORD_SIZE_OUT;
buffer_reg[counter +: WORD_SIZE_IN] <= data_in;
error <= 1'b0;
end
end
//-------------------------------------------------------------------------------------
//-------- combinational counter --------------------------------------------------
always @(count_sub, count_add, counter) begin: counter_operations
begin: combi_counter
case({count_sub, count_add})
2'b01 : aux_counter = counter + WORD_SIZE_IN;
2'b10 : aux_counter = counter - WORD_SIZE_OUT;
default : aux_counter = counter;
endcase
end
end
//-------------------------------------------------------------------------------------
//-------- connection internal registries to ports -----------------------------------
always @(counter, flag_buffer_full, flag_buffer_empty) begin: inner_2_port_connections
data_count = counter;
full = flag_buffer_full;
empty = flag_buffer_empty;
end
//-------------------------------------------------------------------------------------
endmodule