From 3863bfbecdc1b6e143353e6975e6b02674021cb5 Mon Sep 17 00:00:00 2001 From: Kostas Drakontidis Date: Wed, 4 Nov 2026 12:50:44 +0200 Subject: [PATCH] refactor & add tbs --- lab1/lab1.srcs/sim_1/imports/source/tb.v | 26 --- .../sim_1/imports/source/tb_driver.v | 60 ------ .../partA.srcs/sim_1/new/tb_LEDdecoder.v | 60 ++++++ .../sources_1/imports/source/LEDdecoder.v | 48 ++--- lab1/partA/partA.xpr | 189 ++++++++++++++++++ .../partB.ip_user_files}/README.txt | 0 .../constrs_1/imports/source/boolean.xdc | 0 lab1/partB/partB.srcs/sim_1/new/tb_driver.v | 108 ++++++++++ .../sources_1/imports/source/LEDdecoder.v | 24 +++ .../sources_1/new}/FourDigitLEDdriver.v | 182 ++++++++--------- lab1/{lab1.xpr => partB/partB.xpr} | 64 ++---- 11 files changed, 514 insertions(+), 247 deletions(-) delete mode 100644 lab1/lab1.srcs/sim_1/imports/source/tb.v delete mode 100644 lab1/lab1.srcs/sim_1/imports/source/tb_driver.v create mode 100644 lab1/partA/partA.srcs/sim_1/new/tb_LEDdecoder.v rename lab1/{lab1.srcs => partA/partA.srcs}/sources_1/imports/source/LEDdecoder.v (97%) create mode 100644 lab1/partA/partA.xpr rename lab1/{lab1.ip_user_files => partB/partB.ip_user_files}/README.txt (100%) rename lab1/{lab1.srcs => partB/partB.srcs}/constrs_1/imports/source/boolean.xdc (100%) create mode 100644 lab1/partB/partB.srcs/sim_1/new/tb_driver.v create mode 100644 lab1/partB/partB.srcs/sources_1/imports/source/LEDdecoder.v rename lab1/{lab1.srcs/sources_1/imports/source => partB/partB.srcs/sources_1/new}/FourDigitLEDdriver.v (65%) rename lab1/{lab1.xpr => partB/partB.xpr} (78%) diff --git a/lab1/lab1.srcs/sim_1/imports/source/tb.v b/lab1/lab1.srcs/sim_1/imports/source/tb.v deleted file mode 100644 index b34a746..0000000 --- a/lab1/lab1.srcs/sim_1/imports/source/tb.v +++ /dev/null @@ -1,26 +0,0 @@ -`timescale 1ns / 1ps - -module tb; - - reg [3:0] char; - wire [6:0] LED; - integer i; - - LEDdecoder dut ( - .char(char), - .LED (LED) - ); - - initial begin - $dumpfile("wave.vcd"); - $dumpvars(0, tb); - - for (i = 0; i < 16; i = i + 1) begin - char = i; - #10; - $display("char=%h LED{a..g}=%b", char, LED); - end - $finish; - end - -endmodule diff --git a/lab1/lab1.srcs/sim_1/imports/source/tb_driver.v b/lab1/lab1.srcs/sim_1/imports/source/tb_driver.v deleted file mode 100644 index 1d21fca..0000000 --- a/lab1/lab1.srcs/sim_1/imports/source/tb_driver.v +++ /dev/null @@ -1,60 +0,0 @@ -`timescale 1ns / 1ps - -module tb_driver; - - reg clk = 0; - reg reset = 1; - wire an3, an2, an1, an0; - wire a, b, c, d, e, f, g, dp; - - FourDigitLEDdriver dut ( - .clk(clk), - .reset(reset), - .an3(an3), - .an2(an2), - .an1(an1), - .an0(an0), - .a(a), - .b(b), - .c(c), - .d(d), - .e(e), - .f(f), - .g(g), - .dp(dp) - ); - - always #5 clk = ~clk; // 100 MHz - - wire [3:0] low = ~{an3, an2, an1, an0}; - always @(low) - if ((low & (low - 1)) != 0) - $display("ERROR t=%0t: επικάλυψη ανόδων, an=%b", $time, {an3, an2, an1, an0}); - - always @(an3 or an2 or an1 or an0) - $display( - "t=%0t state=%b digit=%h an=%b%b%b%b seg(abcdefg)=%b%b%b%b%b%b%b", - $time, - dut.state, - dut.digit, - an3, - an2, - an1, - an0, - a, - b, - c, - d, - e, - f, - g - ); - - initial begin - $dumpfile("wave_driver.vcd"); - $dumpvars(0, tb_driver); - #100 reset = 0; - #20000 $finish; - end - -endmodule diff --git a/lab1/partA/partA.srcs/sim_1/new/tb_LEDdecoder.v b/lab1/partA/partA.srcs/sim_1/new/tb_LEDdecoder.v new file mode 100644 index 0000000..de807f4 --- /dev/null +++ b/lab1/partA/partA.srcs/sim_1/new/tb_LEDdecoder.v @@ -0,0 +1,60 @@ +`timescale 1ns / 1ps + +module tb_LEDdecoder; + + reg [3:0] char; + wire [6:0] LED; + reg [6:0] expected[0:15]; + integer i, errors; + + // LED = {a,b,c,d,e,f,g}, 1 = on + localparam [6:0] A = 7'b1000000, B = 7'b0100000, C = 7'b0010000, + D = 7'b0001000, E = 7'b0000100, F = 7'b0000010, + G = 7'b0000001; + + LEDdecoder dut ( + .char(char), + .LED (LED) + ); + + // Segment outputs + wire ca = LED[6], cb = LED[5], cc = LED[4], cd = LED[3], ce = LED[2], cf = LED[1], cg = LED[0]; + + initial begin + expected[4'h0] = A | B | C | D | E | F; + expected[4'h1] = B | C; + expected[4'h2] = A | B | D | E | G; + expected[4'h3] = A | B | C | D | G; + expected[4'h4] = B | C | F | G; + expected[4'h5] = A | C | D | F | G; + expected[4'h6] = A | C | D | E | F | G; + expected[4'h7] = A | B | C; + expected[4'h8] = A | B | C | D | E | F | G; + expected[4'h9] = A | B | C | D | F | G; + expected[4'hA] = A | B | C | E | F | G; + expected[4'hB] = C | D | E | F | G; + expected[4'hC] = A | D | E | F; + expected[4'hD] = B | C | D | E | G; + expected[4'hE] = A | D | E | F | G; + expected[4'hF] = A | E | F | G; + + $dumpfile("wave.vcd"); + $dumpvars(0, tb_LEDdecoder); + errors = 0; + + for (i = 0; i < 16; i = i + 1) begin + char = i; + #10; + if (LED !== expected[i]) begin + errors = errors + 1; + $display("ERROR char=%h LED=%b expected=%b", char, LED, expected[i]); + end + end + + if (errors == 0) $display("PASS: 16 tests passed"); + else $display("FAIL: %0d tests failed", errors); + $finish; + end + +endmodule + diff --git a/lab1/lab1.srcs/sources_1/imports/source/LEDdecoder.v b/lab1/partA/partA.srcs/sources_1/imports/source/LEDdecoder.v similarity index 97% rename from lab1/lab1.srcs/sources_1/imports/source/LEDdecoder.v rename to lab1/partA/partA.srcs/sources_1/imports/source/LEDdecoder.v index a639af1..f3203e3 100644 --- a/lab1/lab1.srcs/sources_1/imports/source/LEDdecoder.v +++ b/lab1/partA/partA.srcs/sources_1/imports/source/LEDdecoder.v @@ -1,24 +1,24 @@ -module LEDdecoder ( - input [3:0] char, - output [6:0] LED -); - - assign LED = (char == 4'h0) ? 7'b1111110 : // 0 - (char == 4'h1) ? 7'b0110000 : // 1 - (char == 4'h2) ? 7'b1101101 : // 2 - (char == 4'h3) ? 7'b1111001 : // 3 - (char == 4'h4) ? 7'b0110011 : // 4 - (char == 4'h5) ? 7'b1011011 : // 5 - (char == 4'h6) ? 7'b1011111 : // 6 - (char == 4'h7) ? 7'b1110000 : // 7 - (char == 4'h8) ? 7'b1111111 : // 8 - (char == 4'h9) ? 7'b1111011 : // 9 - (char == 4'hA) ? 7'b1110111 : // A - (char == 4'hB) ? 7'b0011111 : // B - (char == 4'hC) ? 7'b1001110 : // C - (char == 4'hD) ? 7'b0111101 : // D - (char == 4'hE) ? 7'b1001111 : // E - (char == 4'hF) ? 7'b1000111 : // F - 7'b0000000; - -endmodule +module LEDdecoder ( + input [3:0] char, + output [6:0] LED +); + + assign LED = (char == 4'h0) ? 7'b1111110 : // 0 + (char == 4'h1) ? 7'b0110000 : // 1 + (char == 4'h2) ? 7'b1101101 : // 2 + (char == 4'h3) ? 7'b1111001 : // 3 + (char == 4'h4) ? 7'b0110011 : // 4 + (char == 4'h5) ? 7'b1011011 : // 5 + (char == 4'h6) ? 7'b1011111 : // 6 + (char == 4'h7) ? 7'b1110000 : // 7 + (char == 4'h8) ? 7'b1111111 : // 8 + (char == 4'h9) ? 7'b1111011 : // 9 + (char == 4'hA) ? 7'b1110111 : // A + (char == 4'hB) ? 7'b0011111 : // B + (char == 4'hC) ? 7'b1001110 : // C + (char == 4'hD) ? 7'b0111101 : // D + (char == 4'hE) ? 7'b1001111 : // E + (char == 4'hF) ? 7'b1000111 : // F + 7'b0000000; + +endmodule diff --git a/lab1/partA/partA.xpr b/lab1/partA/partA.xpr new file mode 100644 index 0000000..cc0e1ef --- /dev/null +++ b/lab1/partA/partA.xpr @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Vivado Synthesis Defaults + + + + + + + + + + Default settings for Implementation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default_dashboard + + + + + + diff --git a/lab1/lab1.ip_user_files/README.txt b/lab1/partB/partB.ip_user_files/README.txt similarity index 100% rename from lab1/lab1.ip_user_files/README.txt rename to lab1/partB/partB.ip_user_files/README.txt diff --git a/lab1/lab1.srcs/constrs_1/imports/source/boolean.xdc b/lab1/partB/partB.srcs/constrs_1/imports/source/boolean.xdc similarity index 100% rename from lab1/lab1.srcs/constrs_1/imports/source/boolean.xdc rename to lab1/partB/partB.srcs/constrs_1/imports/source/boolean.xdc diff --git a/lab1/partB/partB.srcs/sim_1/new/tb_driver.v b/lab1/partB/partB.srcs/sim_1/new/tb_driver.v new file mode 100644 index 0000000..ccf0cdc --- /dev/null +++ b/lab1/partB/partB.srcs/sim_1/new/tb_driver.v @@ -0,0 +1,108 @@ +`timescale 1ns / 1ps + +module tb_driver; + + reg clk = 0; + reg reset = 1; + wire an3, an2, an1, an0; + wire a, b, c, d, e, f, g, dp; + + FourDigitLEDdriver dut ( + .clk(clk), + .reset(reset), + .an3(an3), + .an2(an2), + .an1(an1), + .an0(an0), + .a(a), + .b(b), + .c(c), + .d(d), + .e(e), + .f(f), + .g(g), + .dp(dp) + ); + + always #5 clk = ~clk; // 100 MHz + + wire [3:0] an = {an3, an2, an1, an0}; // active-low + wire [3:0] lit = ~an; // 1 = anode enabled + wire [6:0] seg = {a, b, c, d, e, f, g}; // active-low + + integer errors = 0; + integer scans = 0; + + // 1) No double anodes lit at the same time + always @(an) + if ((lit & (lit - 4'd1)) != 4'd0) begin + errors = errors + 1; + $display("ERROR t=%0t: overlapping anodes an=%b", $time, an); + end + + // 2) No segment change on lit anode + realtime t_seg_change = 0; + always @(seg) begin + t_seg_change = $realtime; + if (lit != 4'd0) begin + errors = errors + 1; + $display("ERROR t=%0t: segment change on lit anode", $time); + end + end + + // 3) Margin: stable data >= 200 ns before anode off + reg [3:0] prev_lit = 4'd0; + always @(lit) begin + if (prev_lit == 4'd0 && lit != 4'd0 && ($realtime - t_seg_change) < 200.0) begin + errors = errors + 1; + $display("ERROR t=%0t: not enough margin", $time); + end + prev_lit = lit; + end + + // 4) Correct digit for each anode (0123, left to right) + task check_seg(input [6:0] expected); + begin + #100; + if (seg !== expected) begin + errors = errors + 1; + $display("ERROR t=%0t: an=%b seg=%b expected=%b", $time, an, seg, expected); + end + end + endtask + + always @(an) begin + case (an) + 4'b0111: check_seg(7'b0000001); // AN3: 0 + 4'b1011: check_seg(7'b1001111); // AN2: 1 + 4'b1101: check_seg(7'b0010010); // AN1: 2 + 4'b1110: check_seg(7'b0000110); // AN0: 3 + default: ; + endcase + end + + // 5) Scan period = 16 x 200 ns = 3200 ns + realtime t_an3_fall = 0; + always @(negedge an3) begin + scans = scans + 1; + if (t_an3_fall != 0 && + (($realtime - t_an3_fall) < 3199.0 || ($realtime - t_an3_fall) > 3201.0)) begin + errors = errors + 1; + $display("ERROR t=%0t: scan period %0f ns", $time, $realtime - t_an3_fall); + end + t_an3_fall = $realtime; + end + + initial begin + #100 reset = 0; + #100000; // 100 us (includes MMCM lock) + if (scans < 10) begin + errors = errors + 1; + $display("ERROR: %0d scans (MMCM not locked)", scans); + end + if (errors == 0) $display("PASS: %0d scans no errors", scans); + else $display("FAIL: %0d errors", errors); + $finish; + end + +endmodule diff --git a/lab1/partB/partB.srcs/sources_1/imports/source/LEDdecoder.v b/lab1/partB/partB.srcs/sources_1/imports/source/LEDdecoder.v new file mode 100644 index 0000000..f3203e3 --- /dev/null +++ b/lab1/partB/partB.srcs/sources_1/imports/source/LEDdecoder.v @@ -0,0 +1,24 @@ +module LEDdecoder ( + input [3:0] char, + output [6:0] LED +); + + assign LED = (char == 4'h0) ? 7'b1111110 : // 0 + (char == 4'h1) ? 7'b0110000 : // 1 + (char == 4'h2) ? 7'b1101101 : // 2 + (char == 4'h3) ? 7'b1111001 : // 3 + (char == 4'h4) ? 7'b0110011 : // 4 + (char == 4'h5) ? 7'b1011011 : // 5 + (char == 4'h6) ? 7'b1011111 : // 6 + (char == 4'h7) ? 7'b1110000 : // 7 + (char == 4'h8) ? 7'b1111111 : // 8 + (char == 4'h9) ? 7'b1111011 : // 9 + (char == 4'hA) ? 7'b1110111 : // A + (char == 4'hB) ? 7'b0011111 : // B + (char == 4'hC) ? 7'b1001110 : // C + (char == 4'hD) ? 7'b0111101 : // D + (char == 4'hE) ? 7'b1001111 : // E + (char == 4'hF) ? 7'b1000111 : // F + 7'b0000000; + +endmodule diff --git a/lab1/lab1.srcs/sources_1/imports/source/FourDigitLEDdriver.v b/lab1/partB/partB.srcs/sources_1/new/FourDigitLEDdriver.v similarity index 65% rename from lab1/lab1.srcs/sources_1/imports/source/FourDigitLEDdriver.v rename to lab1/partB/partB.srcs/sources_1/new/FourDigitLEDdriver.v index 058b785..f31549a 100644 --- a/lab1/lab1.srcs/sources_1/imports/source/FourDigitLEDdriver.v +++ b/lab1/partB/partB.srcs/sources_1/new/FourDigitLEDdriver.v @@ -1,91 +1,91 @@ -module FourDigitLEDdriver ( - input clk, - input reset, - output an3, - an2, - an1, - an0, - output a, - b, - c, - d, - e, - f, - g, - dp -); - - wire clk_fb, clk_slow_raw, clk_slow, locked; - - MMCME2_BASE #( - .BANDWIDTH ("OPTIMIZED"), - .CLKIN1_PERIOD (10.0), // 100 MHz - .DIVCLK_DIVIDE (1), - .CLKFBOUT_MULT_F (6.0), // VCO = 600 MHz - .CLKOUT1_DIVIDE (120), // 600/120 = 5 MHz - .CLKFBOUT_PHASE (0.0), - .CLKOUT1_PHASE (0.0), - .CLKOUT1_DUTY_CYCLE(0.5), - .STARTUP_WAIT ("FALSE") - ) MMCME2_BASE_inst ( - .CLKIN1(clk), - .CLKFBIN(clk_fb), - .CLKFBOUT(clk_fb), - .CLKOUT1(clk_slow_raw), - .LOCKED(locked), - .PWRDWN(1'b0), - .RST(reset) - ); - - BUFG bufg_slow ( - .I(clk_slow_raw), - .O(clk_slow) - ); - - wire rst_int = reset | ~locked; - - reg [3:0] state; - always @(posedge clk_slow or posedge rst_int) begin - if (rst_int) state <= 4'b1111; - else state <= state - 1; // one step per 200 ns - end - - reg [3:0] an; - reg [3:0] digit; - - always @(*) begin - case (state) - 4'b1110: an = 4'b0111; - 4'b1010: an = 4'b1011; - 4'b0110: an = 4'b1101; - 4'b0010: an = 4'b1110; - default: an = 4'b1111; - endcase - end - - always @(*) begin - case (state) - 4'b0000, 4'b1111, 4'b1110, 4'b1101: digit = 4'h0; - 4'b1100, 4'b1011, 4'b1010, 4'b1001: digit = 4'h1; - 4'b1000, 4'b0111, 4'b0110, 4'b0101: digit = 4'h2; - default: digit = 4'h3; - endcase - end - - wire [6:0] LED; - LEDdecoder LEDdecoder_inst ( - .char(digit), - .LED (LED) - ); - - assign {an3, an2, an1, an0} = an; - assign a = ~LED[6]; - assign b = ~LED[5]; - assign c = ~LED[4]; - assign d = ~LED[3]; - assign e = ~LED[2]; - assign f = ~LED[1]; - assign g = ~LED[0]; - assign dp = 1'b1; - -endmodule +module FourDigitLEDdriver ( + input clk, + input reset, + output an3, + an2, + an1, + an0, + output a, + b, + c, + d, + e, + f, + g, + dp +); + + wire clk_fb_out, clk_fb, clk_slow_raw, clk_slow, locked; + + MMCME2_BASE #( + .BANDWIDTH ("OPTIMIZED"), + .CLKIN1_PERIOD (10.0), // 100 MHz + .DIVCLK_DIVIDE (1), + .CLKFBOUT_MULT_F(6.0), // VCO = 600 MHz + .CLKOUT1_DIVIDE (120), // 600/120 = 5 MHz + .STARTUP_WAIT ("FALSE") + ) MMCME2_BASE_inst ( + .CLKIN1 (clk), + .CLKFBOUT(clk_fb_out), + .CLKFBIN (clk_fb), + .CLKOUT1 (clk_slow_raw), + .LOCKED (locked), + .PWRDWN (1'b0), + .RST (reset) + ); + + BUFG bufg_fb ( + .I(clk_fb_out), + .O(clk_fb) + ); + BUFG bufg_slow ( + .I(clk_slow_raw), + .O(clk_slow) + ); + + wire rst_int = reset | ~locked; + + reg [3:0] state; + always @(posedge clk_slow or posedge rst_int) begin + if (rst_int) state <= 4'b1111; + else state <= state - 1; // one step per 200 ns + end + + reg [3:0] an; + always @(*) begin + case (state) + 4'b1110: an = 4'b0111; + 4'b1010: an = 4'b1011; + 4'b0110: an = 4'b1101; + 4'b0010: an = 4'b1110; + default: an = 4'b1111; + endcase + end + + reg [3:0] digit; + always @(*) begin + case (state) + 4'b0000, 4'b1111, 4'b1110, 4'b1101: digit = 4'h0; + 4'b1100, 4'b1011, 4'b1010, 4'b1001: digit = 4'h1; + 4'b1000, 4'b0111, 4'b0110, 4'b0101: digit = 4'h2; + default: digit = 4'h3; + endcase + end + + wire [6:0] LED; + LEDdecoder LEDdecoder_inst ( + .char(digit), + .LED (LED) + ); + + assign {an3, an2, an1, an0} = an; + assign a = ~LED[6]; + assign b = ~LED[5]; + assign c = ~LED[4]; + assign d = ~LED[3]; + assign e = ~LED[2]; + assign f = ~LED[1]; + assign g = ~LED[0]; + assign dp = 1'b1; + +endmodule diff --git a/lab1/lab1.xpr b/lab1/partB/partB.xpr similarity index 78% rename from lab1/lab1.xpr rename to lab1/partB/partB.xpr index 530f711..24f1574 100644 --- a/lab1/lab1.xpr +++ b/lab1/partB/partB.xpr @@ -3,10 +3,10 @@ - + - @@ -61,17 +57,15 @@ - - + + - + - - @@ -87,8 +81,8 @@ - - + + @@ -98,20 +92,9 @@ - + + - - - - - - - - - - - - @@ -121,6 +104,7 @@