Implementation for a dynamic and compact state machine on Spantan-6 in one logic block (CLB)

This is the implementation of the 4-state FSM fitting in one configurable logic block (CLB) only, as described in the previous post. The verilog code uses "Device Primitive Instanciation" as documented in [UG615]. Each instance was constrained in the same CLB (2 slices) using BEL and LOC constraints.

Screenshot of the device tab in PlanAhead:

A standard FSM design could probably be smaller and faster, by taking advantage of transition-and-state-dependent optimizations. On the other hand, this design has the advantage of being generic (i.e., independent of the implemented state machine), hence enabling dynamic partial reconfiguration without changing the assignment of each element. Only the LUT equations would be updated.

According ot the Xilinx synthesis tool, this design can run at up to 200MHz.

Implementation

module fsm_4bit(
         input  [3:0] in,
         output [3:0] out,
         input clk,
         input ce,
         input reset,
         output ready
         );

wire gnd = 1'b0;
// inverted clock
assign clk_n = ~clk;
// current state feedback
wire [1:0] csf;
// input logic to state
wire [3:0] ils;
// state to output logic
wire [3:0] sol;
// output logic to output register
wire [3:0] olr;

// input logic (next state)
// ########################

LUT6 #(
        .INIT(64'h0000000080008000)  // Specify LUT Contents
) LUT6_inst_i0 (
        .O(ils[0]),   // LUT general output
        .I0(in[0]), // LUT input
        .I1(in[1]), // LUT input
        .I2(in[2]), // LUT input
        .I3(in[3]), // LUT input
        .I4(csf[0]), // LUT input
        .I5(csf[1])  // LUT input
);

LUT6 #(
        .INIT(64'h0000000000000000)  // Specify LUT Contents
) LUT6_inst_i1 (
        .O(ils[1]),   // LUT general output
        .I0(in[0]), // LUT input
        .I1(in[1]), // LUT input
        .I2(in[2]), // LUT input
        .I3(in[3]), // LUT input
        .I4(csf[0]), // LUT input
        .I5(csf[1])  // LUT input
);

LUT6 #(
        .INIT(64'h0000000000000000)  // Specify LUT Contents
) LUT6_inst_i2 (
        .O(ils[2]),   // LUT general output
        .I0(in[0]), // LUT input
        .I1(in[1]), // LUT input
        .I2(in[2]), // LUT input
        .I3(in[3]), // LUT input
        .I4(csf[0]), // LUT input
        .I5(csf[1])  // LUT input
);

LUT6 #(
        .INIT(64'h0000000000000000)  // Specify LUT Contents
) LUT6_inst_i3 (
        .O(ils[3]),   // LUT general output
        .I0(in[0]), // LUT input
        .I1(in[1]), // LUT input
        .I2(in[2]), // LUT input
        .I3(in[3]), // LUT input
        .I4(csf[0]), // LUT input
        .I5(csf[1])  // LUT input
);

// state register
// ##############

FDRE FDRE_inst_s0 (
        .Q(sol[0]),      // 1-bit Data output
        .C(clk),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(ils[0])       // 1-bit Data input
);

FDRE FDRE_inst_s1 (
        .Q(sol[1]),      // 1-bit Data output
        .C(clk),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(ils[1])       // 1-bit Data input
);

FDRE FDRE_inst_s2 (
        .Q(sol[2]),      // 1-bit Data output
        .C(clk),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(ils[2])       // 1-bit Data input
);

FDRE FDRE_inst_s3 (
        .Q(sol[3]),      // 1-bit Data output
        .C(clk),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(ils[3])       // 1-bit Data input
);

// state encoding
// ##############

LUT5 #(
        .INIT(32'h00000002)  // Specify LUT Contents
) LUT5_inst_s0 (
        .O(csf[0]),   // LUT general output
        .I0(sol[0]), // LUT input
        .I1(sol[1]), // LUT input
        .I2(sol[2]), // LUT input
        .I3(sol[3]), // LUT input
        .I4(gnd)  // LUT input
);

LUT5 #(
        .INIT(32'h00000000)  // Specify LUT Contents
) LUT5_inst_s1 (
        .O(csf[1]),   // LUT general output
        .I0(sol[0]), // LUT input
        .I1(sol[1]), // LUT input
        .I2(sol[2]), // LUT input
        .I3(sol[3]), // LUT input
        .I4(gnd)  // LUT input
);

LUT5 #(
        .INIT(32'hfffffffc)  // Specify LUT Contents
) LUT5_inst_ready (
        .O(ready),   // LUT general output
        .I0(sol[0]), // LUT input
        .I1(sol[1]), // LUT input
        .I2(sol[2]), // LUT input
        .I3(sol[3]), // LUT input
        .I4(gnd)  // LUT input
);

// output logic
// ############

LUT5 #(
        .INIT(32'h00000002)  // Specify LUT Contents
) LUT5_inst_o0 (
        .O(olr[0]),   // LUT general output
        .I0(sol[0]), // LUT input
        .I1(sol[1]), // LUT input
        .I2(sol[2]), // LUT input
        .I3(sol[3]), // LUT input
        .I4(gnd)  // LUT input
);

LUT5 #(
        .INIT(32'h00000001)  // Specify LUT Contents
) LUT5_inst_o1 (
        .O(olr[1]),   // LUT general output
        .I0(sol[0]), // LUT input
        .I1(sol[1]), // LUT input
        .I2(sol[2]), // LUT input
        .I3(sol[3]), // LUT input
        .I4(gnd)  // LUT input
);

LUT5 #(
        .INIT(32'h00000002)  // Specify LUT Contents
) LUT5_inst_o2 (
        .O(olr[2]),   // LUT general output
        .I0(sol[0]), // LUT input
        .I1(sol[1]), // LUT input
        .I2(sol[2]), // LUT input
        .I3(sol[3]), // LUT input
        .I4(gnd)  // LUT input
);

LUT5 #(
        .INIT(32'h00000001)  // Specify LUT Contents
) LUT5_inst_o3 (
        .O(olr[3]),   // LUT general output
        .I0(sol[0]), // LUT input
        .I1(sol[1]), // LUT input
        .I2(sol[2]), // LUT input
        .I3(sol[3]), // LUT input
        .I4(gnd)  // LUT input
);

// output register
// ###############

FDRE FDRE_inst_o0 (
        .Q(out[0]),      // 1-bit Data output
        .C(clk_n),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(olr[0])       // 1-bit Data input
);

FDRE FDRE_inst_o1 (
        .Q(out[1]),      // 1-bit Data output
        .C(clk_n),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(olr[1])       // 1-bit Data input
);

FDRE FDRE_inst_o2 (
        .Q(out[2]),      // 1-bit Data output
        .C(clk_n),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(olr[2])       // 1-bit Data input
);

FDRE FDRE_inst_o3 (
        .Q(out[3]),      // 1-bit Data output
        .C(clk_n),      // 1-bit Clock input
        .CE(ce),    // 1-bit Clock enable input
        .R(reset),      // 1-bit Synchronous reset input
        .D(olr[3])       // 1-bit Data input
);

endmodule
[UG615]Spartan-6 Libraries Guide for HDL Designs http://www.xilinx.com/support/documentation/sw_manuals/xilinx12_4/spartan6_hdl.pdf