add dice files
diff --git a/info.yaml b/info.yaml
index fef0d8b..e390bc8 100644
--- a/info.yaml
+++ b/info.yaml
@@ -3,8 +3,7 @@
project:
wokwi_id: 0
source_files: # If using an HDL, set wokwi_id as 0 and uncomment and list your source files here
- - verilog/rtl/counter.v
- - verilog/rtl/decoder.v
+ - verilog/rtl/user_module.v
top_module: "user_module" # put the name of your top module here, make it unique by prepending your github username
# As everyone will have access to all designs, try to make it easy for someone new to your design to know what
diff --git a/verilog/rtl/dice.v b/verilog/rtl/dice.v
new file mode 100644
index 0000000..5ee6d59
--- /dev/null
+++ b/verilog/rtl/dice.v
@@ -0,0 +1,20 @@
+// Structural top-level module of dice
+
+timeunit 1ns; timeprecision 10ps;
+
+module dice(
+ input wire Clock, nReset,
+ output wire TL, ML, BL, MC, TR, MR, BR
+);
+ wire [1:0] Ran;
+ wire [2:0] DiceValue;
+
+ random rand1(.Clock(Clock), .nReset(nReset), .Ran(Ran));
+ control cont1(.Clock(Clock), .nReset(nReset), .Ran(Ran), .DiceValue(DiceValue));
+ encoder enc1(.DiceValue(DiceValue),
+ .L11(TL), .L31(TR),
+ .L12(ML), .L22(MC), .L32(MR),
+ .L13(BL), .L33(BR)
+ );
+
+endmodule
diff --git a/verilog/rtl/dice_stim.v b/verilog/rtl/dice_stim.v
new file mode 100644
index 0000000..a029e2f
--- /dev/null
+++ b/verilog/rtl/dice_stim.v
@@ -0,0 +1,69 @@
+// Testbench for dice
+
+timeunit 1ns; timeprecision 10ps;
+
+module dice_stim();
+
+logic Clock, nReset;
+wire TL, TR, ML, MC, MR, BL, BR;
+
+dice dut1(.Clock(Clock), .nReset(nReset),
+ .TL(TL), .TR(TR),
+ .ML(ML), .MC(MC), .MR(MR),
+ .BL(BL), .BR(BR)
+);
+
+// Probe
+task display_signals;
+ $display($time, " %d %d %b %b %b %b %b %b %b ", dut1.Ran, dut1.DiceValue, TL, TR, ML, MC, MR, BL, BR);
+endtask
+
+initial begin
+ $display(" Time Ran DiceValue TL TR ML MC MR BL BR");
+ $display(" ==== ============= ====================");
+ display_signals();
+ forever begin
+ // Print signals every 10 clock cycles
+ #100;
+ display_signals();
+ // Pause the sim
+ `ifndef NOPAUSE
+ $stop();
+ `endif
+ end
+end
+
+// Stimuli
+initial begin
+ nReset = 0;
+ #2 nReset = 1;
+ // If stop is not included, there needs to be something to stop the sim
+ `ifdef NOPAUSE
+ #2400 $finish();
+ `endif
+end
+
+// 100 MHz clock
+always begin
+ Clock = 0;
+ #5 Clock = 1;
+ #5;
+end
+
+// Self-checking every 2 clock cycles
+integer ones, prev_count=0;
+always begin
+ #20;
+ // Check DiceValue matches number of active LEDs
+ // Doesn't check the pattern, but doing so would amount to asserting the inverse of the design
+ ones = $countones({TL, TR, ML, MC, MR, BL, BR});
+ assert (dut1.DiceValue == ones) else $error("DiceValue %d != number of active LEDs (%d)", dut1.DiceValue, ones);
+ // Check that the dice has not stayed on the same side
+ assert (ones != prev_count) else $error("Dice Value did not change in this cycle");
+ //Check for illegal rolls, ie to the opposite side of the dice
+ assert ((ones+prev_count)!= 7) else $error("Rolling from %d to %d not allowed", prev_count, ones);
+ prev_count = ones;
+
+end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/dtype_synth.v b/verilog/rtl/dtype_synth.v
new file mode 100644
index 0000000..efeab9a
--- /dev/null
+++ b/verilog/rtl/dtype_synth.v
@@ -0,0 +1,20 @@
+// structural model of edge triggered D type
+
+module dtype(
+ output logic Q, nQ,
+ input wire D, Clk, nRst
+ );
+
+timeunit 1ns; timeprecision 10ps;
+
+always_ff @(posedge Clk, negedge nRst) begin
+ if(~nRst) begin
+ Q <= 1'b0;
+ nQ <= 1'b1;
+ end else begin
+ Q <= D;
+ nQ <= ~D;
+ end
+end
+
+endmodule
diff --git a/verilog/rtl/encoder.sv b/verilog/rtl/encoder.sv
new file mode 100644
index 0000000..33f0d5c
--- /dev/null
+++ b/verilog/rtl/encoder.sv
@@ -0,0 +1,27 @@
+// Behavioural model of LED encoder
+
+timeunit 1ns; timeprecision 10ps;
+
+module encoder(
+ input wire [2:0] DiceValue,
+ output wire L11, L12, L13, L21, L22, L23, L31, L32, L33
+ );
+ logic [8:0] output_leds;
+
+ // Reading left to right then down
+ assign {L11, L21, L31, L12, L22, L32, L13, L23, L33} = output_leds;
+
+ always_comb begin
+ case (DiceValue)
+ 3'd0: output_leds = 9'b000_000_000;
+ 3'd1: output_leds = 9'b000_010_000;
+ 3'd2: output_leds = 9'b100_000_001;
+ 3'd3: output_leds = 9'b100_010_001;
+ 3'd4: output_leds = 9'b101_000_101;
+ 3'd5: output_leds = 9'b101_010_101;
+ 3'd6: output_leds = 9'b101_101_101;
+ 3'd7: output_leds = 9'b111_101_111;
+ endcase
+ end
+
+endmodule
diff --git a/verilog/rtl/fast_control.v b/verilog/rtl/fast_control.v
new file mode 100644
index 0000000..8746c54
--- /dev/null
+++ b/verilog/rtl/fast_control.v
@@ -0,0 +1,51 @@
+// control module. Can't get out of error states except with reset
+
+timeunit 1ns; timeprecision 10ps;
+
+module fast_control(
+ input wire Clock, nReset,
+ input wire [1:0] Ran,
+ output wire [2:0] DiceValue
+);
+
+logic [2:0] dice_val, next_dice_value;
+logic n_1_or_6, n_2_or_5, n_3_or_4, enable_reg;
+
+logic [2:0] gated[0:5];
+
+assign n_1_or_6 = !((dice_val==3'd1) | (dice_val==3'd6));
+assign n_2_or_5 = !((dice_val==3'd2) | (dice_val==3'd5));
+assign n_3_or_4 = !((dice_val==3'd3) | (dice_val==3'd4));
+
+//assign n_1_or_6 = !((!dice_val[2] & !dice_val[1]) | ( dice_val[2] & dice_val[1]));
+//assign n_2_or_5 = !((!dice_val[2] & !dice_val[0]) | ( dice_val[2] & dice_val[0]));
+//assign n_3_or_4 = !(( dice_val[1] & dice_val[0]) | (!dice_val[1] & !dice_val[0]));
+
+//assign n_1_or_6 = !(dice_val[2] == dice_val[1]);
+//assign n_2_or_5 = !(dice_val[2] == dice_val[0]);
+//assign n_3_or_4 = !(dice_val[1] == dice_val[0]);
+
+assign DiceValue = dice_val;
+
+assign gated[0] = 3'd1 & {3{n_1_or_6 & Ran[0] & !Ran[1] }};
+assign gated[1] = 3'd2 & {3{n_2_or_5 & Ran[0] & ( Ran[1]^n_3_or_4) }};
+assign gated[2] = 3'd3 & {3{n_3_or_4 & Ran[0] & Ran[1] }};
+assign gated[3] = 3'd4 & {3{n_3_or_4 & !Ran[0] & Ran[1] }};
+assign gated[4] = 3'd5 & {3{n_2_or_5 & !Ran[0] & ( Ran[1]^n_3_or_4) }};
+assign gated[5] = 3'd6 & {3{n_1_or_6 & !Ran[0] & !Ran[1] }};
+
+assign next_dice_value = gated[0] | gated[1] | gated[2] | gated[3] | gated[4] | gated[5];
+
+always_ff @(posedge Clock, negedge nReset) begin
+ if (!nReset) begin
+ enable_reg <= 1'b0;
+ dice_val <= 3'd1;
+ end else begin
+ enable_reg <= !enable_reg;
+ if(enable_reg) begin
+ dice_val <= next_dice_value;
+ end
+ end
+end
+
+endmodule
diff --git a/verilog/rtl/random.v b/verilog/rtl/random.v
new file mode 100644
index 0000000..cf9a328
--- /dev/null
+++ b/verilog/rtl/random.v
@@ -0,0 +1,24 @@
+// SystemVerilog structural model of a LFSR PRBS generator
+
+timeunit 1ns; timeprecision 10ps;
+
+module random(
+ input wire Clock, nReset,
+ output wire [1:0] Ran
+);
+
+ // SV support for arrays of instances
+ // https://stackoverflow.com/questions/1378159/can-we-have-an-array-of-custom-modules
+
+ wire [10:0] dff_inputs, dff_outputs, dff_noutputs;
+
+ dtype lfsr[10:0] (.Clk(Clock), .nRst(nReset), .D(dff_inputs), .Q(dff_outputs), .nQ(dff_noutputs));
+
+ // Connections - see lab book for sketches
+ xor feedback (dff_inputs[10], dff_outputs[0], dff_noutputs[2]);
+
+ assign Ran = dff_outputs[1:0];
+
+ assign dff_inputs[9:0] = dff_outputs[10:1];
+
+endmodule
diff --git a/verilog/rtl/tb_encoder.v b/verilog/rtl/tb_encoder.v
new file mode 100644
index 0000000..3b4b857
--- /dev/null
+++ b/verilog/rtl/tb_encoder.v
@@ -0,0 +1,35 @@
+// Testbench for encoder
+
+timeunit 1ns; timeprecision 10ps;
+
+module tb_encoder;
+
+logic [2:0] DiceValue;
+
+wire L11, L12, L13, L21, L22, L23, L31, L32, L33;
+
+encoder dut1(.DiceValue(DiceValue),
+ .L11(L11), .L21(L21), .L31(L31),
+ .L12(L12), .L22(L22), .L32(L32),
+ .L13(L13), .L23(L23), .L33(L33)
+);
+
+// Stimuli
+integer i;
+initial begin
+ for (i=0; i<7; i++) begin
+ DiceValue = i;
+ # 20;
+ assert ($countones({L11, L12, L13, L21, L22, L23, L31, L32, L33})==DiceValue);
+ # 20;
+ end
+ DiceValue = 7;
+ # 20;
+ assert ($countones({L11, L12, L13, L21, L22, L23, L31, L32, L33})==8);
+ # 20;
+ $finish();
+end
+
+
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/tb_random.v b/verilog/rtl/tb_random.v
new file mode 100644
index 0000000..1bcfee4
--- /dev/null
+++ b/verilog/rtl/tb_random.v
@@ -0,0 +1,47 @@
+// Testbench for random
+
+timeunit 1ns; timeprecision 10ps;
+
+module tb_random;
+
+wire [1:0] Ran;
+logic Clock, nReset;
+
+localparam integer cycles = 2047;
+
+logic [1:0] pr_sequence [0:cycles-1];
+
+random dut1(.Clock(Clock), .nReset(nReset),
+ .Ran(Ran)
+);
+
+
+// Stimuli
+integer i;
+initial begin
+ nReset = 0;
+ #2 nReset = 1;
+ #10;
+
+ for (i=0; i<cycles; i++) begin
+ pr_sequence[i] = Ran;
+ #200;
+ end
+
+ for (i=0; i<cycles; i++) begin
+ assert (pr_sequence[i] == Ran) else $error("Expected %d got %d", pr_sequence[i], Ran);
+ #200;
+ end
+
+ #100 $finish();
+
+end
+
+// 100 MHz clock
+always begin
+ Clock = 0;
+ #50 Clock = 1;
+ #50;
+end
+
+endmodule