運行環境:VCS + verdi
狀態說明:
S0 :?初始狀態
S1 :?東西方向綠燈亮,南北方向紅燈亮;點亮30周期
S2 :?東西方向黃燈亮,南北方向紅燈亮;點亮2 周期
S3?:?東西方向紅燈亮,南北方向綠燈亮;點亮30周期
S4 :?東西方向紅燈亮,南北方向黃燈亮;點亮2 周期
狀態轉換說明:
S0 → S1
S1:點亮30周期,進入S2,不足30周期維持S1
S2:點亮2周期,進入S3,不足2周期維持S2
S3:點亮30周期,進入S4,不足30周期維持S3
S4:點亮2周期,進入S1,不足2周期維持S4
代碼如下:
如果需要控制時間,自行添加分頻器,或者修改tb文件。
module traffic_light (input clk,input rst_n,output [2:0] light_east_west, light_south_north
);// 紅路燈點亮的時間定義
localparam GREEN = 30;
localparam YELLOW = 2;// 亮燈的顏色定義
localparam dark = 2'b00;
localparam green = 2'b01;
localparam yello = 2'b10;
localparam red = 2'b11;// 狀態定義
parameter S0 = 5'b0_0001; // 初始狀態
parameter S1 = 5'b0_0010; // 東西方向綠燈亮,南北方向紅燈亮;30周期
parameter S2 = 5'b0_0100; // 東西方向黃燈亮,南北方向紅燈亮;2 周期
parameter S3 = 5'b0_1000; // 東西方向紅燈亮,南北方向綠燈亮;30周期
parameter S4 = 5'b1_0000; // 東西方向紅燈亮,南北方向黃燈亮;2 周期reg [4:0] status;
reg [4:0] next_status;
reg [7:0] cnt;// 計數器控制
always @(posedge clk or negedge rst_n) beginif(!rst_n) cnt <= 8'b0;else if ( (status == S1 && cnt == GREEN-1 ) ||(status == S2 && cnt == YELLOW-1) ||(status == S3 && cnt == GREEN-1 ) ||(status == S4 && cnt == YELLOW-1) )cnt <= 8'b0;elsecnt <= cnt + 1'b1;
end// 狀態轉換
always @(posedge clk or negedge rst_n) beginif(!rst_n)status <= S0;elsestatus <= next_status;
end// 狀態判斷
always @(*) beginif(!rst_n) beginnext_status = S0;endelse begincase(status)S0 : next_status = S1;S1 : next_status = (cnt == GREEN-1) ? S2 : S1;S2 : next_status = (cnt == YELLOW-1) ? S3 : S2;S3 : next_status = (cnt == GREEN-1) ? S4 : S3;S4 : next_status = (cnt == YELLOW-1) ? S1 : S4;default : next_status = S0;endcaseend
endreg [2:0] r_light_east_west, r_light_south_north;// 輸出控制
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginr_light_east_west <= dark;r_light_south_north <= dark;endelse begincase(status)S0 : beginr_light_east_west <= dark;r_light_south_north <= dark;endS1 : beginr_light_east_west <= green;r_light_south_north <= red;endS2 : beginr_light_east_west <= yello;r_light_south_north <= red;endS3 : beginr_light_east_west <= red;r_light_south_north <= green;endS4 : beginr_light_east_west <= red;r_light_south_north <= yello;enddefault: beginr_light_east_west <= dark;r_light_south_north <= dark;endendcaseend
endassign light_east_west = r_light_east_west;
assign light_south_north = r_light_south_north;endmodule
tb文件:
module tb_traffic_light ();
localparam CLK_PERIDO = 20;reg clk;
reg rst_n;
reg [2:0] light_east_west;
reg [2:0] light_south_north;traffic_light traffic_light_inst(.clk (clk),.rst_n (rst_n),.light_east_west (light_east_west), .light_south_north (light_south_north)
);initial beginclk = 0;forever #(CLK_PERIDO / 2) clk = ~clk;
endinitial beginrst_n = 0;repeat(4) @(posedge clk);#(CLK_PERIDO /5);rst_n = 1;repeat(500) @(posedge clk);$finish;
endinitial begin$dumpfile("traffic_light.fsdb");$dumpvars(0);
endendmodule