// Author: Mya Anderson myaxd.neocities.org
// Author: Mya Anderson myaxd.neocities.org
// Feel free to use this code for your own personal website development!
// Credit me if posting anywhere please!
// Node.js express server for local development of website. I use this to develop my site befor release onto Neocities
// 1. To run: make sure server.js is in the same folder as static - your folder hierarchy has to look like this:
/*
project-root/
│
├── server.js
├── package.json
├── package-lock.json
├── node_modules/
│
└── static/
│
├── html/
│ ├── index.html
│ └── 404.html
│
├── css/
│ └── indexstyle.css
│
├── js/
│ └── app.js
│
├── images/
│ └── background.png
│
├── music/
│ └── song.mp3
│
└── pdfs/
└── document.pdf
*/
// 2. Install Node.js
// 3. in a cmd prompt: navigate to your server dir
// 3.a Run the command: npm install express
// 4. Locate package.json file
// 4.a Change the type to "module" For example it will look like this: ["type": "module"]
// 5. Finally, run the server from cmd: node server.js
import express from "express";
import { fileURLToPath } from "url";
import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const port = 6767;
const app = express();
const htmlDir = path.join(__dirname, "static", "html");
const cssDir = path.join(__dirname, "static", "css");
const jsDir = path.join(__dirname, "static", "js");
const imgDir = path.join(__dirname, "static", "images");
const musicDir = path.join(__dirname, "static", "music");
const pdfDir = path.join(__dirname, "static", "pdfs");
const notFoundPage = path.join(htmlDir, "not_found.html");
const blocked = new Set(["server.js", "package.json", "package-lock.json"]);
app.use((req, res, next) => {
if (blocked.has(path.basename(req.path)) || req.path.startsWith("/node_modules")) {
return res.status(404).sendFile(notFoundPage);
}
next();
});
// HTML pages use flat paths like /index.html and /
app.use(express.static(htmlDir, { index: "index.html" }));
// CSS and JS are referenced at the site root (e.g. /indexstyle.css, /scroll.js)
app.use(express.static(cssDir));
app.use(express.static(jsDir));
app.use(express.static(musicDir));
// Images are referenced as /images/*
app.use("/images", express.static(imgDir));
// PDFs are referenced as /pdfs/*
app.use("/pdfs", express.static(pdfDir, {
setHeaders(res, filePath) {
if (path.extname(filePath).toLowerCase() === ".pdf") {
res.setHeader("Content-Type", "application/pdf");
res.setHeader("Content-Disposition", "inline");
}
}
}));
app.use((req, res) => {
res.status(404).sendFile(notFoundPage);
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
1. Install Node.js
2. in a cmd prompt: navigate to your server directory
3. Run the command: npm install express
4. Locate package.json file and change the type to "module" For example it will look like this: ["type": "module"]
5. Finally, run the server from cmd: node server.js
// Author: Mya Anderson myaxd.neocities.org
// Top module for the Hamming code calculator and verifier.
// Calculates parity bits for the original and inverted data,
// and displays results on LEDs, 7-segment display, buttons, and switches.
`timescale 1ns / 1ps
module top (
output [15:0] o16lLED,
output [ 7:0] o8lSSeg0Cathode,
output [ 3:0] o4lSSeg0Anode,
input isClk,
input [ 3:0] i4lButton,
input [15:0] i16lSwitch
);
wire [7:0] original_data;
wire [7:0] inverted_data;
wire [3:0] parityOld;
wire [3:0] parityInv;
assign original_data = i16lSwitch[7:0];
assign inverted_data = i16lSwitch[15:8];
assign o16lLED[7:0] = original_data ^ inverted_data;
hamming_calculator calcOriginalP(original_data, parityOld);
hamming_calculator calcInvertedP(original_data ^ inverted_data, parityInv);
assign o16lLED[11:8] = parityOld;
assign o16lLED[15:12] = parityInv;
endmodule
// Author: Mya Anderson myaxd.neocities.org
// Calculates the parity bits for an 8-bit data word.
`timescale 1ns / 1ps
module hamming_calculator (
input [7:0] i8lData,
output [3:0] o4lParity
);
assign o4lParity[0] = i8lData[0] ^ i8lData[1] ^ i8lData[3] ^ i8lData[4] ^ i8lData[6];
assign o4lParity[1] = i8lData[0] ^ i8lData[2] ^ i8lData[3] ^ i8lData[5] ^ i8lData[6];
assign o4lParity[2] = i8lData[1] ^ i8lData[2] ^ i8lData[3] ^ i8lData[7];
assign o4lParity[3] = i8lData[4] ^ i8lData[5] ^ i8lData[6] ^ i8lData[7];
endmodule
// Author: Mya Anderson myaxd.neocities.org
// Verifies parity bits for the original data.
`timescale 1ns / 1ps
module hamming_verifier (
input [7:0] i8lData,
input [3:0] i4lParity,
output osDataError
);
wire [3:0] c;
hamming_calculator calc(i8lData, c);
assign osDataError = |(c ^ i4lParity);
endmodule
// Author: Mya Anderson myaxd.neocities.org
`timescale 1ns / 1ps
module top_tb();
reg isClk;
reg [ 3:0] i4lButton;
reg [15:0] i16lSwitch;
wire [15:0] o16lLED;
wire [ 7:0] o8lSSeg0Cathode;
wire [ 3:0] o4lSSeg0Anode;
top fpga (
.o16lLED(o16lLED),
.o8lSSeg0Cathode(o8lSSeg0Cathode),
.o4lSSeg0Anode(o4lSSeg0Anode),
.isClk(isClk),
.i4lButton(i4lButton),
.i16lSwitch(i16lSwitch)
);
initial begin
isClk = 0;
forever #5 isClk = ~isClk; // 100 MHz clock
end
initial begin
i4lButton = 4'b0000;
i16lSwitch = 16'b10100011_00000001;
#10;
$display("original = %b", i16lSwitch[7:0]);
$display("inverted = %b", i16lSwitch[15:8]);
$display("corrupted = %b", o16lLED[7:0]);
$display("original parity = %b", o16lLED[11:8]);
$display("inverted parity = %b", o16lLED[15:12]);
if (o16lLED[11:8] == o16lLED[15:12]) begin
$display("Parity matches - ERROR NOT DETECTED (4-bit corruption passed)");
end else begin
$display("Parity mismatch - Error detected");
end
#10;
$finish;
end
endmodule
`timescale 1 ns / 1ns
`timescale 1 ns / 1ns
module clock_divider (
output reg osClk1Hz,
input isClk100MHz,
input wire reset,
input wire [31:0] divisor
);
reg [26:0] counts = 0;
always @(posedge isClk100MHz) begin
if (reset) begin
counts <= 0;
osClk1Hz <= 0;
end else if (counts == ((divisor / 2) - 1)) begin
osClk1Hz <= ~osClk1Hz;
counts <= 0;
end else begin
counts <= counts + 1;
end
end
endmodule
`timescale 1ns / 1ps
module clock_divider_tb;
reg isClk100MHz = 0;
reg reset;
reg [1:0] counter;
wire osClk1Hz;
clock_divider clkdiv (
.osClk1Hz(osClk1Hz),
.isClk100MHz(isClk100MHz),
.reset(reset)
);
always begin
#5 isClk100MHz = ~isClk100MHz;
end
// Stimulus
initial begin
counter = 0;
reset = 1;
#100;
reset = 0;
end
always @(posedge osClk1Hz) begin
counter <= counter + 1;
if (counter == 3) begin
$finish;
end
end
endmodule
`timescale 1ns / 1ps
module decoder (
output reg [7:0] o8lSSeg,
input [3:0] i4lHexDigit
);
always @(*) begin
case (i4lHexDigit)
4'h0: o8lSSeg = 8'b11000000; // 0
4'h1: o8lSSeg = 8'b11111001; // 1
4'h2: o8lSSeg = 8'b10100100; // 2
4'h3: o8lSSeg = 8'b10110000; // 3
4'h4: o8lSSeg = 8'b10011001; // 4
4'h5: o8lSSeg = 8'b10010010; // 5
4'h6: o8lSSeg = 8'b10000010; // 6
4'h7: o8lSSeg = 8'b11111000; // 7
4'h8: o8lSSeg = 8'b10000000; // 8
4'h9: o8lSSeg = 8'b10011000; // 9
4'hA: o8lSSeg = 8'b10001000; // A
4'hB: o8lSSeg = 8'b10000011; // b
4'hC: o8lSSeg = 8'b11000110; // C
4'hD: o8lSSeg = 8'b10100001; // d
4'hE: o8lSSeg = 8'b10000110; // E
4'hF: o8lSSeg = 8'b10001110; // F
default: o8lSSeg = 8'b1111_1111;
endcase
end
endmodule
`timescale 1ns / 1ps
module lfsr (
output reg [15:0] b16lPRN,
output [15:0] o16lLED,
input [15:0] i16lSeed,
input isClk,
input isRst
);
always @(posedge isClk) begin
if (isRst == 1) begin
b16lPRN <= i16lSeed;
end else begin
b16lPRN[0] <= b16lPRN[1];
b16lPRN[1] <= b16lPRN[2];
b16lPRN[2] <= b16lPRN[3];
b16lPRN[3] <= b16lPRN[4];
b16lPRN[4] <= b16lPRN[5];
b16lPRN[5] <= b16lPRN[6];
b16lPRN[6] <= b16lPRN[7];
b16lPRN[7] <= b16lPRN[8];
b16lPRN[8] <= b16lPRN[9];
b16lPRN[9] <= b16lPRN[10];
b16lPRN[10] <= b16lPRN[11] ^ b16lPRN[0];
b16lPRN[11] <= b16lPRN[12];
b16lPRN[12] <= b16lPRN[13] ^ b16lPRN[0];
b16lPRN[13] <= b16lPRN[14] ^ b16lPRN[0];
b16lPRN[14] <= b16lPRN[15];
b16lPRN[15] <= b16lPRN[0];
end
end
assign o16lLED = b16lPRN;
endmodule
`timescale 1ns / 1ps
module top (
output [15:0] o16lLED,
output wire [7:0] o8lSSeg0Cathode,
output reg [3:0] o4lSSeg0Anode,
input isClk,
input [3:0] i4lButton,
input [15:0] i16lSwitch
);
// Clock signals
wire osClk1Hz;
wire osClk7seg;
wire [15:0] b16lPRN;
reg [3:0] current_digit;
reg [1:0] digit_select = 0;
lfsr lfsr (
.b16lPRN(b16lPRN),
.i16lSeed(i16lSwitch),
.isClk(osClk1Hz),
.isRst(i4lButton[0])
);
assign o16lLED = b16lPRN;
clock_divider clk_div1Hz (
.osClk1Hz(osClk1Hz),
.isClk100MHz(isClk),
.divisor(100_000_000)
);
clock_divider clk_div7seg (
.osClk1Hz(osClk7seg),
.isClk100MHz(isClk),
.divisor(260_000)
);
decoder seg_decoder (
.o8lSSeg(o8lSSeg0Cathode),
.i4lHexDigit(current_digit)
);
initial begin
o4lSSeg0Anode = 4'b1111; // Disable all
end
// Multiplexing logic for 7-segment display
always @(posedge osClk7seg) begin
case (digit_select)
2'b00: begin
current_digit <= b16lPRN[3:0];
o4lSSeg0Anode <= 4'b1110; // Enable digit 0 (rightmost)
end
2'b01: begin
current_digit <= b16lPRN[7:4];
o4lSSeg0Anode <= 4'b1101; // Enable digit 1
end
2'b10: begin
current_digit <= b16lPRN[11:8];
o4lSSeg0Anode <= 4'b1011; // Enable digit 2
end
2'b11: begin
current_digit <= b16lPRN[15:12];
o4lSSeg0Anode <= 4'b0111; // Enable digit 3 (leftmost)
end
default:
o4lSSeg0Anode <= 4'b1111; // Disable all
endcase
digit_select <= digit_select + 1;
if (digit_select > 3) begin
digit_select = 0;
end
end
endmodule
`timescale 1ns / 1ns
module top_tb ();
//clock divider
reg isClk100MHz;
wire osClk1Hz;
reg [2:0] stop = 0;
reg reset;
//lfsr
wire [15:0] b16lPRN;
reg [15:0] i16lSeed = 8'b0000_0000_1100_0000;
reg isRst = 1;
clock_divider clock_divider (
.osClk1Hz(osClk1Hz),
.isClk100MHz(isClk100MHz),
.reset(reset),
.divisor(100_000_000)
);
lfsr lfsr (
.b16lPRN(b16lPRN),
.i16lSeed(i16lSeed),
.isClk(osClk1Hz),
.isRst(isRst)
);
always begin
#5 isClk100MHz=~isClk100MHz;
end
initial begin
isClk100MHz = 0;
reset = 1;
#10;
reset = 0;
end
initial begin
#550_000_000 isRst = 0;
end
always @(posedge osClk1Hz)
begin
stop <= stop + 1;
if (stop == 6) begin
$finish;
end
end
endmodule
`timescale 1ns / 1ps
module fsm(
input wire [3:0] i4lButton, // [0]=Start/Reset, [1]=Roll
input wire [15:0] b16lPRN, // Random 16-bit number
input wire isClk,
output reg [15:0] char_select, // Characters ("UI", "LO", "AO")
output reg [2:0] game_decision, // WIN, LOSE, AO
output reg [15:0] decision_led, // WIN, LOSE, AO
output reg [7:0] SUM,
output reg [7:0] target // Expose target to TB
);
reg [1:0] current_state, next_state;
reg [7:0] next_target;
reg [7:0] next_SUM;
reg [2:0] next_game_decision;
reg [15:0] next_char_select;
// State encoding
localparam [1:0] IDLE = 2'b00, ROLL = 2'b01, DONE = 2'b11;
// Game decisions
localparam [2:0] WIN = 3'b100, LOSE = 3'b010, AO = 3'b110;
// Characters
localparam [7:0] A = 8'b10001000, o = 8'b10100011,
U = 8'b11000001, I = 8'b11111001,
L = 8'b11000111, O = 8'b11000000;
wire [7:0] SUM_W = b16lPRN[15:8] + b16lPRN[7:0];
// Sequential block
always @(posedge isClk) begin
if (i4lButton[0]) begin
// RESET
current_state <= IDLE;
SUM <= 0;
target <= 0;
game_decision <= LOSE;
char_select <= {L,O};
decision_led <= 16'd0;
end else begin
current_state <= next_state;
SUM <= next_SUM;
target <= next_target;
game_decision <= next_game_decision;
char_select <= next_char_select;
end
end
// Combinational block
always @(*) begin
// defaults: keep previous values
next_state = current_state;
next_target = target;
next_SUM = SUM; // default: SUM frozen
next_game_decision = game_decision;
next_char_select = char_select;
case(current_state)
IDLE: begin
next_SUM = SUM_W; // display RNG in IDLE
if (i4lButton[1]) begin
if (SUM_W > 25) begin
next_state = DONE;
next_game_decision = WIN;
next_char_select = {U,I};
next_SUM = SUM_W; // latch SUM at button press
end else if (SUM_W < 5) begin
next_state = DONE;
next_game_decision = LOSE;
next_char_select = {L,O};
next_SUM = SUM_W;
end else begin
next_state = ROLL;
next_target = SUM_W;
next_game_decision = AO;
next_char_select = {A,o};
next_SUM = SUM_W; // latch SUM
end
end
end
ROLL: begin
if (i4lButton[1]) begin
next_SUM = SUM_W; // latch new roll each button press
if (SUM_W > 25) begin
next_state = DONE;
next_game_decision = LOSE;
next_char_select = {L,O};
end else if (SUM_W >= target) begin
next_state = DONE;
next_game_decision = WIN;
next_char_select = {U,I};
end else begin
next_state = ROLL;
next_game_decision = AO;
next_char_select = {A,o};
// target remains the same
end
end
end
DONE: begin
if (i4lButton[0]) begin
next_state = IDLE;
next_game_decision = LOSE;
next_char_select = {L,O};
next_target = 0;
next_SUM = 0;
end
end
default: next_state = IDLE;
endcase
end
endmodule
`timescale 1ns / 1ps
module fsm_tb ();
// Inputs
reg isClk;
reg [3:0] i4lButton;
reg [15:0] b16lPRN;
// Outputs
wire [15:0] char_select;
wire [2:0] game_decision;
wire [7:0] SUM;
wire [7:0] target;
// Instantiate DUT
fsm DUT (
.i4lButton(i4lButton),
.b16lPRN(b16lPRN),
.isClk(isClk),
.char_select(char_select),
.game_decision(game_decision),
.SUM(SUM),
.target(target)
);
// 10 ns clock
initial begin
isClk = 0;
forever #5 isClk = ~isClk;
end
// Helper pulses
task pulse_start; begin
i4lButton[0] = 1; #15;
i4lButton[0] = 0; #15;
end endtask
task pulse_roll; begin
i4lButton[1] = 1; #15;
i4lButton[1] = 0; #15;
end endtask
// Function to compute SUM from PRN
function integer sum_now(input [15:0] x);
sum_now = x[15:8] + x[7:0];
endfunction
// Testbench sequence
initial begin
i4lButton = 0;
b16lPRN = 0;
$display("\nStarting Testbench\n");
// 1) RESET / Initial state
pulse_start(); #20;
$display("1) RESET: char=%h, decision=%b, SUM=%0d, target=%d",
char_select, game_decision, SUM, target);
// 2) Immediate WIN (SUM>25)
b16lPRN = {8'd20, 8'd10}; // SUM = 30
pulse_roll(); #20;
$display("2) Immediate WIN SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
// 3) Immediate LOSE (SUM<5)
pulse_start(); #20;
b16lPRN = {8'd1,8'd2}; // SUM=3
pulse_roll(); #20;
$display("3) Immediate LOSE SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
// 4) Enter ROLL (SUM in 5-25)
pulse_start(); #20;
b16lPRN = {8'd10,8'd10}; // SUM=20
pulse_roll(); #20;
$display("4) Enter ROLL 1 SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
b16lPRN = {8'd15,8'd8}; // SUM=23, target=20
pulse_roll(); #20;
$display(" ROLL 2 -> WIN SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
pulse_start(); #20;
b16lPRN = {8'd12,8'd10}; // SUM=22 enter ROLL
pulse_roll(); #20;
$display("5) ROLL 1 -> LOSE SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
b16lPRN = {8'd60,8'd10}; // SUM=70
pulse_roll(); #20;
$display(" ROLL 2 -> LOSE SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
// 7) ROLL -> AO (SUM < target)
pulse_start(); #20;
b16lPRN = {8'd10,8'd10}; // SUM=20 enter ROLL
pulse_roll(); #20;
$display("6) ROLL 1 -> AO SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
b16lPRN = {8'd15,8'd4}; // SUM=19 < target=20
pulse_roll(); #20;
$display(" ROLL 2 -> AO SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
b16lPRN = {8'd20,8'd6}; // SUM=26 < target=19
pulse_roll(); #20;
$display(" ROLL 3 -> LOSE SUM=%0d: char=%h, decision=%b, target=%d",
sum_now(b16lPRN), char_select, game_decision, target);
// 8) RESET during DONE
pulse_start(); #20;
$display("7) RESET during DONE: char=%h, decision=%b, SUM=%0d, target=%d",
char_select, game_decision, SUM, target);
$display("\nEnding Testbench\n");
#100;
$finish;
end
endmodule
`timescale 1ns / 1ps
module top (
output [15:0] o16lLED,
output wire [ 7:0] o8lSSeg0Cathode,
output reg [ 3:0] o4lSSeg0Anode,
input isClk,
input [ 3:0] i4lButton,
input [15:0] i16lSwitch
);
// Clock signal
wire osClk1Hz;
wire osClk10Hz;
wire osClk7seg;
wire [7:0] SUM; // XOR'd Result of the random number
wire [15:0] b16lPRN;
reg [3:0] current_digit; //
reg [7:0] current_digit2; //
reg [1:0] digit_select = 0;
wire [15:0] char_select;
reg use_char = 1'b0;
// i4lButton[0] is the reset button and i4lButton[1] is the Roll button
lfsr lfsr (
.b16lPRN(b16lPRN),
.i16lSeed(i16lSwitch),
.isRst(i4lButton[0]), // Button to Start/Reset the seed
.isClk(osClk1Hz)
);
clock_divider clk_div1Hz (
.osClk1Hz(osClk1Hz),
.isClk100MHz(isClk),
.divisor(100_000_000)
);
clock_divider clk_div10Hz (
.osClk1Hz(osClk10Hz),
.isClk100MHz(isClk),
.divisor(50_000_000)
);
clock_divider clk_div7seg (
.osClk1Hz(osClk7seg),
.isClk100MHz(isClk),
.divisor(50_000) // NEW: 2 kHz refresh
);
decoder seg_decoder (
.o8lSSeg(o8lSSeg0Cathode),
.i8lHexDigit(current_digit),
.i8lBinDigit(current_digit2),
.use_char(use_char)
);
fsm fsm(
.i4lButton(i4lButton),
.b16lPRN(b16lPRN),
.char_select(char_select),
.isClk(osClk10Hz),
.SUM(SUM)
);
assign o16lLED = b16lPRN;
// Multiplexing logic for 7-segment display
always @(posedge osClk7seg) begin
case (digit_select)
2'b00: begin
use_char <= 1'b0;
current_digit <= {4'b0, SUM[3:0]};
o4lSSeg0Anode <= 4'b1110;
end
2'b01: begin
use_char <= 1'b0;
current_digit <= {4'b0, SUM[7:4]};
o4lSSeg0Anode <= 4'b1101;
end
2'b10: begin
use_char <= 1'b1;
current_digit2 <= char_select[7:0];
o4lSSeg0Anode <= 4'b1011;
end
2'b11: begin
use_char <= 1'b1;
current_digit2 <= char_select[15:8];
o4lSSeg0Anode <= 4'b0111;
end
endcase
digit_select <= digit_select + 1;
end
endmodule
`timescale 1ns / 1ps
module top_tb ();
reg isClk;
reg [3:0] i4lButton;
reg [15:0] b16lPRN;
wire [15:0] char_select;
wire [1:0] game_decision;
wire [7:0] SUM;
fsm DUT (
.i4lButton(i4lButton),
.b16lPRN(b16lPRN),
.isClk(isClk),
.char_select(char_select),
.game_decision(game_decision),
.SUM(SUM)
);
// System clock (10ns period)
initial begin
isClk = 0;
forever #5 isClk = ~isClk;
end
// Proper pulse (≥3 cycles)
task pulse_start;
begin
i4lButton[0] = 0;
#40;
i4lButton[0] = 1;
#40;
end
endtask
task pulse_roll;
begin
i4lButton[1] = 0;
#40;
i4lButton[1] = 1;
#40;
end
endtask
// Helper: print SUM immediately from PRN
function integer sum_now;
input [15:0] x;
begin
sum_now = x[15:8] + x[7:0];
end
endfunction
initial begin
i4lButton = 0;
b16lPRN = 0;
$display("\n Starting Testbench \n");
// TEST 1 : RESET
pulse_start();
#20;
$display("1) Reset test char=%h decision=%b (Expect LO Initial)",
char_select, game_decision);
$display(" Stored target = %0d\n", DUT.target);
// TEST 2 : WIN immediately
b16lPRN = {8'd20, 8'd10}; // SUM = 30
$display("2) SUM > 25 immediate win. SUM=%0d", sum_now(b16lPRN));
pulse_roll();
#20;
$display(" Stored target = %0d", DUT.target);
$display(" Result char=%h decision=%b (WIN expected)\n",
char_select, game_decision);
// RESET AGAIN
pulse_start();
#20;
// TEST 3 : LOSE immediately
b16lPRN = {8'd1, 8'd2}; // SUM = 3
$display("3) SUM < 5 immediate loss. SUM=%0d", sum_now(b16lPRN));
pulse_roll();
#20;
$display(" Stored target = %0d", DUT.target);
$display(" Result char=%h decision=%b (LOSE expected)\n",
char_select, game_decision);
// RESET AGAIN
pulse_start();
#20;
// TEST 4 : ENTER ROLL state (correct test)
b16lPRN = {8'd10, 8'd10}; // SUM = 20
$display("4) Enter ROLL: SUM=%0d (5-25 OK)", sum_now(b16lPRN));
pulse_roll();
#20;
$display(" Stored target (should be 20) = %0d\n", DUT.target);
// Now WIN if SUM >= target
b16lPRN = {8'd15, 8'd6}; // SUM = 20
$display(" Roll WIN test: SUM=%0d vs target=%0d",
sum_now(b16lPRN), DUT.target);
pulse_roll();
#20;
$display(" Result char=%h decision=%b (WIN expected)\n",
char_select, game_decision);
// RESET AGAIN
pulse_start();
#20;
// TEST 5 : ENTER ROLL then LOSE
b16lPRN = {8'd12, 8'd10}; // SUM = 22
$display("5) Enter ROLL: SUM=%0d", sum_now(b16lPRN));
pulse_roll();
#20;
$display(" Stored target = %0d", DUT.target);
// Now LOSE with SUM > 25
b16lPRN = {8'd60, 8'd10}; // SUM = 70
$display(" Roll LOSE test: SUM=%0d vs target=%0d",
sum_now(b16lPRN), DUT.target);
pulse_roll();
#20;
$display(" Result char=%h decision=%b (LOSE expected)\n",
char_select, game_decision);
pulse_start();
#20;
// TEST 6 : ENTER ROLL state (correct test)
b16lPRN = {8'd10, 8'd10}; // SUM = 20
$display("6) Enter ROLL: SUM=%0d (5-25 OK)", sum_now(b16lPRN));
pulse_roll();
#20;
$display(" Stored target (should be 20) = %0d\n", DUT.target);
// Now WIN if SUM >= target
b16lPRN = {8'd15, 8'd4}; // SUM = 19
$display(" Roll AO test: SUM=%0d vs target=%0d",
sum_now(b16lPRN), DUT.target);
pulse_roll();
#20;
$display(" Stored target (should be 20) = %0d\n", DUT.target);
b16lPRN = {8'd15, 8'd6}; // SUM = 20
$display(" Result char=%h decision=%b (WIN expected)\n",
char_select, game_decision);
// END
$display("\n Ending Testbench \n");
#100;
$finish;
end
endmodule