Behavioral Example II: Single-Cycle FIFO

Notes

This illustrates larger if...else blocks. The unit accepts data into the fifo asynchronously and clocks it out synchronously. The double latching of in_cmd_val is for demetastability. This example has been updated so it performs non-blocking assignments properly and doesn't cause feedback loops in the compiler.


/*
 * fifo.v
 * demonstrates use of behavioral synthesis extension constructs
 * 17aug99ajb
 */
module fifo(in_cmd_val, in_cmd_ack, in_cmd, pop_cmd, out_cmd, q_empty, q_full, q_valid, pci_rst, ck);

input in_cmd_val;
output in_cmd_ack;
input [15:0] in_cmd;
input pop_cmd;
output [15:0] out_cmd;

output q_empty;
output q_full;
output q_valid;

input pci_rst;
input ck;


// ------------------------  latch declarations  ------------------------------

reg [7:0]  	fifo_start_l2, fifo_end_l2, fifo_valid_l2;
reg [15:0] 	fifo0_l2, fifo1_l2, fifo2_l2, fifo3_l2, fifo4_l2, fifo5_l2, fifo6_l2, fifo7_l2;
reg        	in_cmd_val_a_l2, in_cmd_val_b_l2, in_cmd_ack_a_l2;

// ------------------------  signal declarations  -----------------------------

wire	   	q_ok;
wire [15:0] 	zero16 = 16'b0000_0000_0000_0000;

// -----------------------------  mainline  -----------------------------------


// 
// fifo queue up op (only if room)
// 

assign q_ok		= ((fifo_start_l2 & fifo_valid_l2) == 8'b0);
assign q_valid		= ((fifo_end_l2 & fifo_valid_l2) != 8'b0);
assign q_empty		= fifo_valid_l2 == 8'b0;
assign q_full		= fifo_valid_l2 == 8'hff;

assign in_cmd_ack 	= in_cmd_ack_a_l2; 		// output port version/demeta of this sig

always @(posedge ck)
begin

in_cmd_val_a_l2 <= in_cmd_val;			// demetastability
in_cmd_val_b_l2 <= in_cmd_val_a_l2;

if (pci_rst==1'b1)					// reset default
	begin
		fifo_start_l2	<= 8'h01;							
		fifo_valid_l2	<= 8'h00;
		in_cmd_ack_a_l2	<= 1'b0;
		fifo0_l2 	<= zero16;
		fifo1_l2 	<= zero16;
		fifo2_l2 	<= zero16;
		fifo3_l2 	<= zero16;
		fifo4_l2 	<= zero16;
		fifo5_l2 	<= zero16;
		fifo6_l2 	<= zero16;
		fifo7_l2 	<= zero16;
	end
	else
	begin
		if (in_cmd_val_b_l2 & q_ok & ~in_cmd_ack_a_l2) // accept fifo data prior to handshake back
			begin
			in_cmd_ack_a_l2 <= 1'b1;
			fifo_start_l2 	<= { fifo_start_l2[6:0], fifo_start_l2[7] }; // bump forward once

			if(fifo_start_l2[0]) fifo0_l2<=in_cmd;
			if(fifo_start_l2[1]) fifo1_l2<=in_cmd;
			if(fifo_start_l2[2]) fifo2_l2<=in_cmd;
			if(fifo_start_l2[3]) fifo3_l2<=in_cmd;
			if(fifo_start_l2[4]) fifo4_l2<=in_cmd;
			if(fifo_start_l2[5]) fifo5_l2<=in_cmd;
			if(fifo_start_l2[6]) fifo6_l2<=in_cmd;
			if(fifo_start_l2[7]) fifo7_l2<=in_cmd;
			end
	
		fifo_valid_l2 <= (fifo_valid_l2 | (		// update valid bits
					fifo_start_l2 & {8{in_cmd_val_b_l2 & q_ok & ~in_cmd_ack_a_l2}}
					))
					& (~fifo_end_l2 | {8{~pop_cmd}});
	
		if (in_cmd_ack_a_l2 & ~in_cmd_val_b_l2)	in_cmd_ack_a_l2 <= 1'b0;	 // finish up handshake
	end
end

// 
// dequeue op
//  
assign out_cmd =						// output mux
	   (fifo0_l2 & {16{fifo_end_l2[0]}})|
	   (fifo1_l2 & {16{fifo_end_l2[1]}})|
	   (fifo2_l2 & {16{fifo_end_l2[2]}})|
	   (fifo3_l2 & {16{fifo_end_l2[3]}})|
	   (fifo4_l2 & {16{fifo_end_l2[4]}})|
	   (fifo5_l2 & {16{fifo_end_l2[5]}})|
	   (fifo6_l2 & {16{fifo_end_l2[6]}})|
	   (fifo7_l2 & {16{fifo_end_l2[7]}});


always @(posedge ck)
	if (pci_rst)						// reset default
		fifo_end_l2	<= 8'h01;
	else if (pop_cmd)					// increment on pop cmd
		fifo_end_l2	<= {fifo_end_l2[6:0],fifo_end_l2[7]};

endmodule


11dec99 bybell@linux-workshop.com / bybell@nc.rr.com
Return to the Ver Homepage...