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