-1

I was wondering if someone may be able to help me? I was not sure how to word the question, but I am basically trying to write a program that generates a square wave output signal from a square wave input signal, matching the duty cycle and frequency of the input signal. Basically, the output just copies the input. To summarize what I am saying graphically, here is a picture I made:

Link to diagram

It is not my final goal, but it would be enough to get me going. I am having a very hard time figuring out how to work with inputs. I have a signal generator making the input square wave signal, and am sending it into an input pin. I've tried calculating the duty cycle mathematically, and then just trying to assign the output to a reg that is set equal to the input on every rising edge of the clock signal but it didn't work.

Here's my code. It has extra functionality of generating a 1 Hz signal, but that is only from learning earlier how to create the pwm. You can ignore "pwm_reg" and the "pwm" output. The "pwm2" output is intended to copy "apwm" input:

`timescale 1ns / 1ps
module duty_cycle_gen(
    input clk,
    input rst_n,
    input apwm,
    output pwm,
    output pwm2
);
    // Input clock is 250MHz
    localparam CLOCK_FREQUENCY = 250000000;
    // Counter for toggling of clock
    integer counter = 0;
    reg pwm_reg = 0;
    assign pwm = pwm_reg;
    reg apwm_val;
always @(posedge clk) begin
        if (!rst_n) begin
            counter <= 8'h00;
            pwm_reg <= 1'b0;
        end
        else begin 
            apwm_val <= apwm;
            // If counter is zero, toggle pwm_reg
            if (counter == 8'h00) begin
                pwm_reg <= ~pwm_reg;
                // Generate 1Hz Frequency
                counter <= CLOCK_FREQUENCY/2 - 1;  
                
            end 
            // Else count down
            else 
                counter <= counter - 1; 
            end
            $display("counter : %d", counter);
            
        end
assign pwm2 = apwm_val;
endmodule
kwhobbs
  • 1
  • 1

1 Answers1

0

Here is a simple example with a test bench. (I like to use a small delay when assigning, #1, to help capture causality for debugging purposes):

module example(
    input wire clk,
    input wire in,
    output reg out);

    always @(posedge clk)
      begin
        out <= #1 in;
      end

endmodule // example

module example_test();
    reg chip__clk;
    reg chip__in;
    wire chip__out;
    reg [10:0] count;

    example ex(
        chip__clk,
        chip__in,
        chip__out);

    initial
      begin
        $dumpvars();
        count <= #1 0;
      end

    always @(count)
      begin
        count <= #1 (count + 1);
        if (count == 1000)
          begin
            $display("RESULT=PASS:0 @ done");
            $finish_and_return(0);
          end
        if ((count == 60) & (chip__out != 1))
          begin
            $display("RESULT=FAIL:1 @ chip.out not raised");
            $finish_and_return(1);
          end
        if ((count == 30) & (chip__out != 0))
          begin
            $display("RESULT=FAIL:1 @ chip.out not lowered");
            $finish_and_return(1);
          end
        chip__in <= #1 count[5];
        chip__clk <= #1 count[1];
      end

endmodule // example_test

It works by treating the in signal as something that can can be thought of as constant over the timescale of the higher frequency clk.

If your in clock is an external signal which might be noisy, with the small latency delay, you can attempt to stabilize it by using a small fifo running with the high frequency clk:

module example(
    input wire clk,
    input wire in,
    output reg out);

    reg [1:0] buffer;

    always @(posedge clk)
      begin
        out <= #1 buffer[1];
        buffer[1] <= #1 buffer[0];
        buffer[0] <= #1 in;
      end

endmodule // example
Tinkerer
  • 865
  • 7
  • 9