90 lines
2.7 KiB
Verilog
90 lines
2.7 KiB
Verilog
`default_nettype none
|
|
`timescale 1ns/1ps
|
|
|
|
module bit_fifo(
|
|
input wire clk,
|
|
|
|
input wire en,
|
|
input wire [IWIDTH-1:0] in,
|
|
input wire in_valid,
|
|
output reg [OWIDTH-1:0] out,
|
|
output reg out_valid);
|
|
|
|
parameter IWIDTH = 0;
|
|
parameter OWIDTH = 0;
|
|
|
|
localparam BWIDTH = OWIDTH-1 + IWIDTH;
|
|
|
|
reg [OWIDTH-1:0] buffer;
|
|
reg [$clog2(OWIDTH)-1:0] buffer_size;
|
|
|
|
initial begin
|
|
buffer = 0;
|
|
buffer_size = 0;
|
|
out = 0;
|
|
out_valid = 0;
|
|
end
|
|
|
|
reg [OWIDTH-1:0] mask;
|
|
reg [OWIDTH-1:0] top_half;
|
|
reg [OWIDTH-1:0] bottom_half;
|
|
reg [OWIDTH-1:0] joined_halves;
|
|
|
|
always @(*) begin
|
|
mask = (1 << buffer_size) - 1;
|
|
top_half = (buffer & mask) << (OWIDTH - buffer_size);
|
|
bottom_half = in >> (IWIDTH- (OWIDTH - buffer_size));
|
|
joined_halves = top_half | bottom_half;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
out_valid <= 0;
|
|
|
|
// RUN state
|
|
if(en && in_valid) begin
|
|
// this module should spit out values as soon as it's able,
|
|
// so if we'll have enough once the present value's clocked in,
|
|
// then we'll need to immediately assign the output as a combination
|
|
// of what's in the buffer and what's on the line.
|
|
|
|
if(buffer_size + IWIDTH >= OWIDTH) begin
|
|
// compute buffer size
|
|
// -> everything that was in the buffer is now in the output,
|
|
// so what we put back in the buffer is purely what's left over
|
|
// from our input data once we've sliced out what we need
|
|
buffer_size <= buffer_size + IWIDTH - OWIDTH;
|
|
|
|
// compute buffer contents
|
|
buffer <= ( (1 << (buffer_size + IWIDTH - OWIDTH)) - 1 ) & in;
|
|
|
|
/*
|
|
$display("buffer_size: %h in: %b ", buffer_size, in);
|
|
$display(" buffer: %b", buffer);
|
|
$display(" mask: %b", mask);
|
|
$display(" top_half: %b", top_half);
|
|
$display(" bottom_half: %b", bottom_half);
|
|
$display(" out: %b \n", joined_halves);
|
|
*/
|
|
|
|
// compute output
|
|
out <= joined_halves;
|
|
out_valid <= 1;
|
|
end
|
|
|
|
else begin
|
|
// shift into the right side of the buffer
|
|
buffer <= {buffer[BWIDTH-1-IWIDTH:0], in};
|
|
buffer_size <= buffer_size + IWIDTH;
|
|
end
|
|
end
|
|
|
|
// FLUSH state
|
|
else if(buffer_size > 0) begin
|
|
out <= (buffer) & ((1 << buffer_size) - 1);
|
|
out_valid <= 1;
|
|
buffer_size <= 0;
|
|
end
|
|
end
|
|
endmodule
|
|
|
|
`default_nettype wire |