用verilog语言实验反应计时器功能

img


用verilog语言实验反应计时器功能
要求可以存储测试结果并进行查看,以及拥有可查看反应最长与最短时间的功能


module muxer(
    input clock,
    input reset,
    input [3:0] fourth,
    input [3:0] third,
    input [3:0] second,
    input [3:0] first,
    output a_m,
    output b_m,
    output c_m,
    output d_m,
    output e_m,
    output f_m,
    output g_m,
    output dp_m,
    output [3:0] an_m
    );

//The Circuit for 7 Segment Multiplexing - 

localparam N = 18; 

reg [N-1:0]count; //the 18 bit counter which allows us to multiplex at 1000Hz

always @ (posedge clock or posedge reset)
 begin
  if (reset)
   count <= 0;
  else
   count <= count + 1;
 end

reg [3:0]sseg; //the 4 bit register to hold the data that is to be output
reg [3:0]an_temp; //register for the 4 bit enable
reg reg_dp;
always @ (*)
 begin
  case(count[N-1:N-2]) //MSB and MSB-1 for multiplexing
   
   2'b00 : 
    begin
     sseg = first;
     an_temp = 4'b1110;
     reg_dp = 1'b1;
    end
   
   2'b01:
    begin
     sseg = second;
     an_temp = 4'b1101;
     reg_dp = 1'b0;
    end
   
   2'b10:
    begin
     sseg = third;
     an_temp = 4'b1011;
     reg_dp = 1'b0;
    end
    
   2'b11:
    begin
     sseg = fourth;
     an_temp = 4'b0111;
     reg_dp = 1'b1;
    end
  endcase
 end
assign an_m = an_temp;

reg [6:0] sseg_temp; 
always @ (*)
 begin
  case(sseg)
   4'd0 : sseg_temp = 7'b1000000; //display 0
   4'd1 : sseg_temp = 7'b1111001; //display 1
   4'd2 : sseg_temp = 7'b0100100; //display 2
   4'd3 : sseg_temp = 7'b0110000; //display 3
   4'd4 : sseg_temp = 7'b0011001; //display 4
   4'd5 : sseg_temp = 7'b0010010; //display 5
   4'd6 : sseg_temp = 7'b0000010; //display 6
   4'd7 : sseg_temp = 7'b1111000; //display 7
   4'd8 : sseg_temp = 7'b0000000; //display 8
   4'd9 : sseg_temp = 7'b0010000; //display 9
   4'd10 : sseg_temp = 7'b0001001; //to display H
   4'd11 : sseg_temp = 7'b1001111; //to display I
   default : sseg_temp = 7'b0111111; //dash
  endcase
 end
assign {g_m, f_m, e_m, d_m, c_m, b_m, a_m} = sseg_temp; 
assign dp_m = reg_dp;

endmodule
module reaction_main(
  input clock, reset, start, stop,
  output led,
  output [3:0] an,
  output a, b, c, d, e, f, g, dp
  );
reg [3:0] regd3, regd2, regd1, regd0; //the main output registers

wire db_start, db_stop;
reg dffstr1, dffstr2, dffstp1, dffstp2;
 
always @ (posedge clock) dffstr1 <= start;
always @ (posedge clock) dffstr2 <= dffstr1;
 
assign db_start = ~dffstr1 & dffstr2; //monostable multivibrator to detect only one pulse of the button
 
always @ (posedge clock) dffstp1 <= stop;
always @ (posedge clock) dffstp2 <= dffstp1;
 
assign db_stop = ~dffstp1 & dffstp2; //monostable multivibrator to detect only one pulse of the button


// Instantiate the 7 segment multiplexing module
muxer display (
    .clock(clock), 
    .reset(reset), 
    .fourth(regd3), 
    .third(regd2), 
    .second(regd1), 
    .first(regd0), 
    .a_m(a), 
    .b_m(b), 
    .c_m(c), 
    .d_m(d), 
    .e_m(e), 
    .f_m(f), 
    .g_m(g), 
    .dp_m(dp), 
    .an_m(an)
    );

//Block for LFSR random number generator  

reg [28:0] random, random_next, random_done; //**29 bit register to keep track upto 10 seconds. 


reg [4:0] count_r, count_next_r; //to keep track of the shifts. 5 bit register to count up to 30

wire feedback = random[28] ^ random[26]; 

always @ (posedge clock or posedge reset)
begin
 if (reset)
 begin
  random <= 29'hF; //An LFSR cannot have an all 0 state, thus reset to FF. 
  count_r <= 0;
 end
 
 else
 begin
  random <= random_next;
  count_r <= count_next_r;
 end
end

always @ (*)
begin
 random_next = random; //default state stays the same
 count_next_r = count_r;
  
  random_next = {random[27:0], feedback}; //shift left the xor'd every posedge clock
           

 if (count_r == 29) 
 begin
  count_next_r = 0;
  random_done = random; //assign the random number to output after 30 shifts
 end
 else
 begin
  count_next_r = count_r + 1;
  random_done = random; //keep previous value of random
 end
 
end
//random number block ends


reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
(* KEEP = "TRUE" *)reg [1:0] sel, sel_next; //for KEEP attribute see note below
localparam [1:0]
      idle = 2'b00,
      starting = 2'b01,
      time_it = 2'b10,
      done = 2'b11;
      
reg [1:0] state_reg, state_next;
reg [28:0] count_reg, count_next; 

always @ (posedge clock or posedge reset)
begin
 if(reset)
  begin 
   state_reg <= idle;
   count_reg <= 0;
   sel <=0;
  end
 else
  begin
   state_reg <= state_next;
   count_reg <= count_next;
   sel <= sel_next;
  end
end

reg go_start;
always @ (*)
begin
 state_next = state_reg; //default state stays the same
 count_next = count_reg;
 sel_next = sel;
 case(state_reg)
  idle:
   begin
    //DISPLAY HI HERE
    sel_next = 2'b00;
    if(db_start)
    begin
     count_next = random_done; //get the random number from LFSR module
     state_next = starting; //go to next state
    end
   end
  starting:
   begin
    if(count_next == 500000000) // **500M equals a delay of 10 seconds. and starting from 'rand' ensures a random delay
    begin  
     state_next = time_it; //go to next state
    end
    
    else
    begin
     count_next = count_reg + 1; 
    end
   end  
  time_it:
   begin
     sel_next = 2'b01; //start the timer
     state_next = done;     
   end
    
  done:
   begin
    if(db_stop)
     begin
      sel_next = 2'b10; //stop the timer
     end
    
   end
   
  endcase
  
 case(sel_next) //this case statement that will control what is sent to the 7 segment based on the sel signal
  2'b00: //hi
  begin
   go_start = 0; //make sure timer module is off
   regd0 = 4'd12; 
   regd1 = 4'd11;
   regd2 = 4'd10;
   regd3 = 4'd12;
  end
  
  2'b01: //timer
  begin
   
   go_start = 1'b1; //enable start signal to start timer
   regd0 = reg_d0;
   regd1 = reg_d1;
   regd2 = reg_d2;
   regd3 = reg_d3;
  end
  
  2'b10: //stop timer
  begin
   go_start = 1'b0;
   regd0 = reg_d0;
   regd1 = reg_d1;
   regd2 = reg_d2;
   regd3 = reg_d3;
  end
  
  2'b11: //Although this condition is of no use to us it is placed here for the sake of completion, case statements left uncompleted will create a latch in implementation
  begin
   regd0 = 4'd12; //4'd12 to siplay '-'
   regd1 = 4'd12;
   regd2 = 4'd12;
   regd3 = 4'd12;
   go_start = 1'b0;
  end
  
  default:
  begin
   regd0 = 4'd12;
   regd1 = 4'd12;
   regd2 = 4'd12;
   regd3 = 4'd12;
   go_start = 1'b0;
  end
 endcase   
end


//the stopwatch block


reg [18:0] ticker; //19 bits needed to count up to 500K bits
wire click;

//the mod 500K clock to generate a tick ever 0.01 second

always @ (posedge clock or posedge reset)
begin
 if(reset)

  ticker <= 0;

 else if(ticker == 500000) //if it reaches the desired max value of 500K reset it
  ticker <= 0;
 else if(go_start) //only start if the input is set high
  ticker <= ticker + 1;
end

assign click = ((ticker == 500000)?1'b1:1'b0); //click to be assigned high every 0.01 second

always @ (posedge clock or posedge reset)
begin
 if (reset)
  begin
   reg_d0 <= 0;
   reg_d1 <= 0;
   reg_d2 <= 0;
   reg_d3 <= 0;
  end
  
 else if (click) //increment at every click
  begin
   if(reg_d0 == 9) //xxx9 - the 0.001 second digit
   begin  //if_1
    reg_d0 <= 0;
    
    if (reg_d1 == 9) //xx99 
    begin  // if_2
     reg_d1 <= 0;
     if (reg_d2 == 5) //x599 - the two digit seconds digits
     begin //if_3
      reg_d2 <= 0;
      if(reg_d3 == 9) //9599 - The minute digit
       reg_d3 <= 0;
      else
       reg_d3 <= reg_d3 + 1;
     end
     else //else_3
      reg_d2 <= reg_d2 + 1;
    end
    
    else //else_2
     reg_d1 <= reg_d1 + 1;
   end 
   
   else //else_1
    reg_d0 <= reg_d0 + 1;
  end
end

//If count_reg == 500M - check if 'stop' key is pressed, if yes disable led, otherwise enable it. If count_reg ~= 500M keep led off.
assign led = ((count_reg == 500000000)?((db_stop == 1)?1'b0:1'b1):1'b0);

endmodule

https://download.csdn.net/download/bill20100829/85531611