blob: 8e579887c219869e512a9be10f6963633bb075aa [file] [log] [blame]
Matt Venndfc149e2022-11-24 16:39:10 +01001`default_nettype none
2
3module krasin_3_bit_8_channel_pwm_driver (
4 input [7:0] io_in,
5 output [7:0] io_out
6);
7
8 wire clk = io_in[0];
9 wire pset = io_in[1];
10 wire [2:0] addr = io_in[4:2];
11 wire [2:0] level = io_in[7:5];
12
13 wire [7:0] pwm_out;
14 assign io_out[7:0] = pwm_out;
15
16 // This register is used to determine if the execution just started and we need to reset.
17 // It's a bullshit implementation and will most likely not work. I am curious to test it anyway.
18 // The idea is that initially this register has a somewhat random value. If it does not match what we expect,
19 // we're in a reset mode and set this register to the expected state + reset all other registers.
20 // This is not a great way, as it does not guarantee anything, but I already use all input pins and
21 // like to live dangerously.
22 reg[8:0] reset_canary = 0;
23
24 // 3-bit PWM counter that goes from 0 to 7.
25 reg [2:0] counter;
26
27 function is_reset (input [8:0] a);
28 begin
29 is_reset = (a != 8'b01010101);
30 end
31 endfunction
32
33 // PWM level for channel0.
34 // 0 means always off.
35 // 1 means that PWM will be on for just 1 clock cycle and then off for the other 6, giving 1/7 on average.
36 // 6 means 6/7 on.
37 // 7 means always on.
38 reg [2:0] pwm0_level;
39 // The rest of the channels.
40 reg [2:0] pwm1_level;
41 reg [2:0] pwm2_level;
42 reg [2:0] pwm3_level;
43 reg [2:0] pwm4_level;
44 reg [2:0] pwm5_level;
45 reg [2:0] pwm6_level;
46 reg [2:0] pwm7_level;
47
48 function is_on(input [3:0] level, input[3:0] counter);
49 begin
50 is_on = (counter < level);
51 end
52 endfunction // is_on
53
54 assign pwm_out[0] = is_on(pwm0_level, counter);
55 assign pwm_out[1] = is_on(pwm1_level, counter);
56 assign pwm_out[2] = is_on(pwm2_level, counter);
57 assign pwm_out[3] = is_on(pwm3_level, counter);
58 assign pwm_out[4] = is_on(pwm4_level, counter);
59 assign pwm_out[5] = is_on(pwm5_level, counter);
60 assign pwm_out[6] = is_on(pwm6_level, counter);
61 assign pwm_out[7] = is_on(pwm7_level, counter);
62
63 // external clock is 1000Hz.
64 always @(posedge clk) begin
65 // if reset, set counter and pwm levels to 0
66 if (is_reset(reset_canary)) begin
67 reset_canary = 8'b01010101;
68 counter <= 0;
69 pwm0_level <= 0;
70 pwm1_level <= 0;
71 pwm2_level <= 0;
72 pwm3_level <= 0;
73 pwm4_level <= 0;
74 pwm5_level <= 0;
75 pwm6_level <= 0;
76 pwm7_level <= 0;
77 end else begin // if (is_reset(reset_canary))
78 if (counter == 6) begin
79 // Roll over.
80 counter <= 0;
81 end else begin
82 // increment counter
83 counter <= counter + 1'b1;
84 end
85 if (pset) begin
86 case (addr)
87 0: pwm0_level <= level;
88 1: pwm1_level <= level;
89 2: pwm2_level <= level;
90 3: pwm3_level <= level;
91 4: pwm4_level <= level;
92 5: pwm5_level <= level;
93 6: pwm6_level <= level;
94 7: pwm7_level <= level;
95 endcase
96 end // if (set)
97 end
98 end // always @ (posedge clk)
99endmodule