From f790da0976767059a5fb33f53afb43dbbc615701 Mon Sep 17 00:00:00 2001 From: "Tim.Li" Date: Mon, 21 Dec 2020 15:50:30 +0800 Subject: [PATCH] Use mod_m_counter to create different frequency --- modelsim/debussy_run.bat | 2 + modelsim/modelsim.do | 1 + rtl/diff_freq_serial_out.v | 157 +++++++------------------------------ rtl/serial_out.v | 140 +++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 128 deletions(-) create mode 100644 rtl/serial_out.v diff --git a/modelsim/debussy_run.bat b/modelsim/debussy_run.bat index fb03bdb..3ee134a 100644 --- a/modelsim/debussy_run.bat +++ b/modelsim/debussy_run.bat @@ -7,6 +7,8 @@ DEL transcript vsim.wlf modelsim.ini /q ::Debussy command debussy -2001 ./../tb/diff_freq_serial_out_tb.v ^ ./../rtl/diff_freq_serial_out.v ^ + ./../rtl/serial_out.v ^ + ./../rtl/mod_m_counter.v ^ -ssf diff_freq_serial_out.fsdb ^ -sswr waveform.rc diff --git a/modelsim/modelsim.do b/modelsim/modelsim.do index 864f7f8..119b582 100644 --- a/modelsim/modelsim.do +++ b/modelsim/modelsim.do @@ -17,6 +17,7 @@ vmap diff_freq_serial_out_lib work # ------------------------------------------------------------------- # vlog -work diff_freq_serial_out_lib +incdir+$rtl_dir $rtl_dir/mod_m_counter.v +vlog -work diff_freq_serial_out_lib +incdir+$rtl_dir $rtl_dir/serial_out.v vlog -work diff_freq_serial_out_lib +incdir+$rtl_dir $rtl_dir/diff_freq_serial_out.v # ------------------------------------------------------------------- # diff --git a/rtl/diff_freq_serial_out.v b/rtl/diff_freq_serial_out.v index 1f3d7b7..b15c2a2 100644 --- a/rtl/diff_freq_serial_out.v +++ b/rtl/diff_freq_serial_out.v @@ -7,9 +7,10 @@ Release : 12/16/2020 v1.0 */ module diff_freq_serial_out #( - parameter DATA_BIT = 16, - parameter [7:0] LOW_FREQ = 20, - parameter [7:0] HIGH_FREQ = 10 + parameter DATA_BIT = 16, + parameter TICK_PER_BIT = 16, + parameter [7:0] LOW_FREQ = 20, + parameter [7:0] HIGH_FREQ = 10 ) ( input clk, input rst_n, @@ -19,133 +20,33 @@ module diff_freq_serial_out #( input [1:0] i_idle_mode, // high, low, keep, repeat input [DATA_BIT-1:0] i_data, output o_data, // idle state is low - output reg o_done_tick + output o_done_tick ); -// Define the states -localparam [1:0] S_IDLE = 2'b00; -localparam [1:0] S_ENABLE = 2'b01; -localparam [1:0] S_DONE = 2'b10; - -localparam [1:0] LOW = 2'b00; -localparam [1:0] HIGH = 2'b01; -localparam [1:0] KEEP = 2'b10; -localparam [1:0] REPEAT = 2'b11; - -// Signal declaration -reg [1:0] state_reg, state_next; -reg output_reg, output_next; -reg [5:0] data_bit_reg, data_bit_next; -reg [DATA_BIT-1:0] data_buf_reg, data_buf_next; -reg [7:0] count_reg, count_next; -reg [7:0] count_max_reg, count_max_next; - -// Body -// FSMD state & data registers -always @(posedge clk, negedge rst_n) begin - if (~rst_n) - begin - state_reg <= S_IDLE; - output_reg <= 1'b0; - data_bit_reg <= 5'b0; - data_buf_reg <= {(DATA_BIT){1'b0}}; - count_reg <= 7'b0; - count_max_reg <= LOW_FREQ - 1'b1; - end - else - begin - state_reg <= state_next; - output_reg <= output_next; - data_bit_reg <= data_bit_next; - data_buf_reg <= data_buf_next; - count_reg <= count_next; - count_max_reg <= count_max_next; - end -end - -// FSMD next-state logic -always @(*) begin - state_next = state_reg; - output_next = output_reg; - data_bit_next = data_bit_reg; - data_buf_next = data_buf_reg; - count_next = count_reg; - count_max_next = count_max_reg; - o_done_tick = 1'b0; - - case (state_reg) - // S_IDLE: waiting for the i_start, output depends on i_idle_mode - S_IDLE: begin - // determine the idle output, default is low. - case (i_idle_mode) - HIGH: output_next = 1'b1; - LOW: output_next = 1'b0; - KEEP: output_next = output_reg; - default: output_next = 1'b0; - endcase - // start output - if (i_start) - begin - state_next = S_ENABLE; - data_buf_next = i_data; // load the input data - data_bit_next = 0; - count_next = 7'b0; // reset the counter - if (i_sel_freq) // get the frequency for next bit - count_max_next = HIGH_FREQ - 1'b1; - else - count_max_next = LOW_FREQ - 1'b1; - end - end // case: S_IDLE - // S_ENABLE: serially output 32-bit data, it can change period per bit - S_ENABLE: begin - output_next = data_buf_next[0]; // transmit lsb first - if (i_stop) - begin - state_next = S_IDLE; - end - else if (count_reg == count_max_reg) - begin - count_next = 7'b0; - data_buf_next = data_buf_reg >> 1; - - if (i_sel_freq) // get the frequency for next bit - count_max_next = HIGH_FREQ - 1'b1; - else - count_max_next = LOW_FREQ - 1'b1; - - if (data_bit_reg == (DATA_BIT - 1 )) - state_next = S_DONE; - else - data_bit_next = data_bit_reg + 1'b1; - end - else - count_next = count_reg + 1'b1; - end // case: S_ENABLE - // S_DONE: assert o_done_tick for one clock - S_DONE: begin - o_done_tick = 1'b1; - state_next = S_IDLE; - - case (i_idle_mode) - HIGH: output_next = 1'b1; - LOW: output_next = 1'b0; - KEEP: begin - output_next = output_reg; - state_next = S_ENABLE; - data_buf_next = i_data; // load the input data - data_bit_next = 0; - count_next = 7'b0; // reset the counter - end - default: output_next = 1'b0; - endcase - - end // case: S_DONE - - default: state_reg = S_IDLE; - endcase -end +wire tick; + +serial_out #( + .DATA_BIT (DATA_BIT), + .TICK_PER_BIT (TICK_PER_BIT) +) serial_out1 ( + .clk (clk), + .rst_n (rst_n), + .i_tick (tick), // select high/low frequency + .i_start (i_start), + .i_stop (i_stop), + .i_idle_mode (i_idle_mode), // high, low, keep, repeat + .i_data (i_data), + .o_data (o_data), // idle state is low + .o_done_tick (o_done_tick) +); -// Output -assign o_data = output_reg; +mod_m_counter #( + .MOD (2) +) tick_10us ( + .clk (clk), + .rst_n (rst_n), + .max_tick (tick), + .q () +); endmodule diff --git a/rtl/serial_out.v b/rtl/serial_out.v new file mode 100644 index 0000000..6b04cbe --- /dev/null +++ b/rtl/serial_out.v @@ -0,0 +1,140 @@ +/* +Filename : serial_out.v +Simulation : ModelSim 10.2c, Debussy 5.4 v9 +Description : Serially output 32-bit data by different frequency +Author : Tim.Li +Release : 12/16/2020 v1.0 +*/ + +module serial_out #( + parameter DATA_BIT = 16, + parameter TICK_PER_BIT = 16 +) ( + input clk, + input rst_n, + input i_tick, // select high/low frequency + input i_start, + input i_stop, + input [1:0] i_idle_mode, // high, low, keep, repeat + input [DATA_BIT-1:0] i_data, + output o_data, // idle state is low + output reg o_done_tick +); + +// Define the states +localparam [1:0] S_IDLE = 2'b00; +localparam [1:0] S_ENABLE = 2'b01; +localparam [1:0] S_DONE = 2'b10; + +localparam [1:0] LOW = 2'b00; +localparam [1:0] HIGH = 2'b01; +localparam [1:0] KEEP = 2'b10; +localparam [1:0] REPEAT = 2'b11; + +// Signal declaration +reg [1:0] state_reg, state_next; +reg output_reg, output_next; +reg [5:0] data_bit_reg, data_bit_next; +reg [DATA_BIT-1:0] data_buf_reg, data_buf_next; +reg [7:0] count_reg, count_next; + +// Body +// FSMD state & data registers +always @(posedge clk, negedge rst_n) begin + if (~rst_n) + begin + state_reg <= S_IDLE; + output_reg <= 1'b0; + data_bit_reg <= 5'b0; + data_buf_reg <= {(DATA_BIT){1'b0}}; + count_reg <= 7'b0; + end + else + begin + state_reg <= state_next; + output_reg <= output_next; + data_bit_reg <= data_bit_next; + data_buf_reg <= data_buf_next; + count_reg <= count_next; + end +end + +// FSMD next-state logic +always @(*) begin + state_next = state_reg; + output_next = output_reg; + data_bit_next = data_bit_reg; + data_buf_next = data_buf_reg; + count_next = count_reg; + o_done_tick = 1'b0; + + case (state_reg) + // S_IDLE: waiting for the i_start, output depends on i_idle_mode + S_IDLE: begin + // determine the idle output, default is low. + case (i_idle_mode) + HIGH: output_next = 1'b1; + LOW: output_next = 1'b0; + KEEP: output_next = output_reg; + default: output_next = 1'b0; + endcase + // start output + if (i_start) + begin + state_next = S_ENABLE; + data_buf_next = i_data; // load the input data + data_bit_next = 0; + count_next = 7'b0; // reset the counter + end + end // case: S_IDLE + // S_ENABLE: serially output 32-bit data, it can change period per bit + S_ENABLE: begin + output_next = data_buf_next[0]; // transmit lsb first + if (i_stop) + begin + state_next = S_IDLE; + end + else if (i_tick) + begin + if (count_reg == TICK_PER_BIT - 1) + begin + count_next = 7'b0; + data_buf_next = data_buf_reg >> 1; + + if (data_bit_reg == (DATA_BIT - 1 )) + state_next = S_DONE; + else + data_bit_next = data_bit_reg + 1'b1; + end + else + count_next = count_reg + 1'b1; + end + end // case: S_ENABLE + // S_DONE: assert o_done_tick for one clock + S_DONE: begin + o_done_tick = 1'b1; + state_next = S_IDLE; + + case (i_idle_mode) + HIGH: output_next = 1'b1; + LOW: output_next = 1'b0; + KEEP: begin + output_next = output_reg; + state_next = S_ENABLE; + data_buf_next = i_data; // load the input data + data_bit_next = 0; + count_next = 7'b0; // reset the counter + end + default: output_next = 1'b0; + endcase + + end // case: S_DONE + + default: state_reg = S_IDLE; + endcase +end + +// Output +assign o_data = output_reg; + +endmodule