commit d094ff3148530d924948ba739c291c0dbe7ad169 Author: Jose Luis Montañes Ojados Date: Sat Feb 28 21:59:55 2026 +0100 first commit diff --git a/adder_nbit/adder_nbit.v b/adder_nbit/adder_nbit.v new file mode 100644 index 0000000..a23c175 --- /dev/null +++ b/adder_nbit/adder_nbit.v @@ -0,0 +1,32 @@ +/* + Adder de N bits +*/ +`include "./full_adder/full_adder.v" + +module adder_nbit #(parameter N = 8)( + input [N-1:0] a, + input [N-1:0] b, + input carry_in, + output [N-1:0] sum, + output carry_out +); + wire [N:0] carry; + + assign carry[0] = carry_in; + + genvar i; + generate + for (i = 0; i < N; i = i + 1) begin: generar_full_adder + full_adder_structural full_adder( + .carry_in(carry[i]), + .a(a[i]), + .b(b[i]), + .sum(sum[i]), + .carry_out(carry[i+1]) + ); + end + endgenerate + + assign carry_out = carry[N]; + +endmodule \ No newline at end of file diff --git a/adder_nbit/adder_nbit.vcd b/adder_nbit/adder_nbit.vcd new file mode 100644 index 0000000..158bad1 --- /dev/null +++ b/adder_nbit/adder_nbit.vcd @@ -0,0 +1,330 @@ +$date + Sat Feb 28 20:27:33 2026 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module adder_nbit_tb $end +$var wire 1 ! carry_out $end +$var wire 8 " sum [7:0] $end +$var reg 8 # a [7:0] $end +$var reg 8 $ b [7:0] $end +$var reg 1 % carry_in $end +$scope module adder_8bit $end +$var wire 8 & a [7:0] $end +$var wire 8 ' b [7:0] $end +$var wire 9 ( carry [8:0] $end +$var wire 1 ) carry_in $end +$var wire 1 ! carry_out $end +$var wire 8 * sum [7:0] $end +$scope begin generar_full_adder[0] $end +$scope module full_adder $end +$var wire 1 + a $end +$var wire 1 , add1_carry $end +$var wire 1 - add1_sum $end +$var wire 1 . add2_carry $end +$var wire 1 / b $end +$var wire 1 0 carry_in $end +$var wire 1 1 carry_out $end +$var wire 1 2 sum $end +$scope module add1 $end +$var wire 1 + a $end +$var wire 1 / b $end +$var wire 1 , carry $end +$var wire 1 - sum $end +$upscope $end +$scope module add2 $end +$var wire 1 - a $end +$var wire 1 0 b $end +$var wire 1 . carry $end +$var wire 1 2 sum $end +$upscope $end +$upscope $end +$upscope $end +$scope begin generar_full_adder[1] $end +$scope module full_adder $end +$var wire 1 3 a $end +$var wire 1 4 add1_carry $end +$var wire 1 5 add1_sum $end +$var wire 1 6 add2_carry $end +$var wire 1 7 b $end +$var wire 1 8 carry_in $end +$var wire 1 9 carry_out $end +$var wire 1 : sum $end +$scope module add1 $end +$var wire 1 3 a $end +$var wire 1 7 b $end +$var wire 1 4 carry $end +$var wire 1 5 sum $end +$upscope $end +$scope module add2 $end +$var wire 1 5 a $end +$var wire 1 8 b $end +$var wire 1 6 carry $end +$var wire 1 : sum $end +$upscope $end +$upscope $end +$upscope $end +$scope begin generar_full_adder[2] $end +$scope module full_adder $end +$var wire 1 ; a $end +$var wire 1 < add1_carry $end +$var wire 1 = add1_sum $end +$var wire 1 > add2_carry $end +$var wire 1 ? b $end +$var wire 1 @ carry_in $end +$var wire 1 A carry_out $end +$var wire 1 B sum $end +$scope module add1 $end +$var wire 1 ; a $end +$var wire 1 ? b $end +$var wire 1 < carry $end +$var wire 1 = sum $end +$upscope $end +$scope module add2 $end +$var wire 1 = a $end +$var wire 1 @ b $end +$var wire 1 > carry $end +$var wire 1 B sum $end +$upscope $end +$upscope $end +$upscope $end +$scope begin generar_full_adder[3] $end +$scope module full_adder $end +$var wire 1 C a $end +$var wire 1 D add1_carry $end +$var wire 1 E add1_sum $end +$var wire 1 F add2_carry $end +$var wire 1 G b $end +$var wire 1 H carry_in $end +$var wire 1 I carry_out $end +$var wire 1 J sum $end +$scope module add1 $end +$var wire 1 C a $end +$var wire 1 G b $end +$var wire 1 D carry $end +$var wire 1 E sum $end +$upscope $end +$scope module add2 $end +$var wire 1 E a $end +$var wire 1 H b $end +$var wire 1 F carry $end +$var wire 1 J sum $end +$upscope $end +$upscope $end +$upscope $end +$scope begin generar_full_adder[4] $end +$scope module full_adder $end +$var wire 1 K a $end +$var wire 1 L add1_carry $end +$var wire 1 M add1_sum $end +$var wire 1 N add2_carry $end +$var wire 1 O b $end +$var wire 1 P carry_in $end +$var wire 1 Q carry_out $end +$var wire 1 R sum $end +$scope module add1 $end +$var wire 1 K a $end +$var wire 1 O b $end +$var wire 1 L carry $end +$var wire 1 M sum $end +$upscope $end +$scope module add2 $end +$var wire 1 M a $end +$var wire 1 P b $end +$var wire 1 N carry $end +$var wire 1 R sum $end +$upscope $end +$upscope $end +$upscope $end +$scope begin generar_full_adder[5] $end +$scope module full_adder $end +$var wire 1 S a $end +$var wire 1 T add1_carry $end +$var wire 1 U add1_sum $end +$var wire 1 V add2_carry $end +$var wire 1 W b $end +$var wire 1 X carry_in $end +$var wire 1 Y carry_out $end +$var wire 1 Z sum $end +$scope module add1 $end +$var wire 1 S a $end +$var wire 1 W b $end +$var wire 1 T carry $end +$var wire 1 U sum $end +$upscope $end +$scope module add2 $end +$var wire 1 U a $end +$var wire 1 X b $end +$var wire 1 V carry $end +$var wire 1 Z sum $end +$upscope $end +$upscope $end +$upscope $end +$scope begin generar_full_adder[6] $end +$scope module full_adder $end +$var wire 1 [ a $end +$var wire 1 \ add1_carry $end +$var wire 1 ] add1_sum $end +$var wire 1 ^ add2_carry $end +$var wire 1 _ b $end +$var wire 1 ` carry_in $end +$var wire 1 a carry_out $end +$var wire 1 b sum $end +$scope module add1 $end +$var wire 1 [ a $end +$var wire 1 _ b $end +$var wire 1 \ carry $end +$var wire 1 ] sum $end +$upscope $end +$scope module add2 $end +$var wire 1 ] a $end +$var wire 1 ` b $end +$var wire 1 ^ carry $end +$var wire 1 b sum $end +$upscope $end +$upscope $end +$upscope $end +$scope begin generar_full_adder[7] $end +$scope module full_adder $end +$var wire 1 c a $end +$var wire 1 d add1_carry $end +$var wire 1 e add1_sum $end +$var wire 1 f add2_carry $end +$var wire 1 g b $end +$var wire 1 h carry_in $end +$var wire 1 i carry_out $end +$var wire 1 j sum $end +$scope module add1 $end +$var wire 1 c a $end +$var wire 1 g b $end +$var wire 1 d carry $end +$var wire 1 e sum $end +$upscope $end +$scope module add2 $end +$var wire 1 e a $end +$var wire 1 h b $end +$var wire 1 f carry $end +$var wire 1 j sum $end +$upscope $end +$upscope $end +$upscope $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +0j +0i +0h +0g +0f +0e +0d +0c +0b +0a +0` +0_ +0^ +0] +0\ +0[ +0Z +0Y +0X +0W +0V +0U +0T +0S +0R +0Q +0P +0O +0N +0M +0L +0K +0J +0I +0H +0G +0F +0E +0D +0C +1B +0A +0@ +1? +0> +1= +0< +0; +0: +09 +08 +07 +06 +05 +04 +03 +12 +01 +00 +1/ +0. +1- +0, +0+ +b101 * +0) +b0 ( +b101 ' +b0 & +0% +b101 $ +b0 # +b101 " +0! +$end +#1 +1: +1J +b1111 " +b1111 * +15 +1E +13 +1C +b1010 # +b1010 & +#2 +1H +0: +0B +1A +b1000 ( +1J +1Z +1b +b1101001 " +b1101001 * +05 +0= +1< +0E +1U +1] +03 +1; +0C +1S +1[ +b1100100 # +b1100100 & +#3 diff --git a/adder_nbit/adder_nbit.vvp b/adder_nbit/adder_nbit.vvp new file mode 100644 index 0000000..48c5948 --- /dev/null +++ b/adder_nbit/adder_nbit.vvp @@ -0,0 +1,421 @@ +#! /c/iverilog/bin/vvp +:ivl_version "0.9.7 " "(v0_9_7)"; +:vpi_time_precision + 0; +:vpi_module "system"; +:vpi_module "v2005_math"; +:vpi_module "va_math"; +S_0118C068 .scope module, "adder_nbit_tb" "adder_nbit_tb" 2 3; + .timescale 0 0; +v011CE8B0_0 .var "a", 7 0; +v011CE3E0_0 .var "b", 7 0; +v011CE750_0 .var "carry_in", 0 0; +v011CE800_0 .net "carry_out", 0 0, L_011D03D8; 1 drivers +RS_0119B434/0/0 .resolv tri, L_011CEDD8, L_011CED80, L_011D0010, L_011CF880; +RS_0119B434/0/4 .resolv tri, L_011CF720, L_011CFFB8, L_011CFAE8, L_011D00C0; +RS_0119B434 .resolv tri, RS_0119B434/0/0, RS_0119B434/0/4, C4, C4; +v011CE7A8_0 .net8 "sum", 7 0, RS_0119B434; 8 drivers +S_0118BE48 .scope module, "adder_8bit" "adder_nbit" 2 10, 3 6, S_0118C068; + .timescale 0 0; +P_01190EEC .param/l "N" 3 6, +C4<01000>; +L_011D0B48 .functor BUFZ 1, v011CE750_0, C4<0>, C4<0>, C4<0>; +v011CE540_0 .net *"_s59", 0 0, L_011D0B48; 1 drivers +v011CE6F8_0 .net "a", 7 0, v011CE8B0_0; 1 drivers +v011CE438_0 .net "b", 7 0, v011CE3E0_0; 1 drivers +RS_0119B3EC/0/0 .resolv tri, L_011CEAC0, L_011CFCA0, L_011CF930, L_011CF8D8; +RS_0119B3EC/0/4 .resolv tri, L_011CF9E0, L_011CFB98, L_011CFB40, L_011CFEB0; +RS_0119B3EC/0/8 .resolv tri, L_011CF7D0, C4, C4, C4; +RS_0119B3EC .resolv tri, RS_0119B3EC/0/0, RS_0119B3EC/0/4, RS_0119B3EC/0/8, C4; +v011CE070_0 .net8 "carry", 8 0, RS_0119B3EC; 9 drivers +v011CE2D8_0 .net "carry_in", 0 0, v011CE750_0; 1 drivers +v011CE858_0 .alias "carry_out", 0 0, v011CE800_0; +v011CE120_0 .alias "sum", 7 0, v011CE7A8_0; +L_011CED28 .part RS_0119B3EC, 0, 1; +L_011CEBC8 .part v011CE8B0_0, 0, 1; +L_011CEB70 .part v011CE3E0_0, 0, 1; +L_011CEDD8 .part/pv L_011CDAF8, 0, 1, 8; +L_011CEAC0 .part/pv L_011CDA88, 1, 1, 9; +L_011CEC20 .part RS_0119B3EC, 1, 1; +L_011CE960 .part v011CE8B0_0, 1, 1; +L_011CEC78 .part v011CE3E0_0, 1, 1; +L_011CED80 .part/pv L_011CF060, 1, 1, 8; +L_011CFCA0 .part/pv L_011CEED8, 2, 1, 9; +L_011CF828 .part RS_0119B3EC, 2, 1; +L_011CFCF8 .part v011CE8B0_0, 2, 1; +L_011CFF08 .part v011CE3E0_0, 2, 1; +L_011D0010 .part/pv L_011CF140, 2, 1, 8; +L_011CF930 .part/pv L_011CEEA0, 3, 1, 9; +L_011CF988 .part RS_0119B3EC, 3, 1; +L_011CFDA8 .part v011CE8B0_0, 3, 1; +L_011D0068 .part v011CE3E0_0, 3, 1; +L_011CF880 .part/pv L_011CEE68, 3, 1, 8; +L_011CF8D8 .part/pv L_011CF0D0, 4, 1, 9; +L_011CFD50 .part RS_0119B3EC, 4, 1; +L_011CFC48 .part v011CE8B0_0, 4, 1; +L_011CF670 .part v011CE3E0_0, 4, 1; +L_011CF720 .part/pv L_011CEFF0, 4, 1, 8; +L_011CF9E0 .part/pv L_011CDC80, 5, 1, 9; +L_011CFA38 .part RS_0119B3EC, 5, 1; +L_011CF778 .part v011CE8B0_0, 5, 1; +L_011CFA90 .part v011CE3E0_0, 5, 1; +L_011CFFB8 .part/pv L_011CEF80, 5, 1, 8; +L_011CFB98 .part/pv L_011D0918, 6, 1, 9; +L_011CFF60 .part RS_0119B3EC, 6, 1; +L_011CFE00 .part v011CE8B0_0, 6, 1; +L_011CF6C8 .part v011CE3E0_0, 6, 1; +L_011CFAE8 .part/pv L_011D0AD8, 6, 1, 8; +L_011CFB40 .part/pv L_011D0B80, 7, 1, 9; +L_011CFBF0 .part RS_0119B3EC, 7, 1; +L_011D0118 .part v011CE8B0_0, 7, 1; +L_011CFE58 .part v011CE3E0_0, 7, 1; +L_011D00C0 .part/pv L_011D07C8, 7, 1, 8; +L_011CFEB0 .part/pv L_011D0870, 8, 1, 9; +L_011CF7D0 .part/pv L_011D0B48, 0, 1, 9; +L_011D03D8 .part RS_0119B3EC, 8, 1; +S_0118A908 .scope generate, "generar_full_adder[0]" "generar_full_adder[0]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_011910EC .param/l "i" 3 19, +C4<00>; +S_0118AF68 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118A908; + .timescale 0 0; +L_011CDA88 .functor OR 1, L_011CDC48, L_011CDBD8, C4<0>, C4<0>; +v011CD708_0 .net "a", 0 0, L_011CEBC8; 1 drivers +v011CD7B8_0 .net "add1_carry", 0 0, L_011CDC48; 1 drivers +v011CD760_0 .net "add1_sum", 0 0, L_011CDD98; 1 drivers +v011CD868_0 .net "add2_carry", 0 0, L_011CDBD8; 1 drivers +v011CD8C0_0 .net "b", 0 0, L_011CEB70; 1 drivers +v011CE0C8_0 .net "carry_in", 0 0, L_011CED28; 1 drivers +v011CE018_0 .net "carry_out", 0 0, L_011CDA88; 1 drivers +v011CDEB8_0 .net "sum", 0 0, L_011CDAF8; 1 drivers +S_0118AB28 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118AF68; + .timescale 0 0; +L_011CDD98 .functor XOR 1, L_011CEBC8, L_011CEB70, C4<0>, C4<0>; +L_011CDC48 .functor AND 1, L_011CEBC8, L_011CEB70, C4<1>, C4<1>; +v011CD9C8_0 .alias "a", 0 0, v011CD708_0; +v011CD658_0 .alias "b", 0 0, v011CD8C0_0; +v011CD810_0 .alias "carry", 0 0, v011CD7B8_0; +v011CD6B0_0 .alias "sum", 0 0, v011CD760_0; +S_0118B650 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118AF68; + .timescale 0 0; +L_011CDAF8 .functor XOR 1, L_011CDD98, L_011CED28, C4<0>, C4<0>; +L_011CDBD8 .functor AND 1, L_011CDD98, L_011CED28, C4<1>, C4<1>; +v011CD550_0 .alias "a", 0 0, v011CD760_0; +v011CD5A8_0 .alias "b", 0 0, v011CE0C8_0; +v011CD918_0 .alias "carry", 0 0, v011CD868_0; +v011CD600_0 .alias "sum", 0 0, v011CDEB8_0; +S_0118B4B8 .scope generate, "generar_full_adder[1]" "generar_full_adder[1]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_011910CC .param/l "i" 3 19, +C4<01>; +S_0118AEE0 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118B4B8; + .timescale 0 0; +L_011CEED8 .functor OR 1, L_011CF3A8, L_011CF3E0, C4<0>, C4<0>; +v011CD398_0 .net "a", 0 0, L_011CE960; 1 drivers +v011CD3F0_0 .net "add1_carry", 0 0, L_011CF3A8; 1 drivers +v011CD4F8_0 .net "add1_sum", 0 0, L_011CDB68; 1 drivers +v011CCAA8_0 .net "add2_carry", 0 0, L_011CF3E0; 1 drivers +v011CCB00_0 .net "b", 0 0, L_011CEC78; 1 drivers +v011CCB58_0 .net "carry_in", 0 0, L_011CEC20; 1 drivers +v011CCBB0_0 .net "carry_out", 0 0, L_011CEED8; 1 drivers +v011CD970_0 .net "sum", 0 0, L_011CF060; 1 drivers +S_0118B7E8 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118AEE0; + .timescale 0 0; +L_011CDB68 .functor XOR 1, L_011CE960, L_011CEC78, C4<0>, C4<0>; +L_011CF3A8 .functor AND 1, L_011CE960, L_011CEC78, C4<1>, C4<1>; +v011CCA50_0 .alias "a", 0 0, v011CD398_0; +v011CD238_0 .alias "b", 0 0, v011CCB00_0; +v011CD290_0 .alias "carry", 0 0, v011CD3F0_0; +v011CCE70_0 .alias "sum", 0 0, v011CD4F8_0; +S_0118B320 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118AEE0; + .timescale 0 0; +L_011CF060 .functor XOR 1, L_011CDB68, L_011CEC20, C4<0>, C4<0>; +L_011CF3E0 .functor AND 1, L_011CDB68, L_011CEC20, C4<1>, C4<1>; +v011CCDC0_0 .alias "a", 0 0, v011CD4F8_0; +v011CCE18_0 .alias "b", 0 0, v011CCB58_0; +v011CCFD0_0 .alias "carry", 0 0, v011CCAA8_0; +v011CD1E0_0 .alias "sum", 0 0, v011CD970_0; +S_0118B298 .scope generate, "generar_full_adder[2]" "generar_full_adder[2]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_0119130C .param/l "i" 3 19, +C4<010>; +S_0118AA18 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118B298; + .timescale 0 0; +L_011CEEA0 .functor OR 1, L_011CEF48, L_011CF290, C4<0>, C4<0>; +v011CD448_0 .net "a", 0 0, L_011CFCF8; 1 drivers +v011CCCB8_0 .net "add1_carry", 0 0, L_011CEF48; 1 drivers +v011CD4A0_0 .net "add1_sum", 0 0, L_011CF098; 1 drivers +v011CCD10_0 .net "add2_carry", 0 0, L_011CF290; 1 drivers +v011CCF78_0 .net "b", 0 0, L_011CFF08; 1 drivers +v011CD080_0 .net "carry_in", 0 0, L_011CF828; 1 drivers +v011CD188_0 .net "carry_out", 0 0, L_011CEEA0; 1 drivers +v011CCD68_0 .net "sum", 0 0, L_011CF140; 1 drivers +S_0118B980 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118AA18; + .timescale 0 0; +L_011CF098 .functor XOR 1, L_011CFCF8, L_011CFF08, C4<0>, C4<0>; +L_011CEF48 .functor AND 1, L_011CFCF8, L_011CFF08, C4<1>, C4<1>; +v011CD2E8_0 .alias "a", 0 0, v011CD448_0; +v011CD028_0 .alias "b", 0 0, v011CCF78_0; +v011CCC60_0 .alias "carry", 0 0, v011CCCB8_0; +v011CCEC8_0 .alias "sum", 0 0, v011CD4A0_0; +S_0118B6D8 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118AA18; + .timescale 0 0; +L_011CF140 .functor XOR 1, L_011CF098, L_011CF828, C4<0>, C4<0>; +L_011CF290 .functor AND 1, L_011CF098, L_011CF828, C4<1>, C4<1>; +v011CD340_0 .alias "a", 0 0, v011CD4A0_0; +v011CD130_0 .alias "b", 0 0, v011CD080_0; +v011CCC08_0 .alias "carry", 0 0, v011CCD10_0; +v011CD0D8_0 .alias "sum", 0 0, v011CCD68_0; +S_0118AE58 .scope generate, "generar_full_adder[3]" "generar_full_adder[3]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_011913AC .param/l "i" 3 19, +C4<011>; +S_0118B188 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118AE58; + .timescale 0 0; +L_011CF0D0 .functor OR 1, L_011CF450, L_011CEFB8, C4<0>, C4<0>; +v011CC6A8_0 .net "a", 0 0, L_011CFDA8; 1 drivers +v011CC7B0_0 .net "add1_carry", 0 0, L_011CF450; 1 drivers +v011CC700_0 .net "add1_sum", 0 0, L_011CF1E8; 1 drivers +v011CC808_0 .net "add2_carry", 0 0, L_011CEFB8; 1 drivers +v011CC860_0 .net "b", 0 0, L_011D0068; 1 drivers +v011CC8B8_0 .net "carry_in", 0 0, L_011CF988; 1 drivers +v011CC910_0 .net "carry_out", 0 0, L_011CF0D0; 1 drivers +v011CCF20_0 .net "sum", 0 0, L_011CEE68; 1 drivers +S_0118ABB0 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118B188; + .timescale 0 0; +L_011CF1E8 .functor XOR 1, L_011CFDA8, L_011D0068, C4<0>, C4<0>; +L_011CF450 .functor AND 1, L_011CFDA8, L_011D0068, C4<1>, C4<1>; +v011CC5A0_0 .alias "a", 0 0, v011CC6A8_0; +v011CC5F8_0 .alias "b", 0 0, v011CC860_0; +v011CC650_0 .alias "carry", 0 0, v011CC7B0_0; +v011CC9C0_0 .alias "sum", 0 0, v011CC700_0; +S_0118B210 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118B188; + .timescale 0 0; +L_011CEE68 .functor XOR 1, L_011CF1E8, L_011CF988, C4<0>, C4<0>; +L_011CEFB8 .functor AND 1, L_011CF1E8, L_011CF988, C4<1>, C4<1>; +v011CC1D8_0 .alias "a", 0 0, v011CC700_0; +v011CC758_0 .alias "b", 0 0, v011CC8B8_0; +v011CC968_0 .alias "carry", 0 0, v011CC808_0; +v011CC548_0 .alias "sum", 0 0, v011CCF20_0; +S_0118BED0 .scope generate, "generar_full_adder[4]" "generar_full_adder[4]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_011912EC .param/l "i" 3 19, +C4<0100>; +S_0118BF58 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118BED0; + .timescale 0 0; +L_011CDC80 .functor OR 1, L_011CF338, L_011CF5D8, C4<0>, C4<0>; +v011CC440_0 .net "a", 0 0, L_011CFC48; 1 drivers +v011CC128_0 .net "add1_carry", 0 0, L_011CF338; 1 drivers +v011CC4F0_0 .net "add1_sum", 0 0, L_011CF2C8; 1 drivers +v011CC180_0 .net "add2_carry", 0 0, L_011CF5D8; 1 drivers +v011CBE10_0 .net "b", 0 0, L_011CF670; 1 drivers +v011CBA48_0 .net "carry_in", 0 0, L_011CFD50; 1 drivers +v011CBEC0_0 .net "carry_out", 0 0, L_011CDC80; 1 drivers +v011CBF18_0 .net "sum", 0 0, L_011CEFF0; 1 drivers +S_0118B100 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118BF58; + .timescale 0 0; +L_011CF2C8 .functor XOR 1, L_011CFC48, L_011CF670, C4<0>, C4<0>; +L_011CF338 .functor AND 1, L_011CFC48, L_011CF670, C4<1>, C4<1>; +v011CBCB0_0 .alias "a", 0 0, v011CC440_0; +v011CC338_0 .alias "b", 0 0, v011CBE10_0; +v011CC0D0_0 .alias "carry", 0 0, v011CC128_0; +v011CBDB8_0 .alias "sum", 0 0, v011CC4F0_0; +S_0118BFE0 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118BF58; + .timescale 0 0; +L_011CEFF0 .functor XOR 1, L_011CF2C8, L_011CFD50, C4<0>, C4<0>; +L_011CF5D8 .functor AND 1, L_011CF2C8, L_011CFD50, C4<1>, C4<1>; +v011CC078_0 .alias "a", 0 0, v011CC4F0_0; +v011CBC58_0 .alias "b", 0 0, v011CBA48_0; +v011CC230_0 .alias "carry", 0 0, v011CC180_0; +v011CBBA8_0 .alias "sum", 0 0, v011CBF18_0; +S_0118C7D8 .scope generate, "generar_full_adder[5]" "generar_full_adder[5]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_01190CAC .param/l "i" 3 19, +C4<0101>; +S_0118C4A8 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118C7D8; + .timescale 0 0; +L_011D0918 .functor OR 1, L_011CDAC0, L_011D0C60, C4<0>, C4<0>; +v011CBB50_0 .net "a", 0 0, L_011CF778; 1 drivers +v011CC3E8_0 .net "add1_carry", 0 0, L_011CDAC0; 1 drivers +v011CBD08_0 .net "add1_sum", 0 0, L_011CDD28; 1 drivers +v011CBFC8_0 .net "add2_carry", 0 0, L_011D0C60; 1 drivers +v011CC390_0 .net "b", 0 0, L_011CFA90; 1 drivers +v011CBD60_0 .net "carry_in", 0 0, L_011CFA38; 1 drivers +v011CC020_0 .net "carry_out", 0 0, L_011D0918; 1 drivers +v011CC2E0_0 .net "sum", 0 0, L_011CEF80; 1 drivers +S_0118BD38 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118C4A8; + .timescale 0 0; +L_011CDD28 .functor XOR 1, L_011CF778, L_011CFA90, C4<0>, C4<0>; +L_011CDAC0 .functor AND 1, L_011CF778, L_011CFA90, C4<1>, C4<1>; +v011CBC00_0 .alias "a", 0 0, v011CBB50_0; +v011CC288_0 .alias "b", 0 0, v011CC390_0; +v011CBE68_0 .alias "carry", 0 0, v011CC3E8_0; +v011CBAF8_0 .alias "sum", 0 0, v011CBD08_0; +S_0118BB18 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118C4A8; + .timescale 0 0; +L_011CEF80 .functor XOR 1, L_011CDD28, L_011CFA38, C4<0>, C4<0>; +L_011D0C60 .functor AND 1, L_011CDD28, L_011CFA38, C4<1>, C4<1>; +v01196AC0_0 .alias "a", 0 0, v011CBD08_0; +v011CBF70_0 .alias "b", 0 0, v011CBD60_0; +v011CC498_0 .alias "carry", 0 0, v011CBFC8_0; +v011CBAA0_0 .alias "sum", 0 0, v011CC2E0_0; +S_0118BCB0 .scope generate, "generar_full_adder[6]" "generar_full_adder[6]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_01190C4C .param/l "i" 3 19, +C4<0110>; +S_0118C640 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118BCB0; + .timescale 0 0; +L_011D0B80 .functor OR 1, L_011D0988, L_011D0B10, C4<0>, C4<0>; +v01196490_0 .net "a", 0 0, L_011CFE00; 1 drivers +v011964E8_0 .net "add1_carry", 0 0, L_011D0988; 1 drivers +v011969B8_0 .net "add1_sum", 0 0, L_011D08A8; 1 drivers +v01196540_0 .net "add2_carry", 0 0, L_011D0B10; 1 drivers +v011966F8_0 .net "b", 0 0, L_011CF6C8; 1 drivers +v011968B0_0 .net "carry_in", 0 0, L_011CFF60; 1 drivers +v01196908_0 .net "carry_out", 0 0, L_011D0B80; 1 drivers +v01196A68_0 .net "sum", 0 0, L_011D0AD8; 1 drivers +S_0118BA08 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118C640; + .timescale 0 0; +L_011D08A8 .functor XOR 1, L_011CFE00, L_011CF6C8, C4<0>, C4<0>; +L_011D0988 .functor AND 1, L_011CFE00, L_011CF6C8, C4<1>, C4<1>; +v01196120_0 .alias "a", 0 0, v01196490_0; +v011963E0_0 .alias "b", 0 0, v011966F8_0; +v01196858_0 .alias "carry", 0 0, v011964E8_0; +v01196438_0 .alias "sum", 0 0, v011969B8_0; +S_0118C6C8 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118C640; + .timescale 0 0; +L_011D0AD8 .functor XOR 1, L_011D08A8, L_011CFF60, C4<0>, C4<0>; +L_011D0B10 .functor AND 1, L_011D08A8, L_011CFF60, C4<1>, C4<1>; +v01196750_0 .alias "a", 0 0, v011969B8_0; +v01196330_0 .alias "b", 0 0, v011968B0_0; +v01196A10_0 .alias "carry", 0 0, v01196540_0; +v01196070_0 .alias "sum", 0 0, v01196A68_0; +S_0118C0F0 .scope generate, "generar_full_adder[7]" "generar_full_adder[7]" 3 19, 3 19, S_0118BE48; + .timescale 0 0; +P_01190EAC .param/l "i" 3 19, +C4<0111>; +S_0118C398 .scope module, "full_adder" "full_adder_structural" 3 20, 4 16, S_0118C0F0; + .timescale 0 0; +L_011D0870 .functor OR 1, L_011D0790, L_011D0BF0, C4<0>, C4<0>; +v011960C8_0 .net "a", 0 0, L_011D0118; 1 drivers +v01196388_0 .net "add1_carry", 0 0, L_011D0790; 1 drivers +v011965F0_0 .net "add1_sum", 0 0, L_011D0BB8; 1 drivers +v011961D0_0 .net "add2_carry", 0 0, L_011D0BF0; 1 drivers +v01196018_0 .net "b", 0 0, L_011CFE58; 1 drivers +v01196598_0 .net "carry_in", 0 0, L_011CFBF0; 1 drivers +v01196800_0 .net "carry_out", 0 0, L_011D0870; 1 drivers +v011966A0_0 .net "sum", 0 0, L_011D07C8; 1 drivers +S_0118C178 .scope module, "add1" "half_adder" 4 23, 5 5, S_0118C398; + .timescale 0 0; +L_011D0BB8 .functor XOR 1, L_011D0118, L_011CFE58, C4<0>, C4<0>; +L_011D0790 .functor AND 1, L_011D0118, L_011CFE58, C4<1>, C4<1>; +v011962D8_0 .alias "a", 0 0, v011960C8_0; +v011967A8_0 .alias "b", 0 0, v01196018_0; +v01196228_0 .alias "carry", 0 0, v01196388_0; +v01196648_0 .alias "sum", 0 0, v011965F0_0; +S_0118C420 .scope module, "add2" "half_adder" 4 24, 5 5, S_0118C398; + .timescale 0 0; +L_011D07C8 .functor XOR 1, L_011D0BB8, L_011CFBF0, C4<0>, C4<0>; +L_011D0BF0 .functor AND 1, L_011D0BB8, L_011CFBF0, C4<1>, C4<1>; +v01196BC8_0 .alias "a", 0 0, v011965F0_0; +v01196960_0 .alias "b", 0 0, v01196598_0; +v01196280_0 .alias "carry", 0 0, v011961D0_0; +v01196178_0 .alias "sum", 0 0, v011966A0_0; +S_0118BDC0 .scope module, "full_adder_behavioral" "full_adder_behavioral" 4 37; + .timescale 0 0; +v011CE908_0 .net "a", 0 0, C4; 0 drivers +v011CE178_0 .net "b", 0 0, C4; 0 drivers +v011CE1D0_0 .net "carry_in", 0 0, C4; 0 drivers +v011CE228_0 .var "carry_out", 0 0; +v011CE490_0 .var "sum", 0 0; +E_01190788 .event edge, v011CE908_0, v011CE178_0, v011CE1D0_0; +S_0118C530 .scope module, "full_adder_dataflow" "full_adder_dataflow" 4 29; + .timescale 0 0; +L_011D09F8 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_011D0A30 .functor XOR 1, L_011D09F8, C4, C4<0>, C4<0>; +L_011D06B0 .functor AND 1, C4, C4, C4<1>, C4<1>; +L_011D0DB0 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_011D0D78 .functor AND 1, C4, L_011D0DB0, C4<1>, C4<1>; +L_011CDA50 .functor OR 1, L_011D06B0, L_011D0D78, C4<0>, C4<0>; +v011CE4E8_0 .net *"_s0", 0 0, L_011D09F8; 1 drivers +v011CDE60_0 .net *"_s4", 0 0, L_011D06B0; 1 drivers +v011CE280_0 .net *"_s6", 0 0, L_011D0DB0; 1 drivers +v011CE388_0 .net *"_s8", 0 0, L_011D0D78; 1 drivers +v011CE598_0 .net "a", 0 0, C4; 0 drivers +v011CE5F0_0 .net "b", 0 0, C4; 0 drivers +v011CDF10_0 .net "carry_in", 0 0, C4; 0 drivers +v011CDF68_0 .net "carry_out", 0 0, L_011CDA50; 1 drivers +v011CE330_0 .net "sum", 0 0, L_011D0A30; 1 drivers +S_0118C310 .scope module, "half_adder_behavioral" "half_adder_behavioral" 5 21; + .timescale 0 0; +v011CDFC0_0 .net "a", 0 0, C4; 0 drivers +v011CE648_0 .net "b", 0 0, C4; 0 drivers +v011CE6A0_0 .var "carry", 0 0; +v011CEA10_0 .var "sum", 0 0; +E_011907C8 .event edge, v011CE648_0, v011CDFC0_0; +S_0118C5B8 .scope module, "half_adder_dataflow" "half_adder_dataflow" 5 13; + .timescale 0 0; +L_011D0EB8 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_011D0EF0 .functor AND 1, C4, C4, C4<1>, C4<1>; +v011CECD0_0 .net "a", 0 0, C4; 0 drivers +v011CEB18_0 .net "b", 0 0, C4; 0 drivers +v011CE9B8_0 .net "carry", 0 0, L_011D0EF0; 1 drivers +v011CEA68_0 .net "sum", 0 0, L_011D0EB8; 1 drivers + .scope S_0118C068; +T_0 ; + %vpi_call 2 19 "$dumpfile", "./adder_nbit/adder_nbit.vcd"; + %vpi_call 2 20 "$dumpvars", 1'sb0, S_0118C068; + %set/v v011CE8B0_0, 0, 8; + %movi 8, 5, 8; + %set/v v011CE3E0_0, 8, 8; + %set/v v011CE750_0, 0, 1; + %delay 1, 0; + %vpi_call 2 24 "$display", "a=%d, b=%d, sum=%d, carry=%b", v011CE8B0_0, v011CE3E0_0, v011CE7A8_0, v011CE800_0; + %movi 8, 10, 8; + %set/v v011CE8B0_0, 8, 8; + %movi 8, 5, 8; + %set/v v011CE3E0_0, 8, 8; + %set/v v011CE750_0, 0, 1; + %delay 1, 0; + %vpi_call 2 27 "$display", "a=%d, b=%d, sum=%d, carry=%b", v011CE8B0_0, v011CE3E0_0, v011CE7A8_0, v011CE800_0; + %movi 8, 100, 8; + %set/v v011CE8B0_0, 8, 8; + %movi 8, 5, 8; + %set/v v011CE3E0_0, 8, 8; + %set/v v011CE750_0, 0, 1; + %delay 1, 0; + %vpi_call 2 30 "$display", "a=%d, b=%d, sum=%d, carry=%b", v011CE8B0_0, v011CE3E0_0, v011CE7A8_0, v011CE800_0; + %end; + .thread T_0; + .scope S_0118BDC0; +T_1 ; + %wait E_01190788; + %load/v 8, v011CE908_0, 1; + %load/v 9, v011CE178_0, 1; + %xor 8, 9, 1; + %load/v 9, v011CE1D0_0, 1; + %xor 8, 9, 1; + %set/v v011CE490_0, 8, 1; + %load/v 8, v011CE908_0, 1; + %load/v 9, v011CE178_0, 1; + %and 8, 9, 1; + %load/v 9, v011CE1D0_0, 1; + %load/v 10, v011CE908_0, 1; + %load/v 11, v011CE178_0, 1; + %xor 10, 11, 1; + %and 9, 10, 1; + %or 8, 9, 1; + %set/v v011CE228_0, 8, 1; + %jmp T_1; + .thread T_1, $push; + .scope S_0118C310; +T_2 ; + %wait E_011907C8; + %load/v 8, v011CDFC0_0, 1; + %load/v 9, v011CE648_0, 1; + %xor 8, 9, 1; + %set/v v011CEA10_0, 8, 1; + %load/v 8, v011CDFC0_0, 1; + %load/v 9, v011CE648_0, 1; + %and 8, 9, 1; + %set/v v011CE6A0_0, 8, 1; + %jmp T_2; + .thread T_2, $push; +# The file index is used to find the file name in the following table. +:file_names 6; + "N/A"; + ""; + ".\adder_nbit\adder_nbit_tb.v"; + "././adder_nbit/adder_nbit.v"; + "././full_adder/full_adder.v"; + "././half_adder/half_adder.v"; diff --git a/adder_nbit/adder_nbit_tb.v b/adder_nbit/adder_nbit_tb.v new file mode 100644 index 0000000..561b84f --- /dev/null +++ b/adder_nbit/adder_nbit_tb.v @@ -0,0 +1,34 @@ +`include "./adder_nbit/adder_nbit.v" + +module adder_nbit_tb; + reg [7:0] a, b; + reg carry_in; + + wire [7:0] sum; + wire carry_out; + + adder_nbit adder_8bit( + .a(a), + .b(b), + .carry_in(carry_in), + .sum(sum), + .carry_out(carry_out) + ); + + initial begin + $dumpfile("./adder_nbit/adder_nbit.vcd"); + $dumpvars(0, adder_nbit_tb); + + a = 0; b = 5; carry_in = 0; + #1 + $display("a=%d, b=%d, sum=%d, carry=%b", a, b, sum, carry_out); + a = 10; b = 5; carry_in = 0; + #1 + $display("a=%d, b=%d, sum=%d, carry=%b", a, b, sum, carry_out); + a = 100; b = 5; carry_in = 0; + #1 + $display("a=%d, b=%d, sum=%d, carry=%b", a, b, sum, carry_out); + + end + +endmodule \ No newline at end of file diff --git a/alu_basic/alu_basic.v b/alu_basic/alu_basic.v new file mode 100644 index 0000000..324e03c --- /dev/null +++ b/alu_basic/alu_basic.v @@ -0,0 +1,56 @@ +/* + Basic ALU 16bit + + inputs: opcode, a, b + outputs: result, zero, carry, negative + + opcode[3:0] | Operación + ------------------------------- + 0x0 | ADD + 0x1 | SUB + 0x2 | MUL + 0x3 | DIV + 0x4 | AND + 0x5 | OR + 0x6 | NOT + 0x7 | NAND + 0x8 | NOR + 0x9 | XOR + 0xA | XNOR + 0xB | NEG +*/ + +module basic_alu ( + input [3:0] opcode, + input [15:0] a, + input [15:0] b, + output reg [15:0] result, + output zero, + output reg carry, + output negative +); + + always @(*) begin + carry = 0; + + case (opcode) + 4'h0: {carry, result} = a + b; // ADD + 4'h1: {carry, result} = a - b; // SUB + 4'h2: result = a * b; // MUL + 4'h3: result = a / b; // DIV + 4'h4: result = a & b; // AND + 4'h5: result = a | b; // OR + 4'h6: result = ~a; // NOT + 4'h7: result = ~(a & b); // NAND + 4'h8: result = ~(a | b); // NOR + 4'h9: result = a ^ b; // XOR + 4'hA: result = ~(a ^ b); // XNOR + 4'hB: result = ~a + 1; // NEG + default: result = 0; + endcase + end + + assign zero = result == 0; + assign negative = result[15]; + +endmodule \ No newline at end of file diff --git a/alu_basic/alu_basic.vcd b/alu_basic/alu_basic.vcd new file mode 100644 index 0000000..1874a80 --- /dev/null +++ b/alu_basic/alu_basic.vcd @@ -0,0 +1,133 @@ +$date + Sat Feb 28 21:00:53 2026 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module basic_alu_tb $end +$var wire 1 ! carry $end +$var wire 1 " negative $end +$var wire 16 # result [15:0] $end +$var wire 1 $ zero $end +$var reg 16 % a [15:0] $end +$var reg 16 & b [15:0] $end +$var reg 4 ' opcode [3:0] $end +$scope module alu $end +$var wire 16 ( a [15:0] $end +$var wire 16 ) b [15:0] $end +$var wire 1 " negative $end +$var wire 4 * opcode [3:0] $end +$var wire 1 $ zero $end +$var reg 1 + carry $end +$var reg 16 , result [15:0] $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +b11001 , +0+ +b0 * +b101 ) +b10100 ( +b0 ' +b101 & +b10100 % +0$ +b11001 # +0" +0! +$end +#1 +b1111 , +b1111 # +b1 ' +b1 * +#2 +1+ +1! +b0 , +1$ +b0 # +b1 & +b1 ) +b1111111111111111 % +b1111111111111111 ( +b0 ' +b0 * +#3 +1" +b1111111111110001 , +0$ +b1111111111110001 # +1+ +1! +b10100 & +b10100 ) +b101 % +b101 ( +b1 ' +b1 * +#4 +0" +b111110100 , +b111110100 # +0+ +0! +b101 & +b101 ) +b1100100 % +b1100100 ( +b10 ' +b10 * +#5 +b10100 , +b10100 # +b11 ' +b11 * +#6 +b111100000000 , +b111100000000 # +b111111110000 & +b111111110000 ) +b1111111100000000 % +b1111111100000000 ( +b100 ' +b100 * +#7 +1" +b1111111111110000 , +b1111111111110000 # +b101 ' +b101 * +#8 +b1111111111111111 , +b1111111111111111 # +b0 & +b0 ) +b0 % +b0 ( +b110 ' +b110 * +#9 +b1111000011110000 , +b1111000011110000 # +b111111110000 & +b111111110000 ) +b1111111100000000 % +b1111111100000000 ( +b1001 ' +b1001 * +#10 +b1111111111111111 , +b1111111111111111 # +b0 & +b0 ) +b1 % +b1 ( +b1011 ' +b1011 * +#11 diff --git a/alu_basic/alu_basic.vvp b/alu_basic/alu_basic.vvp new file mode 100644 index 0000000..158d6b6 --- /dev/null +++ b/alu_basic/alu_basic.vvp @@ -0,0 +1,240 @@ +#! /c/iverilog/bin/vvp +:ivl_version "0.9.7 " "(v0_9_7)"; +:vpi_time_precision + 0; +:vpi_module "system"; +:vpi_module "v2005_math"; +:vpi_module "va_math"; +S_01049710 .scope module, "basic_alu_tb" "basic_alu_tb" 2 3; + .timescale 0 0; +v0104CEA0_0 .var "a", 15 0; +v0104CEF8_0 .var "b", 15 0; +v01080FC0_0 .net "carry", 0 0, v01041578_0; 1 drivers +v010811D0_0 .net "negative", 0 0, L_010810C8; 1 drivers +v01081070_0 .var "opcode", 3 0; +v01080D58_0 .net "result", 15 0, v0104CDF0_0; 1 drivers +v01081438_0 .net "zero", 0 0, L_01081018; 1 drivers +S_01049BD8 .scope module, "alu" "basic_alu" 2 10, 3 23, S_01049710; + .timescale 0 0; +v01045228_0 .net *"_s0", 16 0, L_010813E0; 1 drivers +v01045280_0 .net *"_s3", 0 0, C4<0>; 1 drivers +v010452D8_0 .net *"_s4", 16 0, C4<00000000000000000>; 1 drivers +v010414C8_0 .net "a", 15 0, v0104CEA0_0; 1 drivers +v01041520_0 .net "b", 15 0, v0104CEF8_0; 1 drivers +v01041578_0 .var "carry", 0 0; +v0104CD40_0 .alias "negative", 0 0, v010811D0_0; +v0104CD98_0 .net "opcode", 3 0, v01081070_0; 1 drivers +v0104CDF0_0 .var "result", 15 0; +v0104CE48_0 .alias "zero", 0 0, v01081438_0; +E_01072788 .event edge, v0104CD98_0, v010414C8_0, v01041520_0; +L_010813E0 .concat [ 16 1 0 0], v0104CDF0_0, C4<0>; +L_01081018 .cmp/eq 17, L_010813E0, C4<00000000000000000>; +L_010810C8 .part v0104CDF0_0, 15, 1; + .scope S_01049BD8; +T_0 ; + %wait E_01072788; + %set/v v01041578_0, 0, 1; + %load/v 8, v0104CD98_0, 4; + %cmpi/u 8, 0, 4; + %jmp/1 T_0.0, 6; + %cmpi/u 8, 1, 4; + %jmp/1 T_0.1, 6; + %cmpi/u 8, 2, 4; + %jmp/1 T_0.2, 6; + %cmpi/u 8, 3, 4; + %jmp/1 T_0.3, 6; + %cmpi/u 8, 4, 4; + %jmp/1 T_0.4, 6; + %cmpi/u 8, 5, 4; + %jmp/1 T_0.5, 6; + %cmpi/u 8, 6, 4; + %jmp/1 T_0.6, 6; + %cmpi/u 8, 7, 4; + %jmp/1 T_0.7, 6; + %cmpi/u 8, 8, 4; + %jmp/1 T_0.8, 6; + %cmpi/u 8, 9, 4; + %jmp/1 T_0.9, 6; + %cmpi/u 8, 10, 4; + %jmp/1 T_0.10, 6; + %cmpi/u 8, 11, 4; + %jmp/1 T_0.11, 6; + %set/v v0104CDF0_0, 0, 16; + %jmp T_0.13; +T_0.0 ; + %load/v 8, v010414C8_0, 16; + %mov 24, 0, 1; + %load/v 25, v01041520_0, 16; + %mov 41, 0, 1; + %add 8, 25, 17; + %set/v v0104CDF0_0, 8, 16; + %set/v v01041578_0, 24, 1; + %jmp T_0.13; +T_0.1 ; + %load/v 8, v010414C8_0, 16; + %mov 24, 0, 1; + %load/v 25, v01041520_0, 16; + %mov 41, 0, 1; + %sub 8, 25, 17; + %set/v v0104CDF0_0, 8, 16; + %set/v v01041578_0, 24, 1; + %jmp T_0.13; +T_0.2 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %mul 8, 24, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.3 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %div 8, 24, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.4 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %and 8, 24, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.5 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %or 8, 24, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.6 ; + %load/v 8, v010414C8_0, 16; + %inv 8, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.7 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %and 8, 24, 16; + %inv 8, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.8 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %or 8, 24, 16; + %inv 8, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.9 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %xor 8, 24, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.10 ; + %load/v 8, v010414C8_0, 16; + %load/v 24, v01041520_0, 16; + %xor 8, 24, 16; + %inv 8, 16; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.11 ; + %load/v 8, v010414C8_0, 16; + %mov 24, 0, 16; + %inv 8, 32; + %addi 8, 1, 32; + %set/v v0104CDF0_0, 8, 16; + %jmp T_0.13; +T_0.13 ; + %jmp T_0; + .thread T_0, $push; + .scope S_01049710; +T_1 ; + %vpi_call 2 21 "$dumpfile", "./alu_basic/alu_basic.vcd"; + %vpi_call 2 22 "$dumpvars", 1'sb0, S_01049710; + %set/v v01081070_0, 0, 4; + %movi 8, 20, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 5, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 26 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 1, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 20, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 5, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 29 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %set/v v01081070_0, 0, 4; + %set/v v0104CEA0_0, 1, 16; + %movi 8, 1, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 34 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 1, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 5, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 20, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 39 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 2, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 100, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 5, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 44 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 3, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 100, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 5, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 49 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 4, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 65280, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 4080, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 54 "$display", "opcode=%h, a=%h, b=%h, result=%h, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 5, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 65280, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 4080, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 59 "$display", "opcode=%h, a=%h, b=%h, result=%h, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 6, 4; + %set/v v01081070_0, 8, 4; + %set/v v0104CEA0_0, 0, 16; + %set/v v0104CEF8_0, 0, 16; + %delay 1, 0; + %vpi_call 2 64 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 9, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 65280, 16; + %set/v v0104CEA0_0, 8, 16; + %movi 8, 4080, 16; + %set/v v0104CEF8_0, 8, 16; + %delay 1, 0; + %vpi_call 2 69 "$display", "opcode=%h, a=%h, b=%h, result=%h, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %movi 8, 11, 4; + %set/v v01081070_0, 8, 4; + %movi 8, 1, 16; + %set/v v0104CEA0_0, 8, 16; + %set/v v0104CEF8_0, 0, 16; + %delay 1, 0; + %vpi_call 2 74 "$display", "opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", v01081070_0, v0104CEA0_0, v0104CEF8_0, v01080D58_0, v01081438_0, v01080FC0_0, v010811D0_0; + %end; + .thread T_1; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + ".\alu_basic\alu_basic_tb.v"; + "././alu_basic/alu_basic.v"; diff --git a/alu_basic/alu_basic_tb.v b/alu_basic/alu_basic_tb.v new file mode 100644 index 0000000..4644450 --- /dev/null +++ b/alu_basic/alu_basic_tb.v @@ -0,0 +1,77 @@ +`include "./alu_basic/alu_basic.v" + +module basic_alu_tb; + reg [15:0] a, b; + reg [3:0] opcode; + + wire [15:0] result; + wire zero, carry, negative; + + basic_alu alu( + .opcode(opcode), + .a(a), + .b(b), + .result(result), + .zero(zero), + .carry(carry), + .negative(negative) + ); + + initial begin + $dumpfile("./alu_basic/alu_basic.vcd"); + $dumpvars(0, basic_alu_tb); + + opcode = 4'h0; a = 20; b = 5; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + opcode = 4'h1; a = 20; b = 5; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // ADD con overflow: 65535 + 1 = 0, carry=1, zero=1 + opcode = 4'h0; a = 16'hFFFF; b = 1; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // SUB con negativo: 5 - 20, negative=1 + opcode = 4'h1; a = 5; b = 20; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // MUL: 100 * 5 = 500 + opcode = 4'h2; a = 100; b = 5; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // DIV: 100 / 5 = 20 + opcode = 4'h3; a = 100; b = 5; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // AND: 0xFF00 & 0x0FF0 = 0x0F00 + opcode = 4'h4; a = 16'hFF00; b = 16'h0FF0; + #1 + $display("opcode=%h, a=%h, b=%h, result=%h, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // OR: 0xFF00 | 0x0FF0 = 0xFFF0 + opcode = 4'h5; a = 16'hFF00; b = 16'h0FF0; + #1 + $display("opcode=%h, a=%h, b=%h, result=%h, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // NOT: ~0 = 65535 + opcode = 4'h6; a = 0; b = 0; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // XOR: 0xFF00 ^ 0x0FF0 = 0xF0F0 + opcode = 4'h9; a = 16'hFF00; b = 16'h0FF0; + #1 + $display("opcode=%h, a=%h, b=%h, result=%h, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + + // NEG: -1 en complemento a 2 = 65535 + opcode = 4'hB; a = 1; b = 0; + #1 + $display("opcode=%d, a=%d, b=%d, result=%d, zero=%b, carry=%b, negative=%b", opcode, a, b, result, zero, carry, negative); + end + +endmodule \ No newline at end of file diff --git a/full_adder/full_adder.v b/full_adder/full_adder.v new file mode 100644 index 0000000..114b78e --- /dev/null +++ b/full_adder/full_adder.v @@ -0,0 +1,45 @@ +/* + Full Adder Declaration + + A B Cin | Sum Cout + 0 0 0 | 0 0 + 0 0 1 | 1 0 + 0 1 0 | 1 0 + 0 1 1 | 0 1 + 1 0 0 | 1 0 + 1 0 1 | 0 1 + 1 1 0 | 0 1 + 1 1 1 | 1 1 +*/ +`include "./half_adder/half_adder.v" + +module full_adder_structural (carry_in, a, b, sum, carry_out); + input carry_in, a, b; + output sum, carry_out; + + wire add1_sum, add1_carry; + wire add2_carry; + + half_adder add1(a, b, add1_sum, add1_carry); + half_adder add2(add1_sum, carry_in, sum, add2_carry); + + or final_or(carry_out, add1_carry, add2_carry); +endmodule + +module full_adder_dataflow (carry_in, a, b, sum, carry_out); + input carry_in, a, b; + output sum, carry_out; + + assign sum = a ^ b ^ carry_in; + assign carry_out = (a & b) | (carry_in & (a ^ b)); +endmodule + +module full_adder_behavioral (carry_in, a, b, sum, carry_out); + input carry_in, a, b; + output reg sum, carry_out; + + always @(*) begin + sum = a ^ b ^ carry_in; + carry_out = (a & b) | (carry_in & (a ^ b)); + end +endmodule \ No newline at end of file diff --git a/full_adder/full_adder.vcd b/full_adder/full_adder.vcd new file mode 100644 index 0000000..feb13a9 --- /dev/null +++ b/full_adder/full_adder.vcd @@ -0,0 +1,69 @@ +$date + Sat Feb 28 20:25:22 2026 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module full_adder_tb $end +$var wire 1 ! carry_out $end +$var wire 1 " sum $end +$var reg 1 # a $end +$var reg 1 $ b $end +$var reg 1 % carry_in $end +$scope module full_adder $end +$var wire 1 & a $end +$var wire 1 ' b $end +$var wire 1 ( carry_in $end +$var reg 1 ) carry_out $end +$var reg 1 * sum $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +0* +0) +0( +0' +0& +0% +0$ +0# +0" +0! +$end +#1 +1* +1" +1% +1( +#2 +0* +0" +0% +0( +#3 +1* +1" +1# +1& +#4 +1) +1! +0* +0" +1% +1( +#5 +0% +0( +1$ +1' +#6 +1* +1" +1% +1( diff --git a/full_adder/full_adder.vvp b/full_adder/full_adder.vvp new file mode 100644 index 0000000..e134b63 --- /dev/null +++ b/full_adder/full_adder.vvp @@ -0,0 +1,154 @@ +#! /c/iverilog/bin/vvp +:ivl_version "0.9.7 " "(v0_9_7)"; +:vpi_time_precision + 0; +:vpi_module "system"; +:vpi_module "v2005_math"; +:vpi_module "va_math"; +S_01022BC0 .scope module, "full_adder_dataflow" "full_adder_dataflow" 2 29; + .timescale 0 0; +L_000ED8B8 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_000ED8F0 .functor XOR 1, L_000ED8B8, C4, C4<0>, C4<0>; +L_0105BC40 .functor AND 1, C4, C4, C4<1>, C4<1>; +L_0105BE00 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_0105BFC0 .functor AND 1, C4, L_0105BE00, C4<1>, C4<1>; +L_0105BC78 .functor OR 1, L_0105BC40, L_0105BFC0, C4<0>, C4<0>; +v000ED828_0 .net *"_s0", 0 0, L_000ED8B8; 1 drivers +v01030E00_0 .net *"_s4", 0 0, L_0105BC40; 1 drivers +v01031278_0 .net *"_s6", 0 0, L_0105BE00; 1 drivers +v01030FB8_0 .net *"_s8", 0 0, L_0105BFC0; 1 drivers +v01030F60_0 .net "a", 0 0, C4; 0 drivers +v01030CF8_0 .net "b", 0 0, C4; 0 drivers +v01030E58_0 .net "carry_in", 0 0, C4; 0 drivers +v010311C8_0 .net "carry_out", 0 0, L_0105BC78; 1 drivers +v01030D50_0 .net "sum", 0 0, L_000ED8F0; 1 drivers +S_01023220 .scope module, "full_adder_structural" "full_adder_structural" 2 16; + .timescale 0 0; +L_0105C2F0 .functor OR 1, L_0105BD90, L_0105C750, C4<0>, C4<0>; +v01031068_0 .net "a", 0 0, C4; 0 drivers +v01031430_0 .net "add1_carry", 0 0, L_0105BD90; 1 drivers +v01031118_0 .net "add1_sum", 0 0, L_0105BCB0; 1 drivers +v01031170_0 .net "add2_carry", 0 0, L_0105C750; 1 drivers +v01030DA8_0 .net "b", 0 0, C4; 0 drivers +v01030F08_0 .net "carry_in", 0 0, C4; 0 drivers +v0105B3D0_0 .net "carry_out", 0 0, L_0105C2F0; 1 drivers +v0105B270_0 .net "sum", 0 0, L_0105BF88; 1 drivers +S_01022AB0 .scope module, "add1" "half_adder" 2 23, 3 5, S_01023220; + .timescale 0 0; +L_0105BCB0 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_0105BD90 .functor AND 1, C4, C4, C4<1>, C4<1>; +v010312D0_0 .alias "a", 0 0, v01031068_0; +v01030EB0_0 .alias "b", 0 0, v01030DA8_0; +v01031328_0 .alias "carry", 0 0, v01031430_0; +v01031380_0 .alias "sum", 0 0, v01031118_0; +S_01023660 .scope module, "add2" "half_adder" 2 24, 3 5, S_01023220; + .timescale 0 0; +L_0105BF88 .functor XOR 1, L_0105BCB0, C4, C4<0>, C4<0>; +L_0105C750 .functor AND 1, L_0105BCB0, C4, C4<1>, C4<1>; +v01031010_0 .alias "a", 0 0, v01031118_0; +v010313D8_0 .alias "b", 0 0, v01030F08_0; +v01031220_0 .alias "carry", 0 0, v01031170_0; +v010310C0_0 .alias "sum", 0 0, v0105B270_0; +S_010234C8 .scope module, "full_adder_tb" "full_adder_tb" 4 6; + .timescale 0 0; +v0105B588_0 .var "a", 0 0; +v0105B2C8_0 .var "b", 0 0; +v0105B320_0 .var "carry_in", 0 0; +v0105B1C0_0 .net "carry_out", 0 0, v0105B110_0; 1 drivers +v0105B638_0 .net "sum", 0 0, v0105ADA0_0; 1 drivers +S_010229A0 .scope module, "full_adder" "full_adder_behavioral" 4 10, 2 37, S_010234C8; + .timescale 0 0; +v0105B218_0 .net "a", 0 0, v0105B588_0; 1 drivers +v0105B5E0_0 .net "b", 0 0, v0105B2C8_0; 1 drivers +v0105B008_0 .net "carry_in", 0 0, v0105B320_0; 1 drivers +v0105B110_0 .var "carry_out", 0 0; +v0105ADA0_0 .var "sum", 0 0; +E_01023A48 .event edge, v0105B218_0, v0105B5E0_0, v0105B008_0; +S_01022EF0 .scope module, "half_adder_behavioral" "half_adder_behavioral" 3 21; + .timescale 0 0; +v0105AC98_0 .net "a", 0 0, C4; 0 drivers +v0105B060_0 .net "b", 0 0, C4; 0 drivers +v0105ACF0_0 .var "carry", 0 0; +v0105B428_0 .var "sum", 0 0; +E_01023B28 .event edge, v0105B060_0, v0105AC98_0; +S_010232A8 .scope module, "half_adder_dataflow" "half_adder_dataflow" 3 13; + .timescale 0 0; +L_0105C1A0 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_0105C1D8 .functor AND 1, C4, C4, C4<1>, C4<1>; +v0105B530_0 .net "a", 0 0, C4; 0 drivers +v0105B378_0 .net "b", 0 0, C4; 0 drivers +v0105AC40_0 .net "carry", 0 0, L_0105C1D8; 1 drivers +v0105ADF8_0 .net "sum", 0 0, L_0105C1A0; 1 drivers + .scope S_010229A0; +T_0 ; + %wait E_01023A48; + %load/v 8, v0105B218_0, 1; + %load/v 9, v0105B5E0_0, 1; + %xor 8, 9, 1; + %load/v 9, v0105B008_0, 1; + %xor 8, 9, 1; + %set/v v0105ADA0_0, 8, 1; + %load/v 8, v0105B218_0, 1; + %load/v 9, v0105B5E0_0, 1; + %and 8, 9, 1; + %load/v 9, v0105B008_0, 1; + %load/v 10, v0105B218_0, 1; + %load/v 11, v0105B5E0_0, 1; + %xor 10, 11, 1; + %and 9, 10, 1; + %or 8, 9, 1; + %set/v v0105B110_0, 8, 1; + %jmp T_0; + .thread T_0, $push; + .scope S_010234C8; +T_1 ; + %vpi_call 4 19 "$dumpfile", "./full_adder/full_adder.vcd"; + %vpi_call 4 20 "$dumpvars", 1'sb0, S_010234C8; + %set/v v0105B588_0, 0, 1; + %set/v v0105B2C8_0, 0, 1; + %set/v v0105B320_0, 0, 1; + %delay 1, 0; + %set/v v0105B588_0, 0, 1; + %set/v v0105B2C8_0, 0, 1; + %set/v v0105B320_0, 1, 1; + %delay 1, 0; + %set/v v0105B588_0, 0, 1; + %set/v v0105B2C8_0, 0, 1; + %set/v v0105B320_0, 0, 1; + %delay 1, 0; + %set/v v0105B588_0, 1, 1; + %set/v v0105B2C8_0, 0, 1; + %set/v v0105B320_0, 0, 1; + %delay 1, 0; + %set/v v0105B588_0, 1, 1; + %set/v v0105B2C8_0, 0, 1; + %set/v v0105B320_0, 1, 1; + %delay 1, 0; + %set/v v0105B588_0, 1, 1; + %set/v v0105B2C8_0, 1, 1; + %set/v v0105B320_0, 0, 1; + %delay 1, 0; + %set/v v0105B588_0, 1, 1; + %set/v v0105B2C8_0, 1, 1; + %set/v v0105B320_0, 1, 1; + %end; + .thread T_1; + .scope S_01022EF0; +T_2 ; + %wait E_01023B28; + %load/v 8, v0105AC98_0, 1; + %load/v 9, v0105B060_0, 1; + %xor 8, 9, 1; + %set/v v0105B428_0, 8, 1; + %load/v 8, v0105AC98_0, 1; + %load/v 9, v0105B060_0, 1; + %and 8, 9, 1; + %set/v v0105ACF0_0, 8, 1; + %jmp T_2; + .thread T_2, $push; +# The file index is used to find the file name in the following table. +:file_names 5; + "N/A"; + ""; + "././full_adder/full_adder.v"; + "././half_adder/half_adder.v"; + ".\full_adder\full_adder_tb.v"; diff --git a/full_adder/full_adder_tb.v b/full_adder/full_adder_tb.v new file mode 100644 index 0000000..c0962ed --- /dev/null +++ b/full_adder/full_adder_tb.v @@ -0,0 +1,36 @@ +/* + Full Adder testbench +*/ +`include "./full_adder/full_adder.v" + +module full_adder_tb; + reg a, b, carry_in; + wire sum, carry_out; + + full_adder_behavioral full_adder( + .carry_in(carry_in), + .a(a), + .b(b), + .sum(sum), + .carry_out(carry_out) + ); + + initial begin + $dumpfile("./full_adder/full_adder.vcd"); + $dumpvars(0, full_adder_tb); + + a = 0; b = 0; carry_in = 0; + #1 + a = 0; b = 0; carry_in = 1; + #1 + a = 0; b = 0; carry_in = 0; + #1 + a = 1; b = 0; carry_in = 0; + #1 + a = 1; b = 0; carry_in = 1; + #1 + a = 1; b = 1; carry_in = 0; + #1 + a = 1; b = 1; carry_in = 1; + end +endmodule \ No newline at end of file diff --git a/half_adder/half_adder.v b/half_adder/half_adder.v new file mode 100644 index 0000000..9a45d14 --- /dev/null +++ b/half_adder/half_adder.v @@ -0,0 +1,30 @@ +/* + Half Adder Declaration +*/ + +module half_adder (a,b,sum,carry); + input a,b; + output sum, carry; + + xor x1(sum, a, b); + and a1(carry, a, b); +endmodule + +module half_adder_dataflow (a, b, sum, carry); + input a, b; + output sum, carry; + + assign sum = a ^ b; + assign carry = a & b; +endmodule + +module half_adder_behavioral (a, b, sum, carry); + input a, b; + output reg sum, carry; + + always @(a or b) begin + sum = a ^ b; + carry = a & b; + end +endmodule + \ No newline at end of file diff --git a/half_adder/half_adder.vcd b/half_adder/half_adder.vcd new file mode 100644 index 0000000..06aa4ca --- /dev/null +++ b/half_adder/half_adder.vcd @@ -0,0 +1,51 @@ +$date + Sat Feb 28 20:27:18 2026 +$end +$version + Icarus Verilog +$end +$timescale + 1s +$end +$scope module half_adder_tb $end +$var wire 1 ! carry $end +$var wire 1 " sum $end +$var reg 1 # a $end +$var reg 1 $ b $end +$scope module add1 $end +$var wire 1 % a $end +$var wire 1 & b $end +$var wire 1 ! carry $end +$var wire 1 " sum $end +$upscope $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +0& +0% +0$ +0# +0" +0! +$end +#1 +1" +1$ +1& +#2 +0$ +0& +1# +1% +#3 +0" +1! +1$ +1& +#4 +0! +0$ +0& +0# +0% diff --git a/half_adder/half_adder.vvp b/half_adder/half_adder.vvp new file mode 100644 index 0000000..e6695be --- /dev/null +++ b/half_adder/half_adder.vvp @@ -0,0 +1,74 @@ +#! /c/iverilog/bin/vvp +:ivl_version "0.9.7 " "(v0_9_7)"; +:vpi_time_precision + 0; +:vpi_module "system"; +:vpi_module "v2005_math"; +:vpi_module "va_math"; +S_00119918 .scope module, "half_adder_behavioral" "half_adder_behavioral" 2 21; + .timescale 0 0; +v0011E700_0 .net "a", 0 0, C4; 0 drivers +v0011CF80_0 .net "b", 0 0, C4; 0 drivers +v0011E758_0 .var "carry", 0 0; +v0011E7B0_0 .var "sum", 0 0; +E_0011A260 .event edge, v0011CF80_0, v0011E700_0; +S_001191A8 .scope module, "half_adder_dataflow" "half_adder_dataflow" 2 13; + .timescale 0 0; +L_001115D0 .functor XOR 1, C4, C4, C4<0>, C4<0>; +L_0011D930 .functor AND 1, C4, C4, C4<1>, C4<1>; +v0011D828_0 .net "a", 0 0, C4; 0 drivers +v0011D880_0 .net "b", 0 0, C4; 0 drivers +v0011D8D8_0 .net "carry", 0 0, L_0011D930; 1 drivers +v001114C8_0 .net "sum", 0 0, L_001115D0; 1 drivers +S_001199A0 .scope module, "half_adder_tb" "half_adder_tb" 3 6; + .timescale 0 0; +v01030A60_0 .var "a", 0 0; +v01030A08_0 .var "b", 0 0; +v01030900_0 .net "carry", 0 0, L_01031290; 1 drivers +v01030E80_0 .net "sum", 0 0, L_0011D490; 1 drivers +S_001194D8 .scope module, "add1" "half_adder" 3 10, 2 5, S_001199A0; + .timescale 0 0; +L_0011D490 .functor XOR 1, v01030A60_0, v01030A08_0, C4<0>, C4<0>; +L_01031290 .functor AND 1, v01030A60_0, v01030A08_0, C4<1>, C4<1>; +v00111520_0 .net "a", 0 0, v01030A60_0; 1 drivers +v00111578_0 .net "b", 0 0, v01030A08_0; 1 drivers +v0011D400_0 .alias "carry", 0 0, v01030900_0; +v01031038_0 .alias "sum", 0 0, v01030E80_0; + .scope S_00119918; +T_0 ; + %wait E_0011A260; + %load/v 8, v0011E700_0, 1; + %load/v 9, v0011CF80_0, 1; + %xor 8, 9, 1; + %set/v v0011E7B0_0, 8, 1; + %load/v 8, v0011E700_0, 1; + %load/v 9, v0011CF80_0, 1; + %and 8, 9, 1; + %set/v v0011E758_0, 8, 1; + %jmp T_0; + .thread T_0, $push; + .scope S_001199A0; +T_1 ; + %vpi_call 3 13 "$dumpfile", "./half_adder/half_adder.vcd"; + %vpi_call 3 14 "$dumpvars", 1'sb0, S_001199A0; + %set/v v01030A60_0, 0, 1; + %set/v v01030A08_0, 0, 1; + %delay 1, 0; + %set/v v01030A60_0, 0, 1; + %set/v v01030A08_0, 1, 1; + %delay 1, 0; + %set/v v01030A60_0, 1, 1; + %set/v v01030A08_0, 0, 1; + %delay 1, 0; + %set/v v01030A60_0, 1, 1; + %set/v v01030A08_0, 1, 1; + %delay 1, 0; + %set/v v01030A60_0, 0, 1; + %set/v v01030A08_0, 0, 1; + %end; + .thread T_1; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + "././half_adder/half_adder.v"; + ".\half_adder\half_adder_tb.v"; diff --git a/half_adder/half_adder_tb.v b/half_adder/half_adder_tb.v new file mode 100644 index 0000000..1d1873d --- /dev/null +++ b/half_adder/half_adder_tb.v @@ -0,0 +1,26 @@ +/* + Testbench for half_adder +*/ +`include "./half_adder/half_adder.v" + +module half_adder_tb; + reg a, b; + wire sum, carry; + + half_adder add1(a, b, sum, carry); + + initial begin + $dumpfile("./half_adder/half_adder.vcd"); + $dumpvars(0, half_adder_tb); + + a = 0; b = 0; + #1 + a = 0; b = 1; + #1 + a = 1; b = 0; + #1 + a = 1; b = 1; + #1 + a = 0; b = 0; + end +endmodule \ No newline at end of file diff --git a/half_adder/half_adder_tb.vvp b/half_adder/half_adder_tb.vvp new file mode 100644 index 0000000..0c73eaf --- /dev/null +++ b/half_adder/half_adder_tb.vvp @@ -0,0 +1,46 @@ +#! /c/iverilog/bin/vvp +:ivl_version "0.9.7 " "(v0_9_7)"; +:vpi_time_precision + 0; +:vpi_module "system"; +:vpi_module "v2005_math"; +:vpi_module "va_math"; +S_0122D488 .scope module, "half_adder_tb" "half_adder_tb" 2 6; + .timescale 0 0; +v01225348_0 .var "a", 0 0; +v012253A0_0 .var "b", 0 0; +v012253F8_0 .net "carry", 0 0, L_0122C4C0; 1 drivers +v01225450_0 .net "sum", 0 0, L_0122D510; 1 drivers +S_01221390 .scope module, "add1" "half_adder" 2 10, 3 5, S_0122D488; + .timescale 0 0; +L_0122D510 .functor XOR 1, v01225348_0, v012253A0_0, C4<0>, C4<0>; +L_0122C4C0 .functor AND 1, v01225348_0, v012253A0_0, C4<1>, C4<1>; +v01221418_0 .net "a", 0 0, v01225348_0; 1 drivers +v01226F88_0 .net "b", 0 0, v012253A0_0; 1 drivers +v01221470_0 .alias "carry", 0 0, v012253F8_0; +v012252F0_0 .alias "sum", 0 0, v01225450_0; + .scope S_0122D488; +T_0 ; + %vpi_call 2 13 "$dumpfile", "half_adder.vcd"; + %vpi_call 2 14 "$dumpvars", 1'sb0, S_0122D488; + %set/v v01225348_0, 0, 1; + %set/v v012253A0_0, 0, 1; + %delay 1, 0; + %set/v v01225348_0, 0, 1; + %set/v v012253A0_0, 1, 1; + %delay 1, 0; + %set/v v01225348_0, 1, 1; + %set/v v012253A0_0, 0, 1; + %delay 1, 0; + %set/v v01225348_0, 1, 1; + %set/v v012253A0_0, 1, 1; + %delay 1, 0; + %set/v v01225348_0, 0, 1; + %set/v v012253A0_0, 0, 1; + %end; + .thread T_0; +# The file index is used to find the file name in the following table. +:file_names 4; + "N/A"; + ""; + ".\half_adder_tb.v"; + "./half_adder.v"; diff --git a/half_adder/readme.md b/half_adder/readme.md new file mode 100644 index 0000000..644b0f3 --- /dev/null +++ b/half_adder/readme.md @@ -0,0 +1,14 @@ +1. Compilar el testbench +` +iverilog -o .\half_adder_tb.vvp .\half_adder_tb.v +` + +2. Ejecutar simulacion del testbench +` +vvp .\half_adder_tb.vvp +` + +3. Visualizar ondas +` +gtkwave .\half_adder.vcd +` diff --git a/mux_demux/mux_demux.v b/mux_demux/mux_demux.v new file mode 100644 index 0000000..e196646 --- /dev/null +++ b/mux_demux/mux_demux.v @@ -0,0 +1,34 @@ +/* + Mux / Demux + + + Mux + + a b sel | out + ------------------- + 0 0 0 | 0 + 1 0 0 | 1 + 0 1 1 | 1 + 1 0 1 | 0 + ... + +*/ + +module mux_2n1 #(parameter N = 8) ( + input [N-1:0] a, + input [N-1:0] b, + input sel, + output [N-1:0] out +); + assign out = sel ? b : a; +endmodule + +module demux_1n2 #(parameter N = 8) ( + input [N-1:0] in, + input sel, + output [N-1:0] a, + output [N-1:0] b +); + assign a = sel ? 0 : in; + assign b = sel ? in : 0; +endmodule \ No newline at end of file diff --git a/roadmap.md b/roadmap.md new file mode 100644 index 0000000..3e01a2d --- /dev/null +++ b/roadmap.md @@ -0,0 +1,370 @@ +# Verilog Roadmap: De Turing Complete a FPGA + +> Objetivo: traducir tu CPU custom de 16 bits (Turing Complete) a Verilog sintetizable +> y montarla en la Tang Primer 20K (Gowin GW2A). +> +> Prerequisitos que ya tienes: +> - Logica digital (puertas, muxes, flip-flops, FSMs) — via Turing Complete +> - Arquitectura de CPU de 16 bits — tu CPU custom +> - Lenguaje j-lang + compilador para tu CPU +> - Toolchain: iverilog + vvp + gtkwave funcionando +> - Primer ejercicio (half_adder) completado en 3 estilos +> +> Tu CPU (mycpu_v2): +> - 16 registros de 16 bits (REG0-REG11 generales, REG12=RAM_VAL, REG13=RAM_ADDR, +> REG14=PC, REG15=IN/OUT) +> - Instrucciones de 64 bits: [OPCODE:16][PARAM1:16][PARAM2:16][TARGET:16] +> - Modo de direccionamiento en bits 7-6 del opcode (reg/reg, imm/reg, reg/imm, imm/imm) +> - 12 ops ALU (ADD,SUB,MUL,DIV,AND,OR,NOT,NAND,NOR,XOR,XNOR,NEG) +> - 6 condicionales (EQ,NEQ,LS,LSE,GR,GRE) — branch si condicion true +> - Stack: PUSH, POP, RSTR +> - Funciones: CALL, RET, HALT +> - ISA completo en: D:\Proyectos\c-labs\j-lang\mycpu_v2.md +> +> FPGA target: Tang Primer 20K (Gowin GW2A-LV18PG256C8/I7) +> - 20736 LUT4 | 15552 FF | 828K BSRAM | 48 multiplicadores 18x18 +> - 128MB DDR3 | 32Mbit Flash | JTAG+UART debug | 117 IO + +--- + +## Fase 1: Bloques combinacionales fundamentales + +Cosas que ya conoces del juego, ahora las escribes en Verilog. +Cada ejercicio: modulo + testbench + simulacion con gtkwave. + +### 1.1 Full Adder +- **Carpeta:** `full_adder/` +- **Objetivo:** Combinar dos half adders para hacer un full adder (con carry-in) +- **Practica:** Hacerlo structural (instanciando tu half_adder) y dataflow +- **Concepto Verilog:** instanciacion de modulos, jerarquia + +### 1.2 Adder de N bits (ripple carry) +- **Carpeta:** `adder_nbit/` +- **Objetivo:** Sumador parametrizable de N bits usando `generate` y `parameter` +- **Practica:** Parametrizarlo a 4, 8 y 16 bits desde el testbench +- **Concepto Verilog:** `parameter`, `generate for`, buses `[N-1:0]` + +### 1.3 ALU basica +- **Carpeta:** `alu_basic/` +- **Objetivo:** ALU de 16 bits con las 12 operaciones de tu CPU: + ADD, SUB, MUL, DIV, AND, OR, NOT, NAND, NOR, XOR, XNOR, NEG +- **Practica:** Selector de operacion de 4 bits (opcode[3:0]), flags (zero, carry, negative) +- **Concepto Verilog:** `case`, operadores aritmeticos, concatenacion `{}` +- **Conexion directa:** Este modulo es tu `alu.v` final casi tal cual + +### 1.4 Multiplexor y Demultiplexor +- **Carpeta:** `mux_demux/` +- **Objetivo:** Mux 2:1, 4:1 y 8:1 parametrizables. Demux 1:4 +- **Practica:** Mux con `assign` ternario vs `case` vs `generate` +- **Concepto Verilog:** operador ternario `? :`, seleccion por bits + +### 1.5 Decoder / Encoder +- **Carpeta:** `decoder_encoder/` +- **Objetivo:** Decoder 3:8, encoder con prioridad +- **Practica:** Usar `casez` para don't cares +- **Concepto Verilog:** `casez`, `casex`, wildcards + +--- + +## Fase 2: Bloques secuenciales + +Aqui entran los flip-flops y el clock. Es el salto mas importante desde la logica +combinacional. + +### 2.1 Flip-Flop D y registro +- **Carpeta:** `flip_flop/` +- **Objetivo:** FF-D con reset sincrono y asincrono, enable +- **Practica:** Registro de N bits parametrizable +- **Concepto Verilog:** `always @(posedge clk)`, `posedge`/`negedge`, blocking vs + non-blocking (`=` vs `<=`) + +> **CRITICO:** En logica secuencial SIEMPRE usa `<=` (non-blocking). +> En combinacional usa `=` (blocking). Mezclarlos es el error #1 de Verilog. + +### 2.2 Contador +- **Carpeta:** `counter/` +- **Objetivo:** Contador up/down de N bits con enable, load y reset +- **Practica:** Hacerlo parametrizable, probarlo a distintas frecuencias +- **Concepto Verilog:** Aritmetica en always secuencial, overflow + +### 2.3 Shift Register +- **Carpeta:** `shift_register/` +- **Objetivo:** Registro de desplazamiento con carga paralela, shift left/right +- **Practica:** SISO, SIPO, PISO, PIPO +- **Concepto Verilog:** Operadores de shift en contexto secuencial + +### 2.4 Register File +- **Carpeta:** `register_file/` +- **Objetivo:** Banco de 16 registros de 16 bits (como tu CPU: REG0-REG15), + 2 puertos de lectura simultanea, 1 de escritura +- **Practica:** Lectura combinacional, escritura sincrona. Registros especiales + (REG12=RAM_VAL, REG13=RAM_ADDR, REG14=PC, REG15=IO) pueden tener logica extra +- **Concepto Verilog:** Arreglos `reg [15:0] regs [0:15]`, indexado por variable de 4 bits + +--- + +## Fase 3: Memorias + +### 3.1 RAM sincrona +- **Carpeta:** `ram/` +- **Objetivo:** RAM de 256x16 (256 posiciones de 16 bits), lectura/escritura sincrona +- **Practica:** Single port y dual port +- **Concepto Verilog:** Inferencia de block RAM, `$readmemh` para cargar datos iniciales + +### 3.2 ROM +- **Carpeta:** `rom/` +- **Objetivo:** ROM de 256x16 con contenido inicializado desde archivo .hex +- **Practica:** Cargar un programa simple en hex y leerlo secuencialmente +- **Concepto Verilog:** `$readmemh`, `initial begin` +- **Conexion con tu proyecto:** Aqui eventualmente cargaras el binario que genera + tu compilador j-lang + +### 3.3 Stack (LIFO) +- **Carpeta:** `stack/` +- **Objetivo:** Stack de 256 posiciones de 16 bits con PUSH, POP y RSTR (reset) +- **Practica:** Puntero de stack, deteccion de overflow/underflow +- **Conexion directa:** Tu CPU usa PUSH (0x19/0x59), POP (0x1A), RSTR (0x18) + y CALL/RET que tambien usan el stack para guardar/restaurar el PC + +--- + +## Fase 4: Maquinas de estados finitos (FSM) + +Ya las conoces de Turing Complete. Ahora las codificas formalmente. + +### 4.1 FSM basica — Semaforo +- **Carpeta:** `fsm_traffic/` +- **Objetivo:** Semaforo con estados RED, GREEN, YELLOW y temporizador +- **Practica:** FSM con patron de 2 always (estado_actual + logica_siguiente) +- **Concepto Verilog:** `localparam` para estados, el patron clasico de FSM + +### 4.2 FSM — Controlador UART TX (simplificado) +- **Carpeta:** `uart_tx/` +- **Objetivo:** Transmitir un byte por UART (start bit, 8 data, stop bit) +- **Practica:** Baud rate configurable con counter, FSM de transmision +- **Concepto:** FSM real que usaras para debug en FPGA + +--- + +## Fase 5: Pipeline y CPU simples + +Aqui empiezas a armar las piezas en subsistemas tipo CPU. + +### 5.1 Fetch unit +- **Carpeta:** `fetch_unit/` +- **Objetivo:** Program Counter + ROM = fetch de instrucciones +- **Practica:** PC con increment, load (para jumps), reset +- **Conexion:** Este es el primer pedazo real de tu CPU + +### 5.2 Decoder de instrucciones +- **Carpeta:** `instruction_decoder/` +- **Objetivo:** Tomar una instruccion de 64 bits y extraer: + - `opcode[7:0]` — operacion + tipo de grupo + - `opcode[7:6]` — modo de direccionamiento (00=R/R, 01=I/R, 10=R/I, 11=I/I) + - `opcode[5:4]` — grupo (00=ALU, 01=COND, 01=CTRL, 10=FUNC) + - `opcode[3:0]` — operacion dentro del grupo + - `param1[15:0]` — registro o inmediato segun modo + - `param2[15:0]` — registro o inmediato segun modo + - `target[15:0]` — registro destino o direccion de salto +- **Practica:** Generar senales de control: alu_op, reg_write, mem_read, mem_write, + branch, stack_op, is_immediate1, is_immediate2 +- **Conexion:** Mapeo directo del ISA de mycpu_v2 + +### 5.3 CPU single-cycle minima +- **Carpeta:** `cpu_minimal/` +- **Objetivo:** CPU simplificada que ejecuta un subconjunto de tu ISA: + ADD (reg,imm), SUB, AND, OR — EQ, NEQ — PUSH, POP — CALL, RET, HALT +- **Practica:** Conectar fetch + decode + ALU + register file + RAM + stack +- **Concepto:** Datapath + Control Unit, todo single-cycle +- **Nota:** Tu instruccion es de 64 bits (4 words), asi que el fetch necesita + 4 ciclos de lectura de ROM o una ROM con palabra de 64 bits + +### 5.4 Programa de prueba +- **Objetivo:** Escribir a mano un programa en hex que sume numeros del 1 al 10 +- **Practica:** Cargarlo en la ROM con `$readmemh`, simular, verificar resultado +- **Conexion:** Eventualmente esto lo hara tu compilador j-lang automaticamente + +--- + +## Fase 6: TU CPU de Turing Complete en Verilog + +Aqui es donde todo converge. + +### 6.1 Documentar tu ISA (ya tienes mycpu_v2.md — completar) +- **Carpeta:** `tc_cpu/docs/` +- **Base:** Ya tienes mycpu_v2.md con registros, opcodes y modos +- **Que falta agregar para Verilog:** + - Diagrama de bloques del datapath (que se conecta con que) + - Ciclo de ejecucion: fetch (4 words) -> decode -> execute -> writeback + - Como funciona el acceso a RAM (escribir REG13=addr, leer/escribir REG12=data) + - Comportamiento exacto de CALL (push PC al stack, jump) y RET (pop PC del stack) + - Comportamiento de RSTR (reset del stack pointer?) + - Que pasa con flags/condiciones: se compara en el mismo ciclo? + - Senales de I/O via REG15: protocolo? + +### 6.2 Implementar modulos individuales +- **Carpeta:** `tc_cpu/rtl/` +- **Objetivo:** Cada bloque testeado independientemente +- **Modulos concretos de tu CPU:** + + | Modulo | Archivo | Descripcion | + | -------------------- | -------------------- | --------------------------------------------------- | + | ALU | `alu.v` | 12 ops (ADD-NEG), entradas 16bit, flags Z/C/N | + | Register File | `register_file.v` | 16 regs x 16bit, 2 read + 1 write, regs especiales | + | Program Counter | `pc.v` | Increment por 4 words, load para branch/CALL | + | Instruction Memory | `imem.v` | ROM de 64 bits de ancho (o 4 lecturas de 16 bits) | + | Data Memory (RAM) | `dmem.v` | RAM 16 bit, interfaz via REG12/REG13 | + | Stack | `stack.v` | PUSH/POP/RSTR, para datos y CALL/RET | + | Control Unit | `control_unit.v` | Decode opcode[7:0] -> senales de control | + | Mux de operandos | `operand_mux.v` | Selecciona reg o inmediato segun opcode[7:6] | + | Comparador | `comparator.v` | EQ/NEQ/LS/LSE/GR/GRE para branches | + | I/O Controller | `io_controller.v` | Interfaz REG15 con el mundo exterior | + +### 6.3 Integrar el top-level +- **Archivo:** `tc_cpu/rtl/cpu_top.v` +- **Objetivo:** Conectar todos los modulos +- **Ciclo de ejecucion probable (multi-ciclo o FSM):** + 1. **FETCH:** Leer 4 words consecutivos de IMEM -> registro de instruccion de 64 bits + 2. **DECODE:** Extraer opcode, modo, param1, param2, target. Generar senales de control + 3. **EXECUTE:** ALU o comparacion. Resolver operandos (reg/imm mux) + 4. **MEMORY:** Si opcode accede a RAM (via REG12/REG13), hacer read/write + 5. **WRITEBACK:** Escribir resultado en registro target +- **Nota:** Como tus instrucciones son de 64 bits, probablemente sea multi-ciclo + (4 ciclos de fetch + 1-2 de execute). Alternativa: ROM de 64 bits de ancho + +### 6.4 Compilar j-lang -> hex -> simular en tu CPU Verilog +- **Objetivo:** Cerrar el loop completo +- **Flujo:** `codigo.j` -> compilador j-lang -> `.hex` -> `$readmemh` -> simulacion iverilog +- **Test sugerido:** Un programa j-lang simple (fibonacci, factorial, algo con loops) +- **Verificacion:** Comparar traza de ejecucion en gtkwave vs ejecucion en Turing Complete +- **Esto es el momento "wow":** el mismo programa que corria en Turing Complete + ahora corre en tu CPU Verilog + +--- + +## Fase 7: FPGA — Tang Primer 20K + +Tu placa: **Tang Primer 20K** con Gowin GW2A-LV18PG256C8/I7. + +### Recursos de tu FPGA vs lo que necesita tu CPU +``` +Recurso | Disponible | Tu CPU necesita (estimado) +-----------------|---------------|--------------------------- +LUT4 | 20,736 | ~2,000-4,000 (sobra mucho) +Flip-Flops | 15,552 | ~500-1,000 +BSRAM (828Kb) | 46 bloques | ~2-4 bloques (IMEM + DMEM) +Multiplicador | 48 (18x18) | 1 (para MUL de 16 bits) +PLL | 4 | 1 (para generar tu clock) +IO | 117 | ~20-30 (UART, LEDs, botones) +``` +Te sobra FPGA para tu CPU. Podrias meter varias instancias si quisieras. + +### 7.1 Instalar Gowin EDA y primer proyecto +- **Toolchain:** Gowin EDA (Education Edition es gratuita) + - Descarga: https://www.gowinsemi.com (necesitas registro) + - Incluye: Gowin Synthesizer, Place & Route, Programmer +- **Primer proyecto:** Blink LED + - Aprender: crear proyecto, seleccionar chip GW2A-LV18PG256C8/I7 + - Constraints (.cst): asignar pines fisicos a senales + - Clock: la placa tiene un oscilador de 27 MHz, usar PLL para tu frecuencia + - Flujo: Synthesis -> Place & Route -> Generate Bitstream -> Program +- **Dock vs Lite:** Dependiendo de que placa de expansion uses, los pines cambian. + El Dock trae mas LEDs, botones y conectores + +### 7.2 Adaptar tu CPU para sintesis +- **Cambios necesarios:** + - Quitar todo `$display`, `$dumpfile`, `$dumpvars`, `#delays` (solo simulacion) + - IMEM: Usar inicializacion de BSRAM de Gowin (soporta `$readmemh` en sintesis + para block RAM, pero verificar con Gowin Synthesizer) + - DMEM: Inferir BSRAM (el synthesizer lo detecta si sigues el patron correcto) + - MUL: Gowin puede mapear `*` a los multiplicadores DSP hardware automaticamente + - Clock: Usar la PLL Gowin (PLLVR primitive) para generar un clock limpio + - Reset: Usar el boton de la placa como reset global (con debouncing) + +### 7.3 Agregar I/O real +- **Basico (debug):** + - LEDs de la placa -> mostrar estado/registro/flags + - Botones -> reset, step (ejecutar instruccion a instruccion), run + - 7-segmentos (si hay en el dock) -> mostrar PC o valor de registro +- **UART (esencial para debug):** + - Ya la habras hecho en Fase 4.2, conectarla al REG15 (IN/OUT) + - Permite enviar/recibir datos entre PC y tu CPU via terminal serial + - Debug: imprimir valor de registros, estado del PC, etc. +- **Avanzado (futuro):** + - LCD via el conector de 8 pines + - Tarjeta SD para cargar programas sin resintesis + - DDR3 para expandir RAM (requiere controlador DDR3, mas complejo) + +### 7.4 Meta final +- Tu CPU ejecutando un programa compilado con j-lang en hardware real +- Poder cargar programas y ver resultados via UART desde tu PC +- El loop completo: `codigo.j` -> compilador -> `.hex` -> FPGA -> resultados reales + +--- + +## Consejos generales + +### Estructura de cada ejercicio +``` +nombre_ejercicio/ + nombre.v # modulo principal + nombre_tb.v # testbench + readme.md # notas, comandos, que aprendiste +``` + +### Comandos (ya los conoces) +```bash +iverilog -o modulo_tb.vvp modulo_tb.v +vvp modulo_tb.vvp +gtkwave modulo.vcd +``` + +### Errores comunes a evitar +1. **Blocking vs non-blocking:** `=` en combinacional, `<=` en secuencial. Siempre. +2. **Latch inferido:** Si usas `always @(*)` con `if` sin `else`, Verilog infiere un + latch. Siempre pon `else` o valores por defecto. +3. **Sensitivity list incompleta:** Usa `always @(*)` para combinacional, nunca listes + senales manualmente (es error-prone). +4. **Senales no inicializadas en testbench:** Todo `reg` empieza en `x` si no lo + inicializas. +5. **Confusion wire vs reg:** `wire` para assign y conexiones, `reg` para always blocks. + +### Recursos recomendados +- **HDLBits** (hdlbits.01xz.net) — Ejercicios interactivos de Verilog online. + Excelente complemento para practicar sintaxis. +- **"Digital Design and Computer Architecture"** (Harris & Harris) — El libro de + referencia para ir de compuertas a CPU. Tiene ejemplos en Verilog. +- **Nand2Tetris** — Ya hiciste algo similar con Turing Complete, pero el libro tiene + buena formalizacion del ISA y el compilador. + +--- + +## Progreso + +- [x] Fase 1.0 — Half Adder (3 estilos + testbench) +- [x] Fase 1.1 — Full Adder +- [x] Fase 1.2 — Adder N bits +- [x] Fase 1.3 — ALU basica +- [ ] Fase 1.4 — Mux / Demux +- [ ] Fase 1.5 — Decoder / Encoder +- [ ] Fase 2.1 — Flip-Flop D y registro +- [ ] Fase 2.2 — Contador +- [ ] Fase 2.3 — Shift Register +- [ ] Fase 2.4 — Register File +- [ ] Fase 3.1 — RAM sincrona +- [ ] Fase 3.2 — ROM +- [ ] Fase 3.3 — Stack +- [ ] Fase 4.1 — FSM Semaforo +- [ ] Fase 4.2 — UART TX +- [ ] Fase 5.1 — Fetch Unit +- [ ] Fase 5.2 — Decoder de instrucciones +- [ ] Fase 5.3 — CPU single-cycle minima +- [ ] Fase 5.4 — Programa de prueba +- [ ] Fase 6.1 — Documentar ISA de tu CPU +- [ ] Fase 6.2 — Modulos individuales de tu CPU +- [ ] Fase 6.3 — Top-level integrado +- [ ] Fase 6.4 — j-lang -> hex -> simulacion +- [ ] Fase 7.1 — Gowin EDA + blink LED en Tang Primer 20K +- [ ] Fase 7.2 — CPU sintetizable (quitar sim-only, inferir BSRAM, PLL) +- [ ] Fase 7.3 — I/O real (LEDs, botones, UART) +- [ ] Fase 7.4 — j-lang corriendo en hardware real diff --git a/run.ps1 b/run.ps1 new file mode 100644 index 0000000..abef696 --- /dev/null +++ b/run.ps1 @@ -0,0 +1,14 @@ +param( + [Parameter(Mandatory=$true)] + [string]$module +) + +$module = $module.TrimStart('.', '/', '\').TrimEnd('/', '\') + +iverilog -o ".\$module\$module.vvp" ".\$module\${module}_tb.v" +if ($LASTEXITCODE -ne 0) { exit 1 } + +vvp ".\$module\$module.vvp" +if ($LASTEXITCODE -ne 0) { exit 1 } + +gtkwave ".\$module\$module.vcd"