Commit bcba8085 authored by Koen Martens's avatar Koen Martens
Browse files

uart: refactoring, create transmit module

parent e6da09e3
module transmit #(
parameter DATA_WIDTH = 8,
parameter DIVISOR_WIDTH = 16
)(
input wire clk_i,
input wire rst_i,
input wire [DATA_WIDTH-1:0] data_i,
input wire [DIVISOR_WIDTH-1:0] clk_divisor_i,
output reg sout,
output reg data_latched_o,
input wire data_ready_i
);
reg [DATA_WIDTH-1:0] data;
reg [DIVISOR_WIDTH+3:0] clk_counter;
wire [DIVISOR_WIDTH+3:0] clk_counter_next = clk_counter + 1;
reg [DATA_WIDTH-1:0] data_bit;
reg [7:0] state;
localparam STATE_IDLE = 'b00000001;
localparam STATE_START = 'b00000010;
localparam STATE_DATA = 'b00000100;
localparam STATE_STOP = 'b00001000;
always @(posedge clk_i) begin
if(rst_i) begin
data_latched_o <= 1'b0;
sout <= 1'b1;
clk_counter <= 0;
data <= 0;
data_bit <= 0;
state <= STATE_IDLE;
end else begin
case(state)
STATE_IDLE:
begin
data_latched_o <= data_ready_i;
sout <= 1'b1;
clk_counter <= 1;
if(data_ready_i) begin
data <= data_i;
state <= STATE_START;
end
end
STATE_START:
begin
data_latched_o <= 1'b0;
sout <= 1'b0;
clk_counter <= clk_counter_next;
if(clk_counter == (clk_divisor_i<<4)) begin
clk_counter <= 1;
state <= STATE_DATA;
data_bit <= 1'b1;
end
end
STATE_DATA:
begin
data_latched_o <= 1'b0;
sout <= |(data & data_bit);
clk_counter <= clk_counter_next;
if(clk_counter == (clk_divisor_i<<4)) begin
clk_counter <= 1;
if(data_bit == (1<<DATA_WIDTH-1))
state <= STATE_STOP;
data_bit <= data_bit << 1;
end
end
STATE_STOP:
begin
sout <= 1'b1;
clk_counter <= clk_counter_next;
if(clk_counter == (clk_divisor_i<<4)) begin
clk_counter <= 1;
if(data_ready_i) begin
data_latched_o <= 1'b1;
data <= data_i;
state <= STATE_START;
end else begin
data_latched_o <= 1'b0;
state <= STATE_IDLE;
end
end
end
default:
begin
data_latched_o <= 1'b0;
sout <= 1'b1;
clk_counter <= 0;
state <= STATE_IDLE;
end
endcase
end
end
endmodule
`include "common/testbench.v"
`include "transmit.v"
module transmit_tb();
reg clk = 0;
always #0.5 clk = ~clk;
parameter TB_DATA_WIDTH = 8;
parameter TB_ADDR_WIDTH = 3;
parameter TB_DIVIDER = 8;
reg tb_rst_i;
reg [15:0] tb_clk_divisor_i;
wire tb_sout;
wire tb_data_latched_o;
reg [TB_DATA_WIDTH-1:0] tb_data_i;
reg tb_data_ready_i;
wire tb_delayed_rst_i;
wire [15:0] tb_delayed_clk_divisor_i;
wire tb_delay_sout;
wire tb_delay_data_latched_o;
wire [TB_DATA_WIDTH-1:0] tb_delayed_data_i;
wire tb_delayed_data_ready_i;
assign #`TB_IN_DELAY tb_delayed_rst_i = tb_rst_i;
assign #`TB_IN_DELAY tb_delayed_clk_divisor_i = tb_clk_divisor_i;
assign #`TB_IN_DELAY tb_delayed_data_i = tb_data_i;
assign #`TB_IN_DELAY tb_delayed_data_ready_i = tb_data_ready_i;
assign #`TB_IN_DELAY tb_sout = tb_delay_sout;
assign #`TB_IN_DELAY tb_data_latched_o = tb_delay_data_latched_o;
transmit #(
.DATA_WIDTH(TB_DATA_WIDTH)
) UUT (
.clk_i(clk),
.rst_i(tb_delayed_rst_i),
.clk_divisor_i(tb_delayed_clk_divisor_i),
.sout(tb_delay_sout),
.data_latched_o(tb_delay_data_latched_o),
.data_i(tb_delayed_data_i),
.data_ready_i(tb_delayed_data_ready_i)
);
`include "common/testbench_tasks/tb_assert.v"
task verify_sout(
input [TB_DATA_WIDTH-1:0] expected,
input string message = ""
);
begin
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === 1'b0, {message, ", start bit (0)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", start, data_latched_o deasserted"});
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit0 (1)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 0, data_latched_o deasserted"});
end
expected = expected >> 1;
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit1 (1)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 1, data_latched_o deasserted"});
end
expected = expected >> 1;
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit2 (0)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 2, data_latched_o deasserted"});
end
expected = expected >> 1;
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit3 (1)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 3, data_latched_o deasserted"});
end
expected = expected >> 1;
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit4 (0)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 4, data_latched_o deasserted"});
end
expected = expected >> 1;
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit5 (0)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 5, data_latched_o deasserted"});
end
expected = expected >> 1;
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit6 (1)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 6, data_latched_o deasserted"});
end
expected = expected >> 1;
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout === expected[0], {message, ", bit7 (0)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", bit 7, data_latched_o deasserted"});
end
repeat(31) begin
@(posedge clk);
tb_assert(tb_sout === 1'b1, {message, ", stop bit (1)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", stop bit, data_latched_o deasserted"});
end
end
endtask
integer counter;
initial begin
$dumpfile(`VCD_OUTPUT);
$dumpvars(0, transmit_tb);
tb_rst_i = 1'b1; tb_clk_divisor_i = 2; tb_data_i = 'h4b; tb_data_ready_i = 1'b0;
@(posedge clk);
tb_assert(tb_data_latched_o==1'b0, "data_latched_o not asserted after reset");
tb_assert(tb_sout==1'b1, "sout asserted after reset");
tb_rst_i = 1'b0;
@(posedge clk);
@(posedge clk);
tb_data_ready_i = 1'b1;
@(posedge clk);
tb_data_ready_i = 1'b0;
@(negedge clk);
tb_assert(tb_data_latched_o==1'b1, "data_latched_o asserted after data_ready");
@(posedge clk);
@(negedge clk);
tb_assert(tb_data_latched_o==1'b0, "data_latched_o deasserted after clock cycle");
tb_data_i = 'b10110100; tb_data_ready_i = 1'b1;
// byte 1
verify_sout('h4b, "byte 1");
/*
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 1, start bit (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, start, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 1, bit0 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 0, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 1, bit1 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 1, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 1, bit2 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 2, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 1, bit3 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 3, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 1, bit4 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 4, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 1, bit5 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 5, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 1, bit6 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 6, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 1, bit7 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, bit 7, data_latched_o deasserted");
end
repeat(31) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 1, stop bit (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 1, stop bit, data_latched_o deasserted");
end
*/
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 1, stop bit (1) last period");
tb_assert(tb_data_latched_o==1'b1, "byte 1, data_latched_o asserted for byte 2");
tb_data_ready_i = 1'b0;
@(posedge clk);
// byte 2 ('b10110100)
tb_assert(tb_data_latched_o==1'b0, "data_latched_o deasserted after clock cycle for byte 2");
repeat(31) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 2, start bit (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, start, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 2, bit0 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 0, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 2, bit1 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 1, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 2, bit2 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 2, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 2, bit3 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 3, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 2, bit4 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 4, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 2, bit5 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 5, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 2, bit6 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 6, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 2, bit7 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, bit 7, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 2, stop bit (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 2, stop bit, data_latched_o deasserted");
end
repeat(10) @(posedge clk);
// byte 3
tb_data_i = 8'b10101010;
tb_data_ready_i = 1'b1;
@(posedge clk);
tb_data_ready_i = 1'b0;
@(negedge clk);
tb_assert(tb_data_latched_o==1'b1, "byte 3, data_latched_o asserted after data_ready");
@(posedge clk);
@(negedge clk);
tb_assert(tb_data_latched_o==1'b0, "byte 3, data_latched_o deasserted after clock cycle");
// byte 3
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 3, start bit (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, start, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 3, bit0 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 0, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 3, bit1 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 1, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 3, bit2 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 2, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 3, bit3 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 3, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 3, bit4 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 4, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 3, bit5 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 5, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b0, "byte 3, bit6 (0)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 6, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 3, bit7 (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, bit 7, data_latched_o deasserted");
end
repeat(32) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 3, stop bit (1)");
tb_assert(tb_data_latched_o==1'b0, "byte 3, stop bit, data_latched_o deasserted");
end
repeat(10) begin
@(posedge clk);
tb_assert(tb_sout == 1'b1, "idle (1)");
tb_assert(tb_data_latched_o==1'b0, "idle, data_latched_o deasserted");
end
$display("passed");
$finish;
end
endmodule
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment