Selaa lähdekoodia

cores/misc: Improve uniformity between pdm and pwm

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Sylvain Munaut 4 vuotta sitten
vanhempi
commit
019122035b
3 muutettua tiedostoa jossa 87 lisäystä ja 28 poistoa
  1. 31 15
      cores/misc/rtl/pdm.v
  2. 52 9
      cores/misc/rtl/pwm.v
  3. 4 4
      cores/misc/sim/pdm_tb.v

+ 31 - 15
cores/misc/rtl/pdm.v

@@ -5,7 +5,7 @@
  *
  * Pulse Density Modulation core (1st order with dither)
  *
- * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2020  Sylvain Munaut <tnt@246tNt.com>
  * All rights reserved.
  *
  * BSD 3-clause, see LICENSE.bsd
@@ -37,18 +37,23 @@
 
 module pdm #(
 	parameter integer WIDTH = 8,
-	parameter PHY = "GENERIC",
-	parameter DITHER = "NO"
+	parameter DITHER = "NO",
+	parameter PHY = "GENERIC"
 )(
-	input  wire [WIDTH-1:0] in,
+	// PWM out
 	output wire pdm,
-	input  wire oe,
+
+	// Config
+	input  wire [WIDTH-1:0] cfg_val,
+	input  wire cfg_oe,
+
+	// Clock / Reset
 	input  wire clk,
 	input  wire rst
 );
 
 	// Signals
-	wire [WIDTH:0] in_i;
+	wire [WIDTH:0] inc;
 	reg  [WIDTH:0] acc;
 
 	reg  dither;
@@ -56,14 +61,14 @@ module pdm #(
 	wire pdm_i;
 
 	// Delta Sigma
-	assign in_i = { acc[WIDTH], in };
+	assign inc = { acc[WIDTH], cfg_val };
 
 	always @(posedge clk)
 	begin
 		if (rst)
 			acc <= 0;
 		else
-			acc <= acc + in_i + dither;
+			acc <= acc + inc + dither;
 	end
 
 	assign pdm_i = acc[WIDTH];
@@ -71,6 +76,7 @@ module pdm #(
 	// Dither generator
 	generate
 		if (DITHER == "YES") begin
+			// Dither using a simple LFSR
 			wire [7:0] lfsr_out;
 
 			pdm_lfsr #(
@@ -86,19 +92,29 @@ module pdm #(
 				dither <= lfsr_out[0] ^ lfsr_out[3];
 
 		end else begin
-			always @(posedge clk)
-				dither <= 1'b0;
+			// No dither
+			always @(*)
+				dither = 1'b0;
 		end
 	endgenerate
 
 	// PHY (Basically just IO register)
 	generate
-		if (PHY == "GENERIC") begin
-			reg pdm_r;
+		if (PHY == "NONE") begin
+			// No PHY (and no OE support)
+			assign pdm = pdm_i;
+		end else if (PHY == "GENERIC") begin
+			// Generic IO register, let tool figure it out
+			reg pdm_d_r;
+			reg pdm_oe_r;
 			always @(posedge clk)
-				pdm_r <= oe ? pdm_i : 1'bz;
-			assign pdm = pdm_r;
+			begin
+				pdm_d_r  <= pdm_i;
+				pdm_oe_r <= cfg_oe;
+			end
+			assign pdm = pdm_oe_r ? pdm_d_r : 1'bz;
 		end else if (PHY == "ICE40") begin
+			// iCE40 specific IOB
 			SB_IO #(
 				.PIN_TYPE(6'b110100),
 				.PULLUP(1'b0),
@@ -110,7 +126,7 @@ module pdm #(
 				.CLOCK_ENABLE(1'b1),
 				.INPUT_CLK(1'b0),
 				.OUTPUT_CLK(clk),
-				.OUTPUT_ENABLE(oe),
+				.OUTPUT_ENABLE(cfg_oe),
 				.D_OUT_0(pdm_i),
 				.D_OUT_1(1'b0),
 				.D_IN_0(),

+ 52 - 9
cores/misc/rtl/pwm.v

@@ -3,7 +3,7 @@
  *
  * vim: ts=4 sw=4
  *
- * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2020  Sylvain Munaut <tnt@246tNt.com>
  * All rights reserved.
  *
  * BSD 3-clause, see LICENSE.bsd
@@ -34,22 +34,27 @@
 `default_nettype none
 
 module pwm #(
-	parameter integer WIDTH = 10
+	parameter integer WIDTH = 10,
+	parameter PHY = "GENERIC"
 )(
 	// PWM out
 	output wire pwm,
 
 	// Config
-	input wire [WIDTH-1:0] cfg_val,
+	input  wire [WIDTH-1:0] cfg_val,
+	input  wire cfg_oe,
 
 	// Clock / Reset
-	input wire  clk,
-	input wire  rst
+	input  wire  clk,
+	input  wire  rst
 );
+	// Signals
 	wire [WIDTH:0] cnt_cycle_rst;
-	reg [WIDTH:0] cnt_cycle;
-	reg [WIDTH:0] cnt_on;
+	reg  [WIDTH:0] cnt_cycle;
+	reg  [WIDTH:0] cnt_on;
+	wire pwm_i;
 
+	// Cycle counter (counts 2^WIDTH - 1 cycles)
 	assign cnt_cycle_rst = { { (WIDTH-1){1'b0} }, 2'b10 };
 
 	always @(posedge clk or posedge rst)
@@ -58,12 +63,50 @@ module pwm #(
 		else
 			cnt_cycle <= cnt_cycle[WIDTH] ? cnt_cycle_rst : (cnt_cycle + 1);
 
+	// ON counter (counts cycles with output high)
 	always @(posedge clk or posedge rst)
 		if (rst)
 			cnt_on <= 0;
 		else
-			cnt_on <= (cnt_cycle[WIDTH] ? { 1'b1, cfg_val } : cnt_on) - 1;
+			cnt_on <= cnt_cycle[WIDTH] ? { 1'b1, cfg_val } : (cnt_on - 1);
 
-	assign pwm = cnt_on[WIDTH];
+	assign pwm_i = cnt_on[WIDTH];
+
+	// PHY (Basically just IO register)
+	generate
+		if (PHY == "NONE") begin
+			// No PHY (and no OE support)
+			assign pwm = pwm_i;
+		end else if (PHY == "GENERIC") begin
+			// Generic IO register, let tool figure it out
+			reg pwm_d_r;
+			reg pwm_oe_r;
+			always @(posedge clk)
+			begin
+				pwm_d_r  <= pwm_i;
+				pwm_oe_r <= cfg_oe;
+			end
+			assign pwm = pwm_oe_r ? pwm_d_r : 1'bz;
+		end else if (PHY == "ICE40") begin
+			// iCE40 specific IOB
+			SB_IO #(
+				.PIN_TYPE(6'b110100),
+				.PULLUP(1'b0),
+				.NEG_TRIGGER(1'b0),
+				.IO_STANDARD("SB_LVCMOS")
+			) io_reg_I (
+				.PACKAGE_PIN(pwm),
+				.LATCH_INPUT_VALUE(1'b0),
+				.CLOCK_ENABLE(1'b1),
+				.INPUT_CLK(1'b0),
+				.OUTPUT_CLK(clk),
+				.OUTPUT_ENABLE(cfg_oe),
+				.D_OUT_0(pwm_i),
+				.D_OUT_1(1'b0),
+				.D_IN_0(),
+				.D_IN_1()
+			);
+		end
+	endgenerate
 
 endmodule // pwm

+ 4 - 4
cores/misc/sim/pdm_tb.v

@@ -61,12 +61,12 @@ module pdm_tb;
 	// DUT
 	pdm #(
 		.WIDTH(12),
-		.PHY("ICE40"),
-		.DITHER("ON")
+		.DITHER("ON"),
+		.PHY("ICE40")
 	) dut_I (
-		.in({data[7:4],data}),
 		.pdm(pdm),
-		.oe(1'b1),
+		.cfg_val({data[7:4],data}),
+		.cfg_oe(1'b1),
 		.clk(clk),
 		.rst(rst)
 	);