From 2b6aa409b8d82186598c714f4e847950e36d1a86 Mon Sep 17 00:00:00 2001 From: nsinghal06 Date: Wed, 18 Feb 2026 15:58:07 -0500 Subject: [PATCH 1/3] test --- src/{tt_um_ieeeuoftasic_simproc.sv => tt_um_CCValidator.sv} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{tt_um_ieeeuoftasic_simproc.sv => tt_um_CCValidator.sv} (97%) diff --git a/src/tt_um_ieeeuoftasic_simproc.sv b/src/tt_um_CCValidator.sv similarity index 97% rename from src/tt_um_ieeeuoftasic_simproc.sv rename to src/tt_um_CCValidator.sv index ca9e292..f19ec4c 100644 --- a/src/tt_um_ieeeuoftasic_simproc.sv +++ b/src/tt_um_CCValidator.sv @@ -5,7 +5,7 @@ `default_nettype none -module tt_um_ieeeuoftasic_simproc ( +module tt_um_CCValidator ( input wire [7:0] ui_in, // Dedicated inputs output wire [7:0] uo_out, // Dedicated outputs input wire [7:0] uio_in, // IOs: Input path From ee26ca1dda3366ca3d5b2c52728230567fb79f0c Mon Sep 17 00:00:00 2001 From: nsinghal06 Date: Wed, 18 Feb 2026 16:35:14 -0500 Subject: [PATCH 2/3] created input pan stream file --- src/pan_stream.sv | 167 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 src/pan_stream.sv diff --git a/src/pan_stream.sv b/src/pan_stream.sv new file mode 100644 index 0000000..34a6310 --- /dev/null +++ b/src/pan_stream.sv @@ -0,0 +1,167 @@ +// Module 1: PAN input stream: 16 digits +// What it does: +// - Receives a stream of digits (0..9) with digit_valid +// - start = 1-cycle pulse to begin a new PAN +// - end = 1-cycle pulse to finish the PAN (ideally asserted with the last digit_valid) +// - Counts digits (length), captures IIN prefix (first 8 digits), and streams digits out +// +// Outputs: +// - card_done (pulse when end received) +// - len_final and length_ok +// - iin_prefix and iin_ready +// - error_flag if protocol is weird (e.g., end without digit_valid) + +module pan_stream #( + parameter int MIN_LEN = 13, + parameter int MAX_LEN = 19, + parameter int IIN_DIGITS = 6 // capture first 6 digits +) ( + input logic clk, + input logic rst_n, + + // Host inputs + input logic start, // 1-cycle pulse: begin new card + input logic pan_end, // 1-cycle pulse: last digit has been sent + input logic digit_valid, + input logic [3:0] digit_in, //actual digit/bit value being streamed in + input logic abort, // optional: cancel card (can tie low) + + // Stream outputs (to Luhn) + output logic [3:0] s_digit, //actual digit/bit value being streamed onward + output logic s_valid, //high when module is accepting digits + output logic s_first, // pulse on first accepted digit + output logic s_last, // pulse on last accepted digit + + // Length outputs (how many have been recieved/acceptable) + output logic [4:0] len_count, // running count + output logic [4:0] len_final, // how many numbers counter between 13 - 19 + output logic len_parity, // parity of final length odd or even: needed for luhn alogrithm + output logic length_ok, // valid length range? + + // IIN capture (to issuer lookup) + output logic [31:0] iin_prefix, // 8 digits packed as nibbles + output logic [3:0] iin_digits_captured, // 0..8 + output logic iin_ready, // high once enough digits captured + + // Framing / status + output logic in_progress, + output logic card_done, // 1-cycle pulse when card finishes + output logic digit_ok, // sticky: all digits were 0..9 + output logic error_flag // sticky: protocol / invalid digit errors +); + + // Accept digits only while in_progress + //logic replaces reg/wire: is simpler because can be used in alwyas block + logic accept_digit; + assign accept_digit = in_progress && digit_valid; + + // Forward digit stream (gated) + //sv version of always@(*) combinational block + always_comb begin + s_digit = digit_in; + s_valid = accept_digit; + end + + // Sequential state + //updated ff on every pos edge + always_ff @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + //reset states + in_progress <= 1'b0; + len_count <= 5'd0; + len_final <= 5'd0; + + iin_prefix <= 32'd0; + iin_digits_captured <= 4'd0; + iin_ready <= 1'b0; + + s_first <= 1'b0; + s_last <= 1'b0; + card_done <= 1'b0; + + digit_ok <= 1'b1; + error_flag <= 1'b0; + end + + else begin + // default pulses low each cycle + s_first <= 1'b0; + s_last <= 1'b0; + card_done <= 1'b0; + + // Start a new PAN + //set to 0 at start of every clk, when digit is sent, set pulse to 1 + if (start) begin + in_progress <= 1'b1; //actively accepting digits + len_count <= 5'd0; //start count from 0 + len_final <= 5'd0; + + iin_prefix <= 32'd0; //clear IIN + iin_digits_captured <= 4'd0; + iin_ready <= 1'b0; + + digit_ok <= 1'b1; //assume digit ok until error + error_flag <= 1'b0; // clear errors for new card + end + + // Abort cancels the current PAN + if (abort && in_progress) begin + in_progress <= 1'b0; + error_flag <= 1'b1; + end + + // Accept a digit + if (accept_digit) begin + // First digit pulse + if (len_count == 5'd0) begin + s_first <= 1'b1; + end + + // Digit validity check + if (digit_in > 4'd9) begin + digit_ok <= 1'b0; + error_flag <= 1'b1; + end + + // Increment length + len_count <= len_count + 5'd1; + + // Capture first IIN_DIGITS digits into iin_prefix + if (iin_digits_captured < IIN_DIGITS[3:0]) begin + iin_prefix <= (iin_prefix & ~(32'hF << (4*iin_digits_captured))) | + ({28'd0, digit_in} << (4*iin_digits_captured)); + iin_digits_captured <= iin_digits_captured + 4'd1; + + // Mark ready after at least 6 digits (adjust if you want 8) + if (iin_digits_captured + 4'd1 >= 4'd6) + iin_ready <= 1'b1; + end + end + + // End-of-card handling + // Assumption: end is asserted on the same cycle as the last digit_valid. + if (pan_end && in_progress) begin + if (digit_valid) begin + s_last <= 1'b1; + end else begin + // end without digit_valid is odd; flag it + error_flag <= 1'b1; + end + + // Latch final length: + // If end coincides with digit_valid, final length should include that digit. + len_final <= len_count + (digit_valid ? 5'd1 : 5'd0); + + card_done <= 1'b1; + in_progress <= 1'b0; + end + end + end + + // Derived outputs + always_comb begin + len_parity = len_final[0]; + length_ok = (len_final >= MIN_LEN[4:0]) && (len_final <= MAX_LEN[4:0]); + end + +endmodule From 7ebd102c62b744964006ded99c664431dda9c067 Mon Sep 17 00:00:00 2001 From: SiddharthShroff-dotcom <126933869+SiddharthShroff-dotcom@users.noreply.github.com> Date: Wed, 18 Feb 2026 23:24:31 -0500 Subject: [PATCH 3/3] Add files via upload Luhn files --- src/DEPS.yml | 8 +++ src/dumpfile_new.fst | Bin 0 -> 900 bytes src/luhn_validator.sv | 113 +++++++++++++++++++++++++++++++ src/tb_luhn_validator.sv | 143 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 src/DEPS.yml create mode 100644 src/dumpfile_new.fst create mode 100644 src/luhn_validator.sv create mode 100644 src/tb_luhn_validator.sv diff --git a/src/DEPS.yml b/src/DEPS.yml new file mode 100644 index 0000000..525d86b --- /dev/null +++ b/src/DEPS.yml @@ -0,0 +1,8 @@ +# DEPS configuration for Luhn Validator project + +# Luhn validator testbench simulation +luhn_tb: + deps: + - luhn_validator.sv + - tb_luhn_validator.sv + top: tb_luhn_validator diff --git a/src/dumpfile_new.fst b/src/dumpfile_new.fst new file mode 100644 index 0000000000000000000000000000000000000000..7dad0d333397eee575b97a17772e2c07efb43d74 GIT binary patch literal 900 zcmchU&2G~`6ot=B9J_W3PUUeEBvg!7T{=G`ZCFr*M8qD{MJQ?7gvL@JRpOK)kU-+E zCR_?*8i`o?a2 zNv=#ymcgSm7txK#e%i0T_VY}(zv_3=acERfu|G;s64WB!J(QmHtyiz_PNC`*9gvs}c?!~^zMXpi)N zYL<|PC|nrhzl@DmFyT0vk2b~+=5BvouU(G6YCfFZf_@P%>1rA5{)o!_@AM&pwQ8%^ zyj$I>wfuT5Xw&1SQ1>_dpyI7Km0ZbNfns4UL&}nJq&(>YsX!`{7D$U0&SiGN%so&t zkhU*v2%O0rfL&o#`hw;_cn%RGJcFRC)Ta<}!V?IUK%JTeyLg_7 zsZptqU|7(~%uWcXd$6Yo1K6hs`>;y2)=QSWm#1$75H zc|Y{mp}!6NUFbKN++CG!FWd`@rgW{vj5N$|P>fGpOEL31Wkarc(0|}(JZJ~CR<+x^ N<5UWAcp8q5{s56(UJL*L literal 0 HcmV?d00001 diff --git a/src/luhn_validator.sv b/src/luhn_validator.sv new file mode 100644 index 0000000..5a973a9 --- /dev/null +++ b/src/luhn_validator.sv @@ -0,0 +1,113 @@ +// Luhn Algorithm Validator +// Validates a 16-digit decimal number using the Luhn algorithm +// Input: 16 digits (each 4 bits, BCD encoded) +// Output: valid (1 if checksum passes, 0 otherwise) + + +module luhn_validator ( + input logic [3:0] digit [15:0], // 16 digits, digit[0] is rightmost + output logic valid +); + + // Processed digit values after doubling and digit sum + logic [3:0] processed [15:0]; + + // Total sum + logic [6:0] total_sum; + + // Process each digit + // Digits at odd positions from right (digit[1], [3], [5], etc.) are doubled + // Digits at even positions from right (digit[0], [2], [4], etc.) stay the same + + always_comb begin + // Process digit 0 (rightmost) - no doubling + processed[0] = digit[0]; + + // Process digit 1 - double it + if (digit[1] <= 4'd4) begin + processed[1] = digit[1] << 1; // Just double + end else begin + processed[1] = (digit[1] << 1) - 4'd9; // Double and subtract 9 (adds digits) + end + + // Process digit 2 - no doubling + processed[2] = digit[2]; + + // Process digit 3 - double it + if (digit[3] <= 4'd4) begin + processed[3] = digit[3] << 1; + end else begin + processed[3] = (digit[3] << 1) - 4'd9; + end + + // Process digit 4 - no doubling + processed[4] = digit[4]; + + // Process digit 5 - double it + if (digit[5] <= 4'd4) begin + processed[5] = digit[5] << 1; + end else begin + processed[5] = (digit[5] << 1) - 4'd9; + end + + // Process digit 6 - no doubling + processed[6] = digit[6]; + + // Process digit 7 - double it + if (digit[7] <= 4'd4) begin + processed[7] = digit[7] << 1; + end else begin + processed[7] = (digit[7] << 1) - 4'd9; + end + + // Process digit 8 - no doubling + processed[8] = digit[8]; + + // Process digit 9 - double it + if (digit[9] <= 4'd4) begin + processed[9] = digit[9] << 1; + end else begin + processed[9] = (digit[9] << 1) - 4'd9; + end + + // Process digit 10 - no doubling + processed[10] = digit[10]; + + // Process digit 11 - double it + if (digit[11] <= 4'd4) begin + processed[11] = digit[11] << 1; + end else begin + processed[11] = (digit[11] << 1) - 4'd9; + end + + // Process digit 12 - no doubling + processed[12] = digit[12]; + + // Process digit 13 - double it + if (digit[13] <= 4'd4) begin + processed[13] = digit[13] << 1; + end else begin + processed[13] = (digit[13] << 1) - 4'd9; + end + + // Process digit 14 - no doubling + processed[14] = digit[14]; + + // Process digit 15 - double it + if (digit[15] <= 4'd4) begin + processed[15] = digit[15] << 1; + end else begin + processed[15] = (digit[15] << 1) - 4'd9; + end + + // Calculate total sum + total_sum = processed[0] + processed[1] + processed[2] + processed[3] + + processed[4] + processed[5] + processed[6] + processed[7] + + processed[8] + processed[9] + processed[10] + processed[11] + + processed[12] + processed[13] + processed[14] + processed[15]; + + // Valid if sum modulo 10 equals 0 (last digit is 0) + valid = (total_sum % 7'd10) == 7'd0; + end + +endmodule diff --git a/src/tb_luhn_validator.sv b/src/tb_luhn_validator.sv new file mode 100644 index 0000000..a1fd678 --- /dev/null +++ b/src/tb_luhn_validator.sv @@ -0,0 +1,143 @@ +// Testbench for Luhn Algorithm Validator +// Tests the luhn_validator module with sample valid and invalid numbers + +module tb_luhn_validator; + + // Signals for DUT + logic [3:0] digit [15:0]; + logic valid; + + // Instantiate the DUT (Device Under Test) + luhn_validator dut ( + .digit(digit), + .valid(valid) + ); + + // Test stimulus + initial begin + $display("TEST START"); + $display("========================================"); + $display("Luhn Algorithm Validator Testbench"); + $display("========================================"); + + // Test 1: Valid number - 0000000000000018 + // Manual verification: 8 + (1*2) + 0... = 8 + 2 = 10, which is divisible by 10 + $display("\nTest 1: Testing VALID number: 0000-0000-0000-0018"); + digit[0] = 4'd8; // Rightmost digit + digit[1] = 4'd1; + digit[2] = 4'd0; + digit[3] = 4'd0; + digit[4] = 4'd0; + digit[5] = 4'd0; + digit[6] = 4'd0; + digit[7] = 4'd0; + digit[8] = 4'd0; + digit[9] = 4'd0; + digit[10] = 4'd0; + digit[11] = 4'd0; + digit[12] = 4'd0; + digit[13] = 4'd0; + digit[14] = 4'd0; + digit[15] = 4'd0; // Leftmost digit + + #10; // Wait for combinational logic to settle + + $display(" Input: 0000-0000-0000-0018"); + $display(" Expected: valid = 1"); + $display(" Actual: valid = %0d", valid); + + if (valid === 1'b1) begin + $display(" ✓ Test 1 PASSED"); + end else begin + $display("LOG: %0t : ERROR : tb_luhn_validator : dut.valid : expected_value: 1 actual_value: %0d", $time, valid); + $display(" ✗ Test 1 FAILED"); + $display("ERROR"); + $fatal(1, "Test 1 failed - Valid number incorrectly marked as invalid"); + end + + // Test 2: Invalid number - 0000000000000019 + // Manual verification: 9 + (1*2) + 0... = 9 + 2 = 11, NOT divisible by 10 + $display("\nTest 2: Testing INVALID number: 0000-0000-0000-0019"); + digit[0] = 4'd9; // Changed last digit to make it invalid + digit[1] = 4'd1; + digit[2] = 4'd0; + digit[3] = 4'd0; + digit[4] = 4'd0; + digit[5] = 4'd0; + digit[6] = 4'd0; + digit[7] = 4'd0; + digit[8] = 4'd0; + digit[9] = 4'd0; + digit[10] = 4'd0; + digit[11] = 4'd0; + digit[12] = 4'd0; + digit[13] = 4'd0; + digit[14] = 4'd0; + digit[15] = 4'd0; + + #10; // Wait for combinational logic to settle + + $display(" Input: 0000-0000-0000-0019"); + $display(" Expected: valid = 0"); + $display(" Actual: valid = %0d", valid); + + if (valid === 1'b0) begin + $display(" ✓ Test 2 PASSED"); + end else begin + $display("LOG: %0t : ERROR : tb_luhn_validator : dut.valid : expected_value: 0 actual_value: %0d", $time, valid); + $display(" ✗ Test 2 FAILED"); + $display("ERROR"); + $fatal(1, "Test 2 failed - Invalid number incorrectly marked as valid"); + end + + // Test 3: Another valid number - 0000000000000026 + // Manual verification: 6 + (2*2) + 0... = 6 + 4 = 10, divisible by 10 + $display("\nTest 3: Testing VALID number: 0000-0000-0000-0026"); + digit[0] = 4'd6; + digit[1] = 4'd2; + digit[2] = 4'd0; + digit[3] = 4'd0; + digit[4] = 4'd0; + digit[5] = 4'd0; + digit[6] = 4'd0; + digit[7] = 4'd0; + digit[8] = 4'd0; + digit[9] = 4'd0; + digit[10] = 4'd0; + digit[11] = 4'd0; + digit[12] = 4'd0; + digit[13] = 4'd0; + digit[14] = 4'd0; + digit[15] = 4'd0; + + #10; + + $display(" Input: 0000-0000-0000-0026"); + $display(" Expected: valid = 1"); + $display(" Actual: valid = %0d", valid); + + if (valid === 1'b1) begin + $display(" ✓ Test 3 PASSED"); + end else begin + $display("LOG: %0t : ERROR : tb_luhn_validator : dut.valid : expected_value: 1 actual_value: %0d", $time, valid); + $display(" ✗ Test 3 FAILED"); + $display("ERROR"); + $fatal(1, "Test 3 failed - Valid number incorrectly marked as invalid"); + end + + // All tests passed + $display("\n========================================"); + $display("TEST PASSED"); + $display("All 3 tests completed successfully!"); + $display("========================================"); + + $finish; + end + + // Waveform dump + initial begin + $dumpfile("dumpfile.fst"); + $dumpvars(0); + end + +endmodule