//-------------------------------------------------------------------------------
// combined_top.v — wszystkie moduły w jednym pliku
//-------------------------------------------------------------------------------
module top
(
input wire CLK_PCB,
input wire nRST_PCB,
input wire ROAD_DET,
output wire ROAD_RED,
output wire ROAD_YELLOW,
output wire ROAD_GREEN,
input wire PED_BUTT,
output wire PED_RED,
output wire PED_GREEN,
output wire [3:0] LED
);
// zegar i asynchroniczny reset
wire CLK = CLK_PCB;
wire RST_PCB = ~nRST_PCB;
wire RST_async, RST_sync, RST;
assign RST_async = RST_PCB;
rst_synch_bridge rst_bridge (
.I_RST (RST_async),
.CLK (CLK),
.O_RST (RST_sync)
);
assign RST = RST_sync;
// heartbeat dla diod LED
reg [31:0] heartbeat_clk;
always @(posedge CLK or posedge RST) begin
if (RST)
heartbeat_clk <= 0;
else
heartbeat_clk <= heartbeat_clk + 1;
end
// stan diod LED (status: ROAD_DET, PED_BUTT, RST, heartbeat)
assign LED = ~{ ROAD_DET, PED_BUTT, RST, heartbeat_clk[27] };
// wewnętrzny przewód dla brzęczyka (można podłączyć do fizycznego BUZZER)
wire buzz_unused;
// instancja maszyny stanowej sterującej światłami
automat #(
.TICK_LENGTH(50000 - 1)
) u_automat (
.RST (RST),
.CLK (CLK),
.P_P (PED_BUTT),
.CAR (ROAD_DET),
.CR (ROAD_RED),
.CY (ROAD_YELLOW),
.CG (ROAD_GREEN),
.PR (PED_RED),
.PG (PED_GREEN),
.BUZZ (buzz_unused)
);
endmodule
//-------------------------------------------------------------------------------
// automat — licznik + logika zmiany stanu
//-------------------------------------------------------------------------------
module automat #(
parameter TICK_LENGTH = 50000 - 1 // sub-sekundowy dzielnik
)(
input wire RST, // asynchroniczny reset
input wire CLK, // taktowanie
input wire P_P, // przycisk pieszy (opcjonalnie)
input wire CAR, // detekcja samochodu (opcjonalnie)
output wire CR, // czerwone dla aut
output wire CY, // żółte dla aut
output wire CG, // zielone dla aut
output wire PR, // czerwone dla pieszych
output wire PG, // zielone dla pieszych
output wire BUZZ // brzęczyk
);
reg [31:0] COUNT_SEC; // dzielnik sub-sekund
reg [31:0] COUNT; // licznik sekund
reg [2:0] NEXT_STATE; // kolejny stan
// proces synchroniczny z asynchronicznym resetem
always @(posedge CLK or posedge RST) begin
if (RST) begin
COUNT_SEC <= TICK_LENGTH;
COUNT <= 8;
NEXT_STATE <= 0;
end else begin
if (COUNT_SEC == 0) begin
COUNT_SEC <= TICK_LENGTH;
if (COUNT == 0) begin
COUNT <= 8;
NEXT_STATE <= NEXT_STATE + 1;
end else begin
COUNT <= COUNT - 1;
end
end else begin
COUNT_SEC <= COUNT_SEC - 1;
end
end
end
// bieżący stan maszyny
wire [2:0] STATE = NEXT_STATE;
// mapowanie stanu na wyjścia
stan2LED s2l (
.STATE(STATE),
.CR (CR),
.CY (CY),
.CG (CG),
.PR (PR),
.PG (PG),
.BUZZ (BUZZ)
);
endmodule
//-------------------------------------------------------------------------------
// stan2LED — mapowanie stanu na diody i brzęczyk
//-------------------------------------------------------------------------------
module stan2LED (
input wire [2:0] STATE,
output reg CR,
output reg CY,
output reg CG,
output reg PR,
output reg PG,
output reg BUZZ
);
always @(*) begin
// domyślnie wszystko wyłączone
CR = 0;
CY = 0;
CG = 0;
PR = 0;
PG = 0;
BUZZ = 0;
case (STATE)
0: begin
// idle
end
1: begin
CR = 1; PR = 1; // czerwone auta + czerwone piesi
end
2: begin
CR = 1; CY = 1; PR = 1; // czerwone+żółte auta + czerwone piesi
end
3: begin
CG = 1; PR = 1; // zielone auta + czerwone piesi
end
4: begin
CY = 1; PR = 1; // żółte auta + czerwone piesi
end
5: begin
CR = 1; PR = 1; // ponownie czerwone auta + czerwone piesi
end
6: begin
CR = 1; PG = 1; // czerwone auta + zielone piesi
end
7: begin
CR = 1;
BUZZ = 1; // czerwone auta + brzęczyk
end
endcase
end
endmodule