Skip to content

Commit

Permalink
Use mod_m_counter to create different frequency
Browse files Browse the repository at this point in the history
  • Loading branch information
gtli1452 committed Dec 21, 2020
1 parent 9344eed commit f790da0
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 128 deletions.
2 changes: 2 additions & 0 deletions modelsim/debussy_run.bat
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions modelsim/modelsim.do
Original file line number Diff line number Diff line change
Expand Up @@ -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

# ------------------------------------------------------------------- #
Expand Down
157 changes: 29 additions & 128 deletions rtl/diff_freq_serial_out.v
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
140 changes: 140 additions & 0 deletions rtl/serial_out.v
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit f790da0

Please sign in to comment.