Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
gtli1452 committed Dec 21, 2020
0 parents commit 475660b
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 0 deletions.
31 changes: 31 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ignore ModelSim generated files and directories (temp files and so on)
[_@]*

# ignore compilation output of ModelSim
*.mti
*.dat
*.dbs
*.psm
*.bak
*.cmp
*.jpg
*.html
*.bsf

# ignore simulation output of ModelSim
wlf*
*.wlf
*.vstf
*.ucdb
cov*/
transcript*
sc_dpiheader.h
vsim.dbg
*.fsdb*
*.ini

# ignore Log directory of Debussy
Debussy*/

# ignore user define *.v
uart*.v
17 changes: 17 additions & 0 deletions modelsim/debussy_run.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
::Modelsim command
vsim -c -do modelsim.do

::Delete Modelsim generated files, except the work library folder
DEL transcript vsim.wlf modelsim.ini /q

::Debussy command
debussy -2001 ./../tb/diff_freq_serial_out_tb.v ^
./../rtl/diff_freq_serial_out.v ^
-ssf diff_freq_serial_out.fsdb ^
-sswr waveform.rc

::Delete waveform file
DEL *.fsdb /q

::Delete Debussy generated files
RD Debussy.exeLog /s /q
42 changes: 42 additions & 0 deletions modelsim/modelsim.do
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ------------------------------------------------------------------- #
# Directories location
# ------------------------------------------------------------------- #

set rtl_dir ./../rtl
set tb_dir ./../tb

# ------------------------------------------------------------------- #
# Mapping destination directory for models
# ------------------------------------------------------------------- #

vlib work
vmap diff_freq_serial_out_lib work

# ------------------------------------------------------------------- #
# Compiling components of core
# ------------------------------------------------------------------- #

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/diff_freq_serial_out.v

# ------------------------------------------------------------------- #
# Compiling core
# ------------------------------------------------------------------- #

# ------------------------------------------------------------------- #
# Compiling components of Test Bench
# ------------------------------------------------------------------- #

vlog -work diff_freq_serial_out_lib +incdir+$tb_dir $tb_dir/diff_freq_serial_out_tb.v

# ------------------------------------------------------------------- #
# Loading the Test Bench
# ------------------------------------------------------------------- #

vsim -pli novas.dll -novopt -t ns -lib diff_freq_serial_out_lib diff_freq_serial_out_tb

#wave zoom range 0ns 20us
add wave -unsigned sim:/diff_freq_serial_out_tb/*
run 1ms
q
1 change: 1 addition & 0 deletions modelsim/modelsim_run.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
modelsim -do modelsim.do
146 changes: 146 additions & 0 deletions rtl/diff_freq_serial_out.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
Filename : diff_freq_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 diff_freq_serial_out #(
parameter DATA_BIT = 16,
parameter [7:0] LOW_FREQ = 20,
parameter [7:0] HIGH_FREQ = 10
) (
input clk,
input rst_n,
input i_sel_freq, // 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;
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
output_next = output_reg;
o_done_tick = 1'b1;
if (i_idle_mode == REPEAT)
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
else
state_next = S_IDLE;
end // case: S_DONE

default: state_reg = S_IDLE;
endcase
end

// Output
assign o_data = output_reg;

endmodule
30 changes: 30 additions & 0 deletions rtl/mod_m_counter.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module mod_m_counter #(
parameter MOD = 65, // mod-M
parameter MOD_BIT = $clog2(MOD) // number of bits in counter
) (
input clk,
input rst_n,
output max_tick,
output [MOD_BIT-1:0] q
);

// Signal declaration
reg [MOD_BIT-1:0] count_reg;
wire [MOD_BIT-1:0] count_next;

// Body
// Register
always @(posedge clk, negedge rst_n) begin
if (~rst_n)
count_reg <= 0;
else
count_reg <= count_next;
end

// Next-state logic
assign count_next = (count_reg == (MOD-1)) ? {(MOD_BIT){1'b0}} : count_reg + 1'b1;
// Output logic
assign max_tick = (count_reg == (MOD-1)) ? 1'b1 : 1'b0;
assign q = count_reg;

endmodule
95 changes: 95 additions & 0 deletions tb/diff_freq_serial_out_tb.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
Filename : diff_freq_serial_out_tb.v
Compiler : ModelSim 10.2c, Debussy 5.4 v9
Description : ModelSim with debussy
Author : Tim.Li
Release : 12/16/2020 v1.0
*/

module diff_freq_serial_out_tb ();

// Parameter declaration
localparam DATA_BIT = 8;
localparam SYS_PERIOD_NS = 100; // 1/10Mhz = 100ns

localparam [7:0] LOW_FREQ = 20; // 10MHz/20 = 0.5MHz
localparam [7:0] HIGH_FREQ = 10; // 10MHz/10 = 1MHz

localparam [1:0] IDLE_LOW = 2'b00;
localparam [1:0] IDLE_HIGH = 2'b01;
localparam [1:0] IDLE_KEEP = 2'b10;
localparam [1:0] IDLE_REPEAT = 2'b11;

localparam LOW_SPEED = 1'b0;
localparam HIGH_SPEED = 1'b1;

// Signal declaration
reg clk = 1'b0;
reg rst_n = 1'b0;
reg i_sel_freq = 1'b0; // select high/low frequency
reg i_start = 1'b0;
reg i_stop = 1'b0;
reg [1:0] i_idle_mode = 0; // high, low, keep, repeat
reg [DATA_BIT-1:0] i_data = 0;
wire o_data; // idle state is low
wire o_done_tick; // tick one clock when transmission is done

always #(SYS_PERIOD_NS/2) clk = ~clk;

initial begin
#0;
clk = 1'b0;
rst_n = 1'b0;

#5;
rst_n = 1'b1;
#(SYS_PERIOD_NS/2);
end

initial begin
$fsdbDumpfile("diff_freq_serial_out.fsdb");
$fsdbDumpvars(0, diff_freq_serial_out_tb);
end

diff_freq_serial_out #(
.DATA_BIT (DATA_BIT),
.LOW_FREQ (LOW_FREQ),
.HIGH_FREQ (HIGH_FREQ)
) serial_out_unit (
.clk (clk),
.rst_n (rst_n),
.i_sel_freq (i_sel_freq), // 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)
);

initial begin
@(posedge rst_n); // wait for finish reset
CHANGE_CLK_PER_PACKAGE(8'h55, HIGH_SPEED, IDLE_LOW);
CHANGE_CLK_PER_PACKAGE(8'h55, LOW_SPEED, IDLE_LOW);
CHANGE_CLK_PER_PACKAGE(8'h55, LOW_SPEED, IDLE_LOW);

$finish;
end

task CHANGE_CLK_PER_PACKAGE;
input [DATA_BIT-1:0] input_data;
input transmit_clk;
input idle_output;
begin
i_sel_freq = transmit_clk; // select low speed
i_data = input_data;
i_start = 1'b1; // start transmit
i_idle_mode = idle_output; // idle output is low
@(posedge clk);
i_start = 1'b0; // start signal is high in one clock
@(negedge o_done_tick);
end
endtask


endmodule

0 comments on commit 475660b

Please sign in to comment.