更新:
其余各部分代碼已公布。
-------------------------------------------------------------------------------------------------------
大二數字電路的課程設計中,有一份日常作業使用Xilinx FPGA實現簡易交通信號燈,但很可惜當時時間有限,沒能最終完成。正好在這一學期選修SOPC設計課程,同樣采用了Xilinx FPGA,故打算重新完成交通信號燈的相關內容。
本項目采用Digilent公司生產的BASYS3開發板,基於Xilinx FPGA,該板子目前可以在馬雲家買到,不過價格偏貴,在校學生可在digilent官網申請以更低價格買入。
大致的框架如下,只是個構思,還很不完善,后續會進行修改。比如現在我目前並沒有把計時功能完全從State模塊中摘出來,只是用Timer實例化了一個1s計時器在里面,並且用count計數。
TOP代碼
module BASYS_BIGPROJECT_Top ( input clk, output wire[5:0]Trans_light, output wire[3:0]Num_choose, output wire[7:0]Num_data ); wire [1:0]state_connect; wire [2:0]count_connect; //wire [6:0]Num_data_connect; BASYS_BIGPROJECT_State state( .clk(clk), .state(state_connect), .count(count_connect) ); BASYS_BIGPROJECT_Display display( .clk(clk), .count(count_connect), .state(state_connect), .Trans_light(Trans_light), .Num_choose(Num_choose), .Num_data(Num_data) ); endmodule
State代碼
module BASYS_BIGPROJECT_State( input clk, output [1:0]state, output [2:0]count ); reg [1:0]reg_state = 0; reg [2:0]reg_count = 0; wire cnt_connect; Freq_divider clk_1s( .clk(clk), .rst(0), .count(cnt_connect) ); //states for lights parameter MR_BG = 2'b00; parameter MR_BY = 2'b01; parameter MG_BR = 2'b11; parameter MY_BR = 2'b10; //green led for 4s, yellow led for 2s always@(posedge cnt_connect) begin case(reg_state) MR_BG:begin //main red, branch green if(reg_count<4) begin reg_state <= MR_BG; reg_count <= reg_count + 1; end else begin reg_state <= MR_BY; reg_count <= 3'b000; end end MR_BY:begin //main red, branch yellow if(reg_count<2) begin reg_state <= MR_BY; reg_count <= reg_count + 1; end else begin reg_state <= MG_BR; reg_count <= 3'b000; end end MG_BR:begin //main green, branch red if(reg_count<4) begin reg_state <= MG_BR; reg_count <= reg_count + 1; end else begin reg_state <= MY_BR; reg_count <= 3'b000; end end MY_BR:begin //main yellow, branch red if(reg_count<2) begin reg_state <= MY_BR; reg_count <= reg_count + 1; end else begin reg_state <= MR_BG; reg_count <= 3'b000; end end endcase end assign state = reg_state; assign count = reg_count; endmodule
Display代碼
module BASYS_BIGPROJECT_Display ( input clk, input [1:0]state, input [2:0]count, output [5:0]Trans_light, output [3:0]Num_choose, output [7:0]Num_data ); reg [5:0]reg_light = 0; reg [3:0]reg_Num_digit = 0; reg [3:0]reg_Num_choose = 4'b1110; wire [7:0]Num_data_connect; wire refresh; reg [3:0]Data_Main = 0; reg [3:0]Data_Branch = 0; //divider for refresh Freq_divider #(13)play( .clk(clk), .rst(1'b0), .count(refresh) ); //Decode the digit Digital_decode decoder( .clk(clk), .data(reg_Num_digit), .Trans_num(Num_data_connect) ); //switch the light always @(posedge clk) begin case(state) 2'b00:begin reg_light <= 6'b100001; Data_Main <= 6 - count; Data_Branch <= 4 - count; end 2'b01:begin reg_light <= 6'b100010; Data_Main <= 2 - count; Data_Branch <= 2 - count; end 2'b11:begin reg_light <= 6'b001100; Data_Main <= 4 - count; Data_Branch <= 6 - count; end 2'b10:begin reg_light <= 6'b010100; Data_Main <= 2 - count; Data_Branch <= 2 - count; end endcase end //Scanned display for digit always @(posedge refresh) begin if(reg_Num_choose == 4'b1110) begin reg_Num_choose <= 4'b1011; reg_Num_digit <= Data_Main; end else begin reg_Num_choose <= 4'b1110; reg_Num_digit <= Data_Branch; end end assign Trans_light = reg_light; assign Num_choose = reg_Num_choose; assign Num_data = Num_data_connect; endmodule
Tools代碼
module Freq_divider #(parameter N = 27) ( input clk, input rst, output [N-1:0]freq_div, output count ); reg [N-1:0]regN = 0; always@(posedge clk) begin if(rst) regN <= 0; else regN <= regN+1; end assign freq_div = regN; assign count = (regN == 2**N-1)?1'b1:1'b0; endmodule module Digital_decode ( input clk, input [3:0]data, output [7:0]Trans_num ); reg [7:0]reg_Trans_num = 0; always@(posedge clk) begin case(data) 4'd0: reg_Trans_num <= 8'b0000_0011; 4'd1: reg_Trans_num <= 8'b1001_1111; 4'd2: reg_Trans_num <= 8'b0010_0101; 4'd3: reg_Trans_num <= 8'b0000_1101; 4'd4: reg_Trans_num <= 8'b1001_1001; 4'd5: reg_Trans_num <= 8'b0100_1001; 4'd6: reg_Trans_num <= 8'b0100_0001; 4'd7: reg_Trans_num <= 8'b0001_1111; 4'd8: reg_Trans_num <= 8'b0000_0001; 4'd9: reg_Trans_num <= 8'b0000_1001; default: reg_Trans_num <= 8'b0001_0001; endcase end assign Trans_num = reg_Trans_num; endmodule