Experiment 8: Starting line delay circuit - ml7715/VERI-Laboratory GitHub Wiki
This experiment consists in designing Formula 1 style starting lights. The following circuit schematics was provided to design the circuit more easily:
As we can see some of the modules can be reused while others have to be implemented.
The first step consisted in generating the tick 50000 block. The tick_50000 block of experiment 7 was modified in order to create these two blocks. While previously the tick_50000 block was implemented as a reduced clock now we want it to produce a single tick when the every 50000 cycles of the main clock.
tick_50000 verilog:
module tick_50000(CLOCK_IN, CLK_OUT);
parameter NBIT = 16;
input CLOCK_IN;
output CLK_OUT;
reg [NBIT-1:0] count;
reg CLK_OUT;
initial
begin
count = 16'd49999;
CLK_OUT = 1'b0;
end
always @ (posedge CLOCK_IN)
begin
if(count == 16'b0)
begin
CLK_OUT <= 1'b1;
count <= 16'd49999;
end
else
begin
count <= count - 1'b1;
CLK_OUT <= 1'b0;
end
end
endmodule
As we can see a tick is produced when the counter reaches 0, as the tick is produced the count value is reset to its initial value.
One of the specifications of the design is that the LEDs have to turn off after a random time between 0.25 and 16 seconds. The random time is generated by the LFSR. To do so the LFSR of the previous experiment was modified to implement the polynomial 1+X+X^6, which generated 6-bit random values (min=1, max=64). Multiplying the value by 250 in the delay block we obtain the random time value wanted. On top of that an enable input was added to the design.
LFSR verilog:
module LFSR(CLK, en, COUNT);
input CLK;
input en;
output [6:1] COUNT;
reg [6:1] COUNT;
initial COUNT = 6'd1;
always @ (posedge CLK)
if(en == 1'b1)
COUNT <= {COUNT[5:1], COUNT[6] ^ COUNT[1]};
else
COUNT <= COUNT;
endmodule
The next module to implement is the delay block. the delay block was implemented as a finite state machine with 4 states IDLE = 2'b0, COUNTING = 2'b1, TIME_OUT = 2'b10, WAIT_LOW = 2'b11:
- Initially the the delay block is IDLE; when the start_delay signal is received the delay block starts counting (COUNTING);
- as soon as a random time period has elapsed the TIME_OUT state is entered and a time_out signal is sent to the fsm block;
- if the trigger input is goes to 0 then state machine returns to an IDLE state otherwise the state WAIT_LOW is entered to prevent glitches.
delay block verilog:
module delay(clk, N, trigger, time_out);
parameter BIT_SZ = 14;
input clk, trigger;
input [5:0] N;
output time_out;
reg[BIT_SZ-1:0] count;
reg time_out;
reg [1:0] state;
parameter IDLE = 2'b0, COUNTING = 2'b1, TIME_OUT = 2'b10, WAIT_LOW = 2'b11;
initial begin
state = IDLE;
end
always @ (posedge clk)
case(state)
IDLE: if(trigger == 1'b1)
begin
count <= N*250;
state <= COUNTING;
end
COUNTING:
begin
if(count == 1'b0)
begin
state <= TIME_OUT;
end
else
count <= count - 1'b1;
end
TIME_OUT:
begin
if(trigger == 1'b0)
state <= IDLE;
else
state <= WAIT_LOW;
end
WAIT_LOW:
if(trigger == 1'b0)
state <= IDLE;
default: ;
endcase
always @ (*)
case(state)
IDLE: time_out = 1'b0;
COUNTING: time_out = 1'b0;
TIME_OUT: time_out = 1'b1;
WAIT_LOW: time_out = 1'b0;
default: ;
endcase
endmodule
The last block to implement is the finite state machine which drives the digital design.
The finite state machine implemented has three states: WAIT_TRIGGER = 2'd0, LIGHT_UP_LEDS = 2'd1, WAIT_FOR_TIMEOUT = 2'd2.
- The initial state of the finite state machine is WAIT_TRIGGER; in this state the fsm waits for KEY[3] to be pressed to start the line delay circuit, when KEY[3] is pressed the fsm transitions to the state LIGHT_UP_LEDS;
- In the state LIGHT_UP_LEDS the 10 leds are lit up one after the other starting from led0. This feature is implemented using a counter which lights up a new led every 500 cycles of tick_50000. When all the LEDs are lit up the state WAIT_FOR_TIMEOUT is entered;
- In the state WAIT_FOR_TIMEOUT a start_delay signal is sent to the delay block, which starts counting. When the time_out signal is received from the delay block the fsm returns to the state WAIT_TRIGGER and the LEDs are turned off.
formula_fsm verilog:
module formula_fsm(clk, trigger, time_out, en_lfsr, start_delay, ledr);
input clk, trigger, time_out;
output en_lfsr, start_delay;
output [9:0] ledr;
reg [1:0] state;
reg led_on, en_lfsr, start_delay;
reg [9:0] ledr;
reg [8:0] count;
parameter WAIT_TRIGGER = 2'd0, LIGHT_UP_LEDS = 2'd1, WAIT_FOR_TIMEOUT = 2'd2;
initial
begin
state = WAIT_TRIGGER;
en_lfsr = 1'b0;
start_delay = 1'b0;
end
always @ (posedge clk)
case(state)
WAIT_TRIGGER:
begin
if(trigger == 1'b1)
state <= LIGHT_UP_LEDS;
end
LIGHT_UP_LEDS:
if(ledr == 10'h3ff)
state <= WAIT_FOR_TIMEOUT;
WAIT_FOR_TIMEOUT:
if(time_out == 1'b1)
state <= WAIT_TRIGGER;
default: ;
endcase
always @ (posedge clk)
case(state)
WAIT_TRIGGER:
ledr = 0;
LIGHT_UP_LEDS:
begin
if(count == 1'b0)
begin
ledr <= {ledr[8:0], 1'b1};
count <= 9'd499;
end
else
begin
count <= count - 1'b1;
end
end
default: count <= 9'd499;
endcase
always @ (*)
case(state)
WAIT_TRIGGER:
begin
en_lfsr = 1'b0;
start_delay = 1'b0;
end
LIGHT_UP_LEDS:
begin
en_lfsr = 1'b1;
end
WAIT_FOR_TIMEOUT:
begin
start_delay = 1'b1;
en_lfsr = 1'b0;
end
default: ;
endcase
endmodule
All the different blocks were then linked together by the following top verilog design:
module ex8(CLOCK_50, KEY, HEX0, HEX1, HEX2, LEDR);
input CLOCK_50;
input [3:0] KEY;
output [9:0] LEDR;
output [6:0] HEX0, HEX1, HEX2;
wire tick_ms, tick_hs, time_out, start_delay, en_lfsr;
wire [5:0] N;
wire [6:0] bcd_to_hex;
wire[3:0] BCD_0, BCD_1, BCD_2, BCD_3, BCD_4;
tick_50000 TICK0(CLOCK_50, tick_ms);
formula_fsm FSM(tick_ms, ~KEY[3], time_out, en_lfsr, start_delay, LEDR);
LFSR LFSR0(tick_ms, en_lfsr, N);
delay DEL0(tick_ms, N, start_delay, time_out);
bin2bcd_16 BCD(N, BCD_0, BCD_1, BCD_2, BCD_3, BCD_4);
hex_to_7seg SEG0(HEX0, BCD_0);
hex_to_7seg SEG1(HEX1, BCD_1);
hex_to_7seg SEG2(HEX2, BCD_2);
endmodule
The design was then compiled and sent to the FPGA. The design proved to be working.
When KEY[3] is pressed the lfsr starts producing random values and the LEDs light up one after the other.
When all the LEDs light up, the delay block stops generating random values. After a random amount of time (250*the value on the 7-seg displays), the LEDs turn off.