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