Hardware Design with FPGA's
You can download the following sample projects:
- Schematic capture sample project: File:NOTgate.zip
- Verilog sample project: File:Verilogintro.zip
- A complete pin-mapping file
- NOTE! This mapping file has different names for the pins (such as SW instead of switches, and LEDG instead of LEDs)
- The following code will map a hexadecimal number to a 7-segment display. Note that you need the above pin mappings for it to work.
module hex2sevenseg(output wire [6:0] Segments, input wire [3:0] Hex); assign Segments = !((Hex & !Hex) | (!Hex & Hex) | (Hex & Hex) | (!Hex & Hex & Hex) |(Hex & !Hex & !Hex) | (!Hex & !Hex & !Hex) | (Hex & Hex & !Hex)); assign Segments = !((!Hex & !Hex) | (!Hex & !Hex & !Hex) | (!Hex & Hex & Hex) | (Hex & !Hex & Hex) | (!Hex & !Hex)); assign Segments = !((!Hex & !Hex) | (!Hex & Hex) | (!Hex & Hex) | (!Hex & Hex) |(Hex & !Hex)); assign Segments = !((Hex & !Hex) | (Hex & Hex & !Hex) | (!Hex & !Hex & Hex) | (!Hex & !Hex & !Hex) | (!Hex & Hex & Hex) | (Hex & !Hex & Hex)); assign Segments = !((Hex & !Hex) | (Hex & Hex) | (Hex & !Hex) | (Hex & Hex) | (!Hex & !Hex)); assign Segments = !((!Hex & !Hex) | (Hex & Hex) | (Hex & !Hex) | (Hex & !Hex) | (!Hex & Hex & !Hex)); assign Segments = !((Hex & !Hex) | (!Hex & Hex) | (Hex & !Hex) | (Hex & Hex) | (!Hex & Hex & !Hex)); endmodule //and you instansiate it like this hex2sevenseg(HEX0[6:0], rnd[3:0]); hex2sevenseg(HEX1[6:0], rnd[7:4]); hex2sevenseg(HEX2[6:0], rnd[11:8]); hex2sevenseg(HEX3[6:0], rnd[15:12]);
ISA for the custom processor
Exercises session 3
Note that for all these exercises you can drive your module's clock signal using the clock generated by freqdiv, to make everything run at a more human interactive pace.
// A frequency divider module freqdiv(input clk, output reg divclk); reg [31:0]counterstate = 0; parameter [31:0] divammount = 10000000; always @ (posedge clk) begin counterstate = counterstate + 1; if (counterstate == divammount) begin divclk = ~divclk; counterstate = 0; end end endmodule
- Make a counter that counts to a fixed value, then overflows to 0 and keeps going
- Make a random number generator using a counter with an enable signal.
- Make a variable frequency counter, that is, make it overflow to 0 when it has got to a certain value, instead of a fixed value. Make it increment an output register on every overflow. This should make a variable frequency counter.
- Using (one instance of) the following ALU block, compute A + B - C - D where A,B,C,D are some arbitrary 32 bit numbers.
// a very simple ALU module ALU(input [1:0] fselect, input [31:0] A, input [31:0] B, output reg [31:0] Result); always @ (*) begin //Multiplexer with fselect as selection //Note that N'bxx means a N bit literal with binary value xx case (fselect) 2'b00: Result = A + B; //do nothing 2'b01: Result = A - B; 2'b10: Result = A; 2'b11: Result = 0; endcase end endmodule
- Make a counter that uses a switch as the clock input
- You might notice that when you flick the switch you actually generate more than one clock edge. This is called contact bounce. To avoid this you have to make a debounce circuit. Make sure you know what is going on in this code.
- Let a switch be a manual clock signal, i.e.
always (@posedge SW) begin. On the first flick of the clock switch, the value of the rest of the switches should be loaded into operand A. At the next flick, they should be loaded into operand B. The next flick should load the logic operation to be performed (i.e. load fselect), and display the result on the 7-segments or the LED's.
- The following syntax for defining an array of words
reg [31:0] memory_array [7:0], which makes an array of 8 32 bit words, accessed as entire words using
memory_array[index]. Add one last cycle after fselect where you select a memory location to store the result on the next flick. Check that it did indeed store the result using the signal tap analyzer.
- Make it so that you use a reserved switch to select if on every flick you do: either the value gets loaded (as per last time), or memory_array[value] gets loaded. Compute A + B - C - D using this method of storing intermediate results.
- Have a look at Linear Feedback Shift Registers. Make an enhanced random number generator using a 32 bit LFSR.
Exercises session 2
1. Implement a 2to1 multiplexer (as a module) with the following specifications:
input A, 3 bits wide (tip: use the array notation) input B, 3 bits wide input select, 1 bit wide (tip: simply a wire) output Y, 3 bits wide
Elaboration: if select signal is zero (0), make Y output the A's value. if select signal is one (1),
make Y output the B's value.
(!) Note: example of a binary constant of width one with value zero: 1'b0. First value is the length
of the literal, b means that it is a binary literal and 0 is the value.
To test, either test the module directly in the simulator or (if doing it in hardware) use the
switches and LEDs.
2. Make a adder/subtractor/leftshift by one/right shift by one block that uses a 2 bit input to
select the operation. i.e. if select is : 00 then: result = A + B 01 then: result = A - B 10 then: result = A << 1 11 then: result = A >> 1
3. Make a 3-to-8 one-hot decoder (google what one-hot encoding is) hint: use a variable ammount of left shift, OR: note that the following syntax is valid
result[select] = 1; 4. Make a 8-to-3 priority encoder (google what priority-encoder is) hint: use nested if, else if, else if, .... else statement extra: try doing this with a for loop. Check the syntax on google 5. Make a module that can rotate an input to the left by 1 bit. hint: use a shift and the concatination operator to bring the last bit around 6. Make a module that takes a 3 bit control input that represents a number from 0 to 7, and uses
this to rotate to the left an input value by the specified number of bits. hint: use sucessive if statements to sequentially selectively rotate a temporary variable by
the corresponding power of 2.
Creating a new project
- Put in some Verilog of your choice, such as:
// Top level module: needs to have the same name as the project
// The inputs and outputs need to be things defined in the pin-planner in order to map to the real world
module emptyproject( input [7:0] switches, output [7:0] LEDs, input CLOCK_50);
// Instantiation of the "my_logic" module, called inst1
// The inputs and outputs are mapped to the actual pins here
my_logic inst1(switches, switches, LEDs);
// make any logic you want
module my_logic(input in1, input in2, output out);
assign out = ~in1 & in2;
To run the simulator run the following (or equivalent): C:\altera\12.0sp2\quartus\bin\quartus_sh --qsim