Course design of Hangdian digital circuit -- taxi meter
Experimental purpose
(1) Learn the dynamic scanning method of nixie tube, be further familiar with the method of module call, and exercise the ability of programming and designing digital system.
(2) Master the skills and methods of flexibly using Verilog HDL language for various description and modeling.
Module design
(1) Frequency division module: because the simulation of taxi meter is in seconds, i.e. a CLK is generated by dividing the frequency by 1 second_ Out to control the operation of other modules.
(2) Meter module: used to increase the corresponding mileage according to the effective unit time and speed.
(3) Taxi and other traffic lights module: it is used for timing when waiting for traffic lights. If it is 10 seconds, a time is generated_ The enable signal controls whether the meter charges for traffic lights.
(4) Billing module: calculate the corresponding fee according to the incoming mileage and time_ The enable signal determines whether to add additional traffic light charging.
(5) Nixie tube refresh module: used to refresh the nixie tube. The refresh rate is 62.5Hz to ensure that people can't feel the flicker of the nixie tube visually.
(6) Binary to BCD code module: used to convert the incoming mileage and expenses into BCD code for nixie tube display.
(7) Nixie tube display module: convert the mileage or cost into position selection and segment selection signals according to the corresponding control signals to realize the realization of nixie tube.
Program module relationship
(1) The frequency division 1s effective clock signal of the frequency division module controls the work of the meter module, taxi and other traffic light modules and billing modules.
(2) The mileage of the metering module is used for the cost calculation of the billing module.
(3) Design of traffic light module such as taxi_ Enable is used to control whether the billing module generates additional fees for traffic lights such as taxis.
(4) The bit selection signal generated by the nixie tube refresh module is used to control the nixie tube display.
(5) Mileage BCD code and expense BCD code generated by binary BCD code conversion module are used for nixie tube display.
program source code
module sy_last_code(reset, clk_M, start, pause, waitL, speedup, d_m, Seg, AN); input reset; input clk_M; input start; input pause; input waitL; input [1:0] speedup; input d_m; //Segment selection output [7:0] Seg; //Bit selection output [3:0] AN; wire [9:0] fee_before; wire [9:0] distance_before; wire [15:0] distance_b; wire [15:0] fee_b; wire time_enable; wire clk_out; wire [1:0] Bit_Sel; Fdiv u1(reset, clk_M, clk_out); // calculated by mileage Distance u2(clk_out, reset, start, speedup, waitL, pause, distance_before); // Waiting time for traffic lights Time u3(clk_out, reset, pause, waitL, time_enable); // charging Fee u4(clk_out, reset, waitL, pause, time_enable, distance_before, start, fee_before); // Frequency division refresh nixie tube Delay_4ms u5(clk_M, Bit_Sel); // Binary conversion to BCD code Binary u6(distance_before, distance_b); Binary u7(fee_before, fee_b); // Display nixie tube Smg u8(d_m, fee_b, distance_b, Bit_Sel, Seg, AN); endmodule //frequency divider // 1s module Fdiv( input wire reset, input wire clk_M, output reg clk_out ); // Define counter reg [31:0] counter; initial begin counter = 32'd0; end initial begin clk_out = 0; end always @(posedge reset or posedge clk_M) begin if(reset) begin // reset to 0 counter <= 32'd0; clk_out <= 1'b0; end else if(counter == 32'd12_500_000) begin clk_out <= ~clk_out; counter <= 32'd0; end else begin counter <= counter + 1'b1; clk_out <= 0; end end endmodule //Meter module module Distance( input wire clk, // Car reset input wire reset, // Car start input wire start, input wire [1:0] speedup, // Waiting for the bus (traffic light) input wire waitL, // Suspension of vehicle behavior input wire pause, output reg [9:0] distance ); initial begin distance = 10'b0; end always @(posedge reset or posedge clk) begin if(reset) begin distance <= 10'd0; end else if(start && !waitL && !pause) begin case(speedup) 2'b0_0: begin distance <= distance + 10'd1; end 2'b0_1: begin distance <= distance + 10'd2; end 2'b1_0: begin distance <= distance + 10'd3; end 2'b1_1: begin distance <= distance + 10'd4; end endcase end end endmodule // The timing module is used when waiting for a red light module Time( input wire clk, input wire reset, input wire pause, input wire waitL, output reg time_enable ); reg [7:0]count; initial begin count = 8'd0; end initial begin time_enable = 0; end always @(posedge reset or posedge clk) begin if(reset) begin count <= 8'd0; time_enable <= 0; end else if(count == 8'd10) begin time_enable <= ~time_enable; count <= 8'd0; end else if(!pause && waitL) begin count <= count + 1'd1; time_enable <= 0; end end endmodule // charging module Fee( input wire clk, input wire reset, input wire waitL, input wire pause, input wire time_enable, input wire [9:0] distance, input wire start, output reg [9:0] fee ); initial begin fee <= 10'b0; end parameter s_fee = 10'd60; always @(posedge reset or posedge clk) begin if(reset) begin fee <= 16'd0; end else if(start && !waitL && !pause) begin if(distance <= 30) begin fee <= s_fee; end else if(fee < 10'd200) begin fee <= s_fee + (12 * (distance - 30)) / 10; if(fee > 10'd200) begin fee <= s_fee + (18 * (distance - 30)) / 10; end end else begin fee <= s_fee + (18 * (distance - 30)) / 10; end end else if(time_enable) begin fee <= fee + 10'd5; end end endmodule // Frequency division refresh nixie tube module Delay_4ms(clk_M,Bit_Sel); input wire clk_M; output reg [1:0] Bit_Sel; // Define counter integer counter = 0; initial begin Bit_Sel <= 2'b00; end always@(posedge clk_M) begin counter <= counter + 1; // 25MHz clock pulse // The refresh frequency of 62.5Hz is adopted to obtain 16ms, and the time for each nixie tube to select the channel is 4ms if(counter == 100000) begin Bit_Sel <= Bit_Sel + 2'b01; counter <= 0; end end endmodule // Nixie tube display module Smg( input wire d_m, input wire [15:0] fee, input wire [15:0] distance, //Nixie tube selection input wire [1:0] Bit_Sel, //Segment selection output reg [7:0] Seg, //Bit selection output reg [3:0] AN ); reg [3:0] Data_now; reg [7:0] duan_ctrl; initial begin Data_now = 4'b0; duan_ctrl = 8'b0; end always @(*) begin case(Bit_Sel) 2'b00:AN<=4'b1000; 2'b01:AN<=4'b1001; 2'b10:AN<=4'b1010; 2'b11:AN<=4'b1011; default:AN<=4'b1111; endcase end always @(*) begin if(d_m) begin case(Bit_Sel) 2'b00: Data_now[3:0] <= distance[15:12]; 2'b01: Data_now[3:0] <= distance[11:8]; 2'b10: Data_now[3:0] <= distance[7:4]; 2'b11: Data_now[3:0] <= distance[3:0]; default: Data_now[3:0] <= distance[3:0]; endcase end else begin case(Bit_Sel) 2'b00: Data_now[3:0] <= fee[15:12]; 2'b01: Data_now[3:0] <= fee[11:8]; 2'b10: Data_now[3:0] <= fee[7:4]; 2'b11: Data_now[3:0] <= fee[3:0]; default: Data_now[3:0] <= fee[3:0]; endcase end end always @(*) begin // 0~9 // It adopts common anode connection, low-level lighting, and 8 signals according to the nixie tube if(Bit_Sel == 2'b10) begin case(Data_now[3:0]) 4'b0000: Seg[7:0] <= 8'b00000010; 4'b0001: Seg[7:0] <= 8'b10011110; 4'b0010: Seg[7:0] <= 8'b00100100; 4'b0011: Seg[7:0] <= 8'b00001100; 4'b0100: Seg[7:0] <= 8'b10011000; 4'b0101: Seg[7:0] <= 8'b01001000; 4'b0110: Seg[7:0] <= 8'b01000000; 4'b0111: Seg[7:0] <= 8'b00011110; 4'b1000: Seg[7:0] <= 8'b00000000; 4'b1001: Seg[7:0] <= 8'b00001000; default:Seg[7:0]<=8'b11111111; endcase end else begin case(Data_now[3:0]) 4'b0000: Seg[7:0] <= 8'b00000011; 4'b0001: Seg[7:0] <= 8'b10011111; 4'b0010: Seg[7:0] <= 8'b00100101; 4'b0011: Seg[7:0] <= 8'b00001101; 4'b0100: Seg[7:0] <= 8'b10011001; 4'b0101: Seg[7:0] <= 8'b01001001; 4'b0110: Seg[7:0] <= 8'b01000001; 4'b0111: Seg[7:0] <= 8'b00011111; 4'b1000: Seg[7:0] <= 8'b00000001; 4'b1001: Seg[7:0] <= 8'b00001001; default:Seg[7:0]<=8'b11111111; endcase end end endmodule module Binary(bin,bcd); input wire [9:0] bin; output reg [15:0] bcd; initial begin bcd = 16'b0; end always @(*) begin bcd [ 3:0] = bin % 10;//Bit bcd [ 7:4] = bin /10 % 10;//Ten bcd [11:8] = bin / 100 % 10;//Hundredth bcd [15:12] = bin / 1000 % 10;//Hundredth end endmodule
Test program source code
module test; // Inputs reg reset; reg clk_M; reg start; reg pause; reg waitL; reg [1:0] speedup; reg d_m; // Outputs wire [7:0] Seg; wire [3:0] AN; // Instantiate the Unit Under Test (UUT) sy_last_code uut ( .reset(reset), .clk_M(clk_M), .start(start), .pause(pause), .waitL(waitL), .speedup(speedup), .d_m(d_m), .Seg(Seg), .AN(AN) ); always begin #10 clk_M = ~clk_M; end initial begin // Initialize Inputs reset = 1; clk_M = 0; start = 1; pause = 0; waitL = 0; speedup = 0; d_m = 0; // Wait 100 ns for global reset to finish #100; reset = 0; start = 1; pause = 0; waitL = 0; speedup = 2'b00; d_m = 1; end endmodule
Thinking and problems encountered
1. Problems and solutions in the experiment
Problems:
In the binary to BCD module, the shift method of judging greater than 4 plus 3 is used to realize the conversion of BCD code. All cases are true, but in the conversion of 9, 3 is added every time.
Solution:
Finally, the integer division and remainder method is adopted, that is, the individual bit is the remainder of 10, the ten bit is the remainder of 10, the hundred bit is the remainder of 100 to 10, and the thousand bit is the remainder of 100 to 10. Finally, it is successfully debugged and tested.
2. Thinking and exploration
Question 1: if the system clock frequency is 20MHz, what changes should be made to the source program to achieve the required gear speed?
Because this experiment uses the system clock frequency of 25MHz to calculate, that is, to achieve the speed per second, modify the count value in the delay module. The original 25MHz is divided into 1Hz and the count value is 12_ 500_ 000; At present, 20MHz is divided into 1Hz and the count value is 10_ 000_ 000.
Question 2: if it is required to display the fare accurately to 1 yuan and the mileage accurately to 1 km, how should the program be modified?
In the binary to BCD code module, the single digit is set to 0 by default, that is, the number after the decimal point is not output, which means that it is accurate to 1 yuan or 1 kilometer, but the complete value is stored in the register, which meets the system requirements and can switch the accuracy at any time.
This article is original by the author. Please attach a link for reprint!!
The complete report content has been uploaded ~
Creation is not easy ~ ~