An example introductory project: Implement a design of a shift register with enable signal. The design should input a single bit from a key and put in into the shift register. The current state and the output of the shift register should be displayed on LEDs in binary representation. In addition, the current state of the shift register should be displayed on static multi-digit seven-segment display in hexadecimal form. The design should be implemented using Terasic DE2-115 board with Altera Cyclone IV E FPGA. As a base for the project a student can use the top module template from Terasic; the example of a seven-segment display driver for Digilent Basys 3 board with Xilinx Artix-7 FPGA; and the example illustrating a shift register (without enable signal), that outputs the current state of the shift register on LEDs in binary representation, also implemented for Basys 3 board.
//-------------------------------------------------------------------- Top module from Terasic Altera DE2-115 template: module de2_115_user ( input CLOCK_50, input [ 3:0] KEY, input [17:0] SW, output [ 8:0] LEDG, output [17:0] LEDR, output [ 6:0] HEX0, output [ 6:0] HEX1, output [ 6:0] HEX2, output [ 6:0] HEX3, output [ 6:0] HEX4, output [ 6:0] HEX5, output [ 6:0] HEX6, output [ 6:0] HEX7 ); assign LEDG [3:0] = KEY; assign LEDG [4] = KEY [0] & KEY [1]; assign LEDG [5] = KEY [0] | KEY [1]; assign LEDG [6] = KEY [0] ^ KEY [1]; assign LEDG [7] = ~ KEY [0]; assign LEDG [8] = ~ KEY [1]; assign LEDR = SW; assign HEX0 = 7'h0; assign HEX1 = 7'h7f; assign HEX2 = 7'h0; assign HEX3 = 7'h7f; assign HEX4 = 7'h0; assign HEX5 = 7'h7f; assign HEX6 = 7'h0; assign HEX7 = 7'h7f; endmodule //-------------------------------------------------------------------- // Combinational driver for single-digit display module single_digit_display ( input [3:0] digit, input single_digit, input show_dot, output reg [6:0] seven_segments, output dot, output [3:0] anodes ); always @* case (digit) 'h0: seven_segments = 'b1000000; // a b c d e f g 'h1: seven_segments = 'b1111001; 'h2: seven_segments = 'b0100100; // --a-- 'h3: seven_segments = 'b0110000; // | | 'h4: seven_segments = 'b0011001; // f b 'h5: seven_segments = 'b0010010; // | | 'h6: seven_segments = 'b0000010; // --g-- 'h7: seven_segments = 'b1111000; // | | 'h8: seven_segments = 'b0000000; // e c 'h9: seven_segments = 'b0011000; // | | 'ha: seven_segments = 'b0001000; // --d-- 'hb: seven_segments = 'b0000011; 'hc: seven_segments = 'b1000110; 'hd: seven_segments = 'b0100001; 'he: seven_segments = 'b0000110; 'hf: seven_segments = 'b0001110; endcase assign dot = ~ show_dot; assign anodes = single_digit ? 4'b1110 : 4'b0000; endmodule //-------------------------------------------------------------------- // Basys3 project that instantiates // combinational driver for single-digit display module basys3 ( input clk, input btnC, input btnU, input btnL, input btnR, input btnD, input [15:0] sw, output [15:0] led, output [ 6:0] seg, output dp, output [ 3:0] an ); single_digit_display single_digit_display ( .digit ( sw [3:0] ), .single_digit ( sw [15] ), .show_dot ( sw [14] ), .seven_segments ( seg ), .dot ( dp ), .anodes ( an ) ); endmodule //-------------------------------------------------------------------- // Clock divider for 100 MHz input clock: module clock_divider_100_MHz_to_1_49_Hz ( input clock_100_MHz, input resetn, output clock_1_49_Hz ); // 100 MHz / 2 ** 26 = 1.49 Hz reg [25:0] counter; always @ (posedge clock_100_MHz) begin if (! resetn) counter <= 0; else counter <= counter + 1; end assign clock_1_49_Hz = counter [25]; endmodule //-------------------------------------------------------------------- // Shift register (without enable) module shift_register ( input clock, input resetn, input in, output out, output reg [15:0] data ); always @ (posedge clock or negedge resetn) begin if (! resetn) data <= 16'hABCD; else data <= { in, data [15:1] }; // data <= (data >> 1) | (in << 15); end assign out = data [0]; endmodule //-------------------------------------------------------------------- // Basys3 project that instantiates shift register module basys3 ( input clk, input btnC, input btnU, input btnL, input btnR, input btnD, input [15:0] sw, output [15:0] led, output [ 6:0] seg, output dp, output [ 3:0] an ); wire clock; wire resetn = ! btnU; clock_divider_100_MHz_to_1_49_Hz clock_divider ( .clock_100_MHz (clk), .resetn (resetn), .clock_1_49_Hz (clock) ); wire out; shift_register shift_register ( .clock ( clock ), .resetn ( resetn ), .in ( btnC ), .out ( out ), .data ( led ) ); assign seg = out ? 7'b1111001 : 7'b1000000; assign dp = 1'b1; assign an = 4'b1110; endmodule //-------------------------------------------------------------------- //-------------------------------------------------------------------- //-------------------------------------------------------------------- The solution: //-------------------------------------------------------------------- //-------------------------------------------------------------------- //-------------------------------------------------------------------- Top module: module de2_115_user ( input CLOCK_50, input [ 3:0] KEY, input [17:0] SW, output [ 8:0] LEDG, output [17:0] LEDR, output [ 6:0] HEX0, output [ 6:0] HEX1, output [ 6:0] HEX2, output [ 6:0] HEX3, output [ 6:0] HEX4, output [ 6:0] HEX5, output [ 6:0] HEX6, output [ 6:0] HEX7 ); wire clock; wire resetn = KEY [3]; clock_divider_50_MHz_to_1_49_Hz clock_divider_50_MHz_to_1_49_Hz ( .clock_50_MHz (CLOCK_50), .resetn (resetn), .clock_1_49_Hz (clock) ); shift_register_with_enable shift_register_with_enable ( .clock ( clock ), .resetn ( resetn ), .in ( ~ KEY [2] ), .enable ( KEY [1] ), .out ( LEDG [7] ), .data ( LEDR ) ); single_digit_display digit_0 ( .digit ( LEDR [ 3: 0] ), .seven_segments ( HEX0 ) ); single_digit_display digit_1 ( .digit ( LEDR [ 7: 4] ), .seven_segments ( HEX1 ) ); single_digit_display digit_2 ( .digit ( LEDR [11: 8] ), .seven_segments ( HEX2 ) ); single_digit_display digit_3 ( .digit ( LEDR [15:12] ), .seven_segments ( HEX3 ) ); single_digit_display digit_4 ( .digit ( { 2'b0 , LEDR [17:16] } ), .seven_segments ( HEX4 ) ); assign LEDG [7:1] = 7'b111_1111; assign HEX5 = 7'h7f; assign HEX6 = 7'h7f; assign HEX7 = 7'h7f; endmoduleTop module instantiation in the wrapper provided by Terasic. Note unused ports: Top module de2_115_user RTL schematics: Clock divider has to be modified to accomodate 50 MHz input frequency instead of 100 MHz: module clock_divider_50_MHz_to_1_49_Hz ( input clock_50_MHz, input resetn, output clock_1_49_Hz ); // 50 MHz / 2 ** 25 = 1.49 Hz reg [24:0] counter; always @ (posedge clock_50_MHz) begin if (! resetn) counter <= 0; else counter <= counter + 1; end assign clock_1_49_Hz = counter [24]; endmoduleModule clock_divider_50_MHz_to_1_49_Hz RTL schematics: Added enable signal to shift register, made it wider (18 bits) and changed its reset value for simplicity: module shift_register_with_enable ( input clock, input resetn, input in, input enable, output out, output reg [17:0] data ); always @ (posedge clock or negedge resetn) begin if (! resetn) data <= 18'b10_0000_0000_0000_0000; else if (enable) data <= { in, data [17:1] }; end assign out = data [0]; endmoduleModule shift_register_with_enable RTL schematics: Module shift_register_with_enable post synthesis schematics: Module shift_register_with_enable post synthesis schematics - fragment: Terasic DE2-115 board uses static display, so we don't need a dynamic display. We just instantiate several single digit displays. Moreover, this static display does not have a dot, so we can remove unused signals. module single_digit_display ( input [3:0] digit, output reg [6:0] seven_segments ); always @* case (digit) 'h0: seven_segments = 'b1000000; // a b c d e f g 'h1: seven_segments = 'b1111001; 'h2: seven_segments = 'b0100100; // --a-- 'h3: seven_segments = 'b0110000; // | | 'h4: seven_segments = 'b0011001; // f b 'h5: seven_segments = 'b0010010; // | | 'h6: seven_segments = 'b0000010; // --g-- 'h7: seven_segments = 'b1111000; // | | 'h8: seven_segments = 'b0000000; // e c 'h9: seven_segments = 'b0011000; // | | 'ha: seven_segments = 'b0001000; // --d-- 'hb: seven_segments = 'b0000011; 'hc: seven_segments = 'b1000110; 'hd: seven_segments = 'b0100001; 'he: seven_segments = 'b0000110; 'hf: seven_segments = 'b0001110; endcase endmoduleModule single_digit_display RTL schematics: Altera Quartus II screenshot with area report Altera Quartus II timing report - Fmax Altera Quartus II timing report - slack Board on reset Board after reset Entering input A new sequence started after entering input: