Skip to content
This repository has been archived by the owner on Jan 26, 2025. It is now read-only.

Commit

Permalink
Latest changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
hell03end committed Jul 19, 2020
1 parent 291b3d5 commit cad12f9
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 170 deletions.
Empty file.
Empty file added testbench/Uart8Receiver_tb.v
Empty file.
125 changes: 125 additions & 0 deletions testbench/Uart8Transmitter_tb.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
`timescale 1 ns / 100 ps

`ifndef SIMULATION_CYCLES
`define SIMULATION_CYCLES 120
`endif

`include "UartStates.vh"


module Uart8Transmitter_tb;
parameter Tt = 20; // clock timout

reg clk;
reg en;
reg start;
reg [7:0] in;
reg out;
reg done;
reg busy;

Uart8Transmitter utx (
.clk ( clk ),
.en ( en ),
.start ( start ),
.in ( in ),
.out ( out ),
.done ( done ),
.busy ( busy )
);

// simulation init
initial begin
clk = 0;
forever clk = #(Tt/2) ~clk;
end

initial begin
rst_n = 0;
repeat (4) @(posedge clk);
rst_n = 1;
end

//register file reset
integer i;
initial begin
for (i = 0; i < 32; i = i + 1) begin
sm_top.sm_cpu.rf.rf[i] = 0;
end
end

task disasmInstr (
input [31:0] instr
);
reg [ 5:0] cmdOper;
reg [ 5:0] cmdFunk;
reg [ 4:0] cmdRs;
reg [ 4:0] cmdRt;
reg [ 4:0] cmdRd;
reg [ 4:0] cmdSa;
reg [15:0] cmdImm;
reg signed [15:0] cmdImmS;

begin
cmdOper = instr[31:26];
cmdFunk = instr[ 5:0 ];
cmdRs = instr[25:21];
cmdRt = instr[20:16];
cmdRd = instr[15:11];
cmdSa = instr[10:6 ];
cmdImm = instr[15:0 ];
cmdImmS = instr[15:0 ];

$write(" ");

casez( {cmdOper,cmdFunk} )
default : if (instr == 32'b0) begin
$write ("nop");
end else begin
$write ("new/unknown");
end

{ `C_SPEC, `F_ADDU } : $write ("addu $%1d, $%1d, $%1d", cmdRd, cmdRs, cmdRt);
{ `C_SPEC, `F_OR } : $write ("or $%1d, $%1d, $%1d", cmdRd, cmdRs, cmdRt);
{ `C_SPEC, `F_SRL } : $write ("srl $%1d, $%1d, $%1d", cmdRd, cmdRs, cmdRt);
{ `C_SPEC, `F_SLTU } : $write ("sltu $%1d, $%1d, $%1d", cmdRd, cmdRs, cmdRt);
{ `C_SPEC, `F_SUBU } : $write ("subu $%1d, $%1d, $%1d", cmdRd, cmdRs, cmdRt);

{ `C_ADDIU, `F_ANY } : $write ("addiu $%1d, $%1d, %1d", cmdRt, cmdRs, cmdImm);
{ `C_LUI, `F_ANY } : $write ("lui $%1d, %1d", cmdRt, cmdImm);

{ `C_BEQ, `F_ANY } : $write ("beq $%1d, $%1d, %1d", cmdRs, cmdRt, cmdImmS + 1);
{ `C_BNE, `F_ANY } : $write ("bne $%1d, $%1d, %1d", cmdRs, cmdRt, cmdImmS + 1);

{ `C_SPEC, `F_XOR } : $write ("xor $%1d, $%1d, %1d", cmdRd, cmdRs, cmdRt);
{ `C_XORI, `F_ANY } : $write ("xori $%1d, $%1d, %1d", cmdRd, cmdRs, cmdImm);
{ `C_SPEC, `F_JR } : $write ("jr $%1d", cmdRs);
{ `C_SPEC, `F_SLL } : $write ("sll $%1d, $%1d, %1d", cmdRd, cmdRs, cmdImm);

{ `C_LIB, `F_ANY } : $write ("lib $%1d, $%1d", cmdRd, cmdImm);
endcase
end
endtask

//simulation debug output
integer cycle; initial cycle = 0;

initial regAddr = 0; // get PC

always @(posedge clk) begin
$write ("%5d pc = %2d pcaddr = %h instr = %h v0 = %1d",
cycle, regData, (regData << 2), sm_top.sm_cpu.instr, sm_top.sm_cpu.rf.rf[2]);

disasmInstr(sm_top.sm_cpu.instr);

$write("\n");

cycle = cycle + 1;

if (cycle > `SIMULATION_CYCLES) begin
$display ("Timeout");
$stop;
end
end

endmodule
Empty file added testbench/Uart8_tb.v
Empty file.
2 changes: 0 additions & 2 deletions uart/BaudRateGenerator.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
`timescale 1 ns / 1 ps

/*
* Baud rate generator to divide {CLOCK_RATE} (internal board clock) into
* a rx/tx {BAUD_RATE} pair with rx oversamples by 16x.
Expand Down
2 changes: 0 additions & 2 deletions uart/Uart8.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
`timescale 1 ns / 1 ps

/*
* Simple 8-bit UART realization.
* Combine receiver, transmitter and baud rate generator.
Expand Down
178 changes: 89 additions & 89 deletions uart/Uart8Receiver.v
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
`timescale 1 ns / 1 ps
`include "UartStates.vh"

/*
* 8-bit UART Receiver.
Expand All @@ -8,115 +8,115 @@
* When receive is in progress {busy} is driven high.
* Clock should be decreased to baud rate.
*/
module Uart8Receiver (
input wire clk, // baud rate
input wire en,
input wire in, // rx
output reg [7:0] out, // received data
output reg done, // end on transaction
output reg busy, // transaction is in process
output reg err // error while receiving data
module Uart8Receiver (
input wire clk, // baud rate
input wire en,
input wire in, // rx
output reg [7:0] out, // received data
output reg done, // end on transaction
output reg busy, // transaction is in process
output reg err // error while receiving data
);
// states of state machine
reg [1:0] RESET = 2'b00;
reg [1:0] IDLE = 2'b01;
reg [1:0] DATA_BITS = 2'b10;
reg [1:0] STOP_BIT = 2'b11;
// states of state machine
reg [1:0] RESET = 2'b00;
reg [1:0] IDLE = 2'b01;
reg [1:0] DATA_BITS = 2'b10;
reg [1:0] STOP_BIT = 2'b11;

reg [2:0] state;
reg [2:0] bitIdx = 3'b0; // for 8-bit data
reg [1:0] inputSw = 2'b0; // shift reg for input signal state
reg [3:0] clockCount = 4'b0; // count clocks for 16x oversample
reg [7:0] receivedData = 8'b0; // temporary storage for input data
reg [2:0] state;
reg [2:0] bitIdx = 3'b0; // for 8-bit data
reg [1:0] inputSw = 2'b0; // shift reg for input signal state
reg [3:0] clockCount = 4'b0; // count clocks for 16x oversample
reg [7:0] receivedData = 8'b0; // temporary storage for input data

initial begin
out <= 8'b0;
err <= 1'b0;
done <= 1'b0;
busy <= 1'b0;
end

always @(posedge clk) begin
inputSw = { inputSw[0], in };

if (!en) begin
state = RESET;
initial begin
out <= 8'b0;
err <= 1'b0;
done <= 1'b0;
busy <= 1'b0;
end

case (state)
RESET: begin
out <= 8'b0;
err <= 1'b0;
done <= 1'b0;
busy <= 1'b0;
bitIdx <= 3'b0;
clockCount <= 4'b0;
receivedData <= 8'b0;
if (en) begin
state <= IDLE;
end
always @(posedge clk) begin
inputSw = { inputSw[0], in };

if (!en) begin
state = RESET;
end

IDLE: begin
done <= 1'b0;
if (&clockCount) begin
state <= DATA_BITS;
case (state)
RESET: begin
out <= 8'b0;
err <= 1'b0;
done <= 1'b0;
busy <= 1'b0;
bitIdx <= 3'b0;
clockCount <= 4'b0;
receivedData <= 8'b0;
busy <= 1'b1;
err <= 1'b0;
end else if (!(&inputSw) || |clockCount) begin
// Check bit to make sure it's still low
if (&inputSw) begin
err <= 1'b1;
state <= RESET;
if (en) begin
state <= IDLE;
end
clockCount <= clockCount + 4'b1;
end
end

// Wait 8 full cycles to receive serial data
DATA_BITS: begin
if (&clockCount) begin // save one bit of received data
clockCount <= 4'b0;
// TODO: check the most popular value
receivedData[bitIdx] <= inputSw[0];
if (&bitIdx) begin
IDLE: begin
done <= 1'b0;
if (&clockCount) begin
state <= DATA_BITS;
out <= 8'b0;
bitIdx <= 3'b0;
state <= STOP_BIT;
clockCount <= 4'b0;
receivedData <= 8'b0;
busy <= 1'b1;
err <= 1'b0;
end else if (!(&inputSw) || |clockCount) begin
// Check bit to make sure it's still low
if (&inputSw) begin
err <= 1'b1;
state <= RESET;
end
clockCount <= clockCount + 4'b1;
end
end

// Wait 8 full cycles to receive serial data
DATA_BITS: begin
if (&clockCount) begin // save one bit of received data
clockCount <= 4'b0;
// TODO: check the most popular value
receivedData[bitIdx] <= inputSw[0];
if (&bitIdx) begin
bitIdx <= 3'b0;
state <= STOP_BIT;
end else begin
bitIdx <= bitIdx + 3'b1;
end
end else begin
bitIdx <= bitIdx + 3'b1;
clockCount <= clockCount + 4'b1;
end
end else begin
clockCount <= clockCount + 4'b1;
end
end

/*
* Baud clock may not be running at exactly the same rate as the
* transmitter. Next start bit is allowed on at least half of stop bit.
*/
STOP_BIT: begin
if (&clockCount || (clockCount >= 4'h8 && !(|inputSw))) begin
state <= IDLE;
done <= 1'b1;
busy <= 1'b0;
out <= receivedData;
clockCount <= 4'b0;
end else begin
clockCount <= clockCount + 1;
// Check bit to make sure it's still high
if (!(|inputSw)) begin
err <= 1'b1;
state <= RESET;
/*
* Baud clock may not be running at exactly the same rate as the
* transmitter. Next start bit is allowed on at least half of stop bit.
*/
STOP_BIT: begin
if (&clockCount || (clockCount >= 4'h8 && !(|inputSw))) begin
state <= IDLE;
done <= 1'b1;
busy <= 1'b0;
out <= receivedData;
clockCount <= 4'b0;
end else begin
clockCount <= clockCount + 1;
// Check bit to make sure it's still high
if (!(|inputSw)) begin
err <= 1'b1;
state <= RESET;
end
end
end
end

default: state <= IDLE;
endcase
end
default: state <= IDLE;
endcase
end

endmodule
Loading

0 comments on commit cad12f9

Please sign in to comment.