# Course design of Hangdian digital circuit -- taxi meter

Posted by JohnMC on Thu, 03 Feb 2022 03:47:59 +0100

# 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.