Commit 47ee9529 authored by Roberto Hexsel's avatar Roberto Hexsel

fixed UART TX state machine: new char transmitted before end of stop-bit

parent 607df88f
......@@ -118,12 +118,14 @@ if [ $synth = true ]; then
S="-D FOR_SYNTHESIS" ;
c_start="${include}"/syn_start
c_hndlrs="${include}"/syn_handlers
touch $pkg_vhd -r ${srcVHDL}/packageMemory_fpga.vhd
touch $pkg_vhd -r ${srcVHDL}/packageMemory_fpga.vhd
touch $pkg_vhd
else
S="-U FOR_SYNTHESIS" ;
c_start="${include}"/start
c_hndlrs="${include}"/handlers
touch $pkg_vhd -r ${srcVHDL}/packageMemory_simu.vhd
touch $pkg_vhd -r ${srcVHDL}/packageMemory_simu.vhd
touch $pkg_vhd
fi
if [ $pkg_vhd -nt $c_h -o\
......
......@@ -69,7 +69,7 @@ extern void LCDgotoxy(int, int);
extern void LCDputc(char);
extern void LCDint(unsigned int);
extern void LCDshort(unsigned short);
extern void LCDchar(unsigned char);
extern void LCDbyte(unsigned char);
// 7-segment display and keyboard (Macnica board)
extern void DSP7SEGput(int, int, int, int, int);
......
......@@ -393,7 +393,7 @@ void LCDshort(unsigned short n) {
}
// write a char to the display
void LCDchar(unsigned char n) {
void LCDbyte(unsigned char n) {
int k;
k = (n >>4);
......
......@@ -76,7 +76,7 @@ _start: nop
##
exit:
_exit: la $k0, HW_dsp7seg_addr # 7 segment display
li $k1, 0x0300 # display .0.0
li $k1, 0x1300 # display .0.0, RED led
sw $k1, 0($k0) # write to 7 segment display
hexit: j hexit # wait forever
......
......@@ -49,17 +49,17 @@ int main(void) {
LCDtopLine();
LCDput(' ');
LCDput('h');
LCDput('e');
LCDput('l');
LCDput('l');
LCDput('o');
LCDput(' ');
LCDput('w');
LCDput('o');
LCDput('r');
LCDput('l');
LCDput('d');
LCDput('p');
LCDput('-');
LCDput('b');
LCDput('a');
LCDput('c');
LCDput('k');
LCDput('?');
LCDput(' ');
#else
to_stdout('\n');
#endif
......@@ -77,7 +77,7 @@ int main(void) {
// let us see the state
state = uart->cs.stat.rxFull;
LCDgotoxy(14,1);
LCDchar((unsigned char)state);
LCDbyte((unsigned char)state);
DSP7SEGput( state>>4 , 0, state & 0xf, 0, 4);
s = '0'; // start transmission from '0'
......@@ -86,7 +86,7 @@ int main(void) {
while ( ( state = uart->cs.stat.txEmpty ) == 0 ) {
i = i+1;
LCDgotoxy(14,1);
LCDchar((unsigned char)state);
LCDbyte((unsigned char)state);
DSP7SEGput( state>>4 , 0, state & 0xf, 0, i & 0x07);
};
uart->d.tx = (int)s; // send out char
......
//========================================================================
// UART transmit functional test
// Linux computer must be connected via USB-serial (/dev/ttyUSB0)
// and must run minicom @ 115.200 bps
// and must run putty @ 9.600 bps
// If all is well, minicom's screen shows, forever, '0'..'9''\n'...
//========================================================================
#include "cMIPS.h"
typedef struct control { // control register fields (uses only ls byte)
int ign : 24, // ignore uppermost bits
rts : 1, // Request to Send
ign2 : 2, // bits 6,5 ignored
intTX : 1, // interrupt on TX buffer empty (bit 4)
intRX : 1, // interrupt on RX buffer full (bit 3)
speed : 3; // 4,8,16..256 tx-rx clock data rates (bits 0..2)
} Tcontrol;
typedef struct status { // status register fields (uses only ls byte)
int s;
// int ign : 24, // ignore uppermost bits
// ign7 : 1, // ignored (bit 7)
// txEmpty : 1, // TX register is empty (bit 6)
// rxFull : 1, // octet available from RX register (bit 5)
// int_TX_empt: 1, // interrupt pending on TX empty (bit 4)
// int_RX_full: 1, // interrupt pending on RX full (bit 3)
// ign2 : 1, // ignored (bit 2)
// framing : 1, // framing error (bit 1)
// overun : 1; // overun error (bit 0)
} Tstatus;
#define RXfull 0x00000020
#define TXempty 0x00000040
typedef union ctlStat { // control + status on same address
Tcontrol ctl; // write-only
Tstatus stat; // read-only
} TctlStat;
typedef union data { // data registers on same address
int tx; // write-only
int rx; // read-only
} Tdata;
typedef struct serial {
TctlStat cs;
Tdata d;
} Tserial;
#include "uart_defs.c"
#if 0
char s[32]; // = "the quick brown fox jumps over the lazy dog";
char s[64] = "the quick brown fox jumps over the lazy dog";
#else
// char s[32]; // = " ";
#endif
int main(void) { // receive a string through the UART serial interface
void main(void) { // receive a string through the UART serial interface
// and write it to the LCD display
volatile Tserial *uart; // tell GCC not to optimize away code
volatile Tstatus status;
Tcontrol ctrl;
int i,n;
int i,n,z, DELAY;
int state;
char c, s[32];
char c,d; // , s[32];
LCDinit();
LCDtopLine();
LCDput(' ');
LCDput('c');
LCDput('M');
LCDput('I');
LCDput('P');
LCDput('S');
LCDput(' ');
LCDput('s');
LCDput('a');
LCDput('y');
LCDput('s');
LCDput(' ');
LCDput('h');
LCDput('i');
LCDput('!');
LCDbotLine();
uart = (void *)IO_UART_ADDR; // bottom of UART address range
ctrl.ign = 0;
ctrl.rts = 0;
ctrl.rts = 1;
ctrl.ign2 = 0;
ctrl.intTX = 0;
ctrl.intRX = 0;
ctrl.speed = 3;
ctrl.speed = 7; // 9.600 bps
uart->cs.ctl = ctrl;
//
// let us try with a long delay between consecutive characters
//
c = '0';
n = 0;
n = z = 0;
DELAY = 2500; // wait 2ms == 2 character times, at 9,600baud
do {
while ( ( (state = uart->cs.stat.s) & TXempty ) == 0 )
;
do {
delay_us(1); // just do something so gcc won't optimize this away
status = uart->cs.stat;
} while ( status.txEmpty == 0 );
uart->d.tx = (int)c;
DSP7SEGput( state>>4 , 0, state & 0xf, 0);
LCDput(c);
DSP7SEGput( (int)status.txEmpty, 0, (int)status.rxFull, 0, 0);
LCDgotoxy(8,1);
LCDbyte(state);
LCDgotoxy(11,1);
LCDputc(c);
n += 1;
z += 1;
c = (char)((int)c + 1);
cmips_delay(6125000);
delay_us(DELAY);
if( status.rxFull == 1 ) {
d = uart->d.rx;
LCDgotoxy(11,2);
LCDputc(c);
}
if ( n == 10 ) {
while ( ( (state = uart->cs.stat.s) & TXempty ) == 0 )
;
uart->d.tx = (int)(0x0a);
while ( ( (state = uart->cs.stat.s) & TXempty ) == 0 )
;
uart->d.tx = (int)(0x00);
LCDbotLine();
while ( uart->cs.stat.txEmpty == 0 )
{ delay_us(1); } // do something
uart->d.tx = (int)('\n');
delay_us(DELAY);
c = '0';
n = 0;
}
} while (1 == 1);
} while (z < 100);
//
// let us try with a short delay between consecutive characters
//
c = 'a';
n = z = 0;
DELAY = 5; // wait 5us == 1/200 character times, at 9,600baud
do {
do {
delay_us(1); // just do something so gcc won't optimize this away
status = uart->cs.stat;
} while ( status.txEmpty == 0 );
uart->d.tx = (int)c;
DSP7SEGput( (int)status.txEmpty, 0, (int)status.rxFull, 0, 0);
LCDgotoxy(8,1);
LCDbyte(state);
LCDgotoxy(11,1);
LCDputc(c);
n += 1;
z += 1;
c = (char)((int)c + 1);
delay_us(DELAY);
if( status.rxFull == 1 ) {
d = uart->d.rx;
LCDgotoxy(11,2);
LCDputc(c);
}
if ( n == 10 ) {
while ( uart->cs.stat.txEmpty == 0 )
{ delay_us(1); } // do something
uart->d.tx = (int)('\n');
delay_us(DELAY);
c = 'a';
n = 0;
}
} while (z < 100);
return 0;
exit(0);
}
......@@ -7,10 +7,11 @@
## Cause an exception by referencing an unmapped address and
## then check BadVPN2
##
##
## EntryHi : EntryLo0 : EntryLo1
## VPN2 g ASID : PPN0 ccc0 d0 v0 g0 : PPN1 ccc1 d1 v1 g1
##
.include "cMIPS.s"
.set MMU_CAPACITY, 8
......@@ -45,7 +46,7 @@ _start:
##
##================================================================
## exception vector_0180 TLBrefill, from See MIPS Run pg 145
## exception vector_0180 TLBrefill, from "See MIPS Run" pg 145
##
.org x_EXCEPTION_0180,0
.set noreorder
......@@ -99,7 +100,9 @@ main: la $31, x_IO_BASE_ADDR
li $30, 'o'
sw $30, x_IO_ADDR_RANGE($31)
li $30, 'k'
li $30, 'k
sw $30, x_IO_ADDR_RANGE($31)
li $30, '1'
j next1
sw $30, x_IO_ADDR_RANGE($31)
......@@ -108,8 +111,9 @@ error1: li $30, 'e'
li $30, 'r'
sw $30, x_IO_ADDR_RANGE($31)
sw $30, x_IO_ADDR_RANGE($31)
li $30, '1'
sw $30, x_IO_ADDR_RANGE($31)
next1: li $30, '\n'
sw $30, x_IO_ADDR_RANGE($31)
......@@ -134,6 +138,8 @@ next1: li $30, '\n'
li $30, 'o'
sw $30, x_IO_ADDR_RANGE($31)
li $30, 'k'
sw $30, x_IO_ADDR_RANGE($31)
li $30, '2'
j next2
sw $30, x_IO_ADDR_RANGE($31)
......@@ -142,6 +148,8 @@ error2: li $30, 'e'
li $30, 'r'
sw $30, x_IO_ADDR_RANGE($31)
sw $30, x_IO_ADDR_RANGE($31)
li $30, '2'
sw $30, x_IO_ADDR_RANGE($31)
next2: li $30, '\n'
sw $30, x_IO_ADDR_RANGE($31)
......@@ -172,8 +180,7 @@ next2: li $30, '\n'
ehb # clear hazards
nop
nop
move $28, $zero
nop
la $8, x_DATA_BASE_ADDR # cause the exception: TLBinvalid
sw $zero, 0($8)
......@@ -186,15 +193,18 @@ next2: li $30, '\n'
nop
mfc0 $28, cop0_Context
# sw $28, 0($31)
#sw $28, 0($31)
la $27, 0xffff0000 | (x_DATA_BASE_ADDR >>9)
nop
bne $28, $27, error3
nop
li $30, 'o'
sw $30, x_IO_ADDR_RANGE($31)
li $30, 'k'
sw $30, x_IO_ADDR_RANGE($31)
li $30, '3'
j next3
sw $30, x_IO_ADDR_RANGE($31)
......@@ -203,7 +213,8 @@ error3: li $30, 'e'
li $30, 'r'
sw $30, x_IO_ADDR_RANGE($31)
sw $30, x_IO_ADDR_RANGE($31)
li $30, '3'
sw $30, x_IO_ADDR_RANGE($31)
next3: li $30, '\n'
sw $30, x_IO_ADDR_RANGE($31)
......@@ -220,6 +231,8 @@ next3: li $30, '\n'
li $30, 'o'
sw $30, x_IO_ADDR_RANGE($31)
li $30, 'k'
li $30, '4'
sw $30, x_IO_ADDR_RANGE($31)
j next4
sw $30, x_IO_ADDR_RANGE($31)
......@@ -228,6 +241,8 @@ error4: li $30, 'e'
li $30, 'r'
sw $30, x_IO_ADDR_RANGE($31)
sw $30, x_IO_ADDR_RANGE($31)
li $30, '4'
sw $30, x_IO_ADDR_RANGE($31)
next4: li $30, '\n'
sw $30, x_IO_ADDR_RANGE($31)
......
......@@ -347,7 +347,7 @@ begin
i_ena <= data_inp(31) when (sel='0' and wr='0') else int_en;
U_INTERR_EN: FFDsimple port map (clk, rst, i_ena, int_en);
equals <= '1' when (Q = Qlimit(NUM_BITS-1 downto 0)) else '0';
equals <= '1' when (Q = Qlimit) else '0';
irq <= '1' when (equals = '1' and int_en = '1') else '0';
......@@ -605,6 +605,7 @@ architecture behavioral of read_keys is
type kbd_state is (st_idle, st_start, st_wait, st_load, st_release);
signal kbd_current_st, kbd_next_st : kbd_state;
attribute SYN_ENCODING of kbd_state : type is "safe";
-- signal kbd_dbg_st : integer; -- debugging only
signal cnt_ld, cnt_en, new_ld : std_logic;
......
......@@ -93,38 +93,41 @@ architecture estrutural of uart_int is
-- state machine for transmission-CPU interface
type txcpu_state is (st_idle, st_check, st_done);
signal txcpu_current_st, txcpu_next_st : txcpu_state;
attribute SYN_ENCODING of txcpu_state : type is "safe";
-- state machine for transmission circuit
type tx_state is (st_idle, st_check, st_start,
st_b0, st_b1, st_b2, st_b3, st_b4, st_b5, st_b6, st_b7,
st_stop, st_done);
st_stop, st_end, st_done);
signal tx_current_st, tx_next_st : tx_state;
attribute SYN_ENCODING of tx_state : type is "safe";
-- state machine for reception-CPU interface
type rxcpu_state is (st_idle, st_copy, st_check, st_error);
signal rxcpu_current_st, rxcpu_next_st : rxcpu_state;
attribute SYN_ENCODING of rxcpu_state : type is "safe";
-- state machine for reception circuit
type rx_state is (st_idle, st_check, st_start,
st_b0, st_b1, st_b2, st_b3, st_b4, st_b5, st_b6, st_b7,
st_stop, st_done);
signal rx_current_st, rx_next_st : rx_state;
attribute SYN_ENCODING of rx_state : type is "safe";
-- for debugging only
signal tx_dbg_st, txcpu_dbg_st, rx_dbg_st, rxcpu_dbg_st : integer;
signal ctrl, status, txreg, rxreg, received : reg8;
signal tx_bit_rt, rx_bit_rt : std_logic;
signal tx_ld, tx_shift, tx_next, tx_bfr_empt, tx_shr_full, en_tx_clk, txclk : std_logic;
signal rx_ld, rx_shift, rx_next, rx_bfr_full, en_rx_clk, rx_done, rxclk : std_logic;
signal txclk_rise : std_logic;
signal rxclk_fall, rxclk_rise, rxdat_1to0, rxdat_new, rxdat_int, rxdat_old : std_logic;
signal en_tx_clk, txclk, txclk_rise : std_logic;
signal tx_ld, tx_shift, tx_next, tx_bfr_empt, tx_shr_full : std_logic;
signal rx_ld, rx_shift, rx_next, rx_bfr_full : std_logic;
signal rxdat_1to0, rxdat_new, rxdat_int, rxdat_old : std_logic;
signal rxclk_fall, rxclk_rise, en_rx_clk, rx_done, rxclk : std_logic;
signal a_overrun, a_framing, sel_delayed, reset_rxck : std_logic;
signal sta_xmit_sto, sta_recv_sto : reg10;
signal err_overrun, err_framing : std_logic;
signal rx_int_set, interr_RX_full, tx_int_set, interr_TX_empty : std_logic;
signal d_int_tx_empty, d_rx_int_set, d_err_framing, d_err_overrun : std_logic;
signal tx_baud_div, rx_baud_div : integer := 0;
......@@ -136,7 +139,7 @@ begin
rts <= ctrl(7);
-- testing only: tells remote unit of transmission speed
-- for testing only: tells remote unit what is the transmission speed
bit_rt <= ctrl(2 downto 0);
U_ctrl: register8 port map (clk,rst, s_ctrl, d_inp(7 downto 0), ctrl);
......@@ -150,10 +153,11 @@ begin
U_delay: FFDsimple port map (clk, rst, s_stat, sel_delayed);
-- TRANSMISSION ===========================================================
-- txreg is updated under the assumption that SW checked TXempty beforehand
U_txreg: register8 port map (clk,rst, s_tx, d_inp(7 downto 0), txreg);
sta_xmit_sto <= '1'& txreg & '0'; -- start (b0), octet, stop (b9)
sta_xmit_sto <= '1' & txreg & '0'; -- start (b0), octet, stop (b9)
tx_next <= txclk_rise and tx_shift;
U_transmit: par_ser10 port map (clk, rst, tx_ld, tx_next,
sta_xmit_sto, txdat);
......@@ -295,10 +299,16 @@ begin
end if;
when st_stop =>
if txclk_rise = '1' then
tx_next_st <= st_done;
tx_next_st <= st_end;
else
tx_next_st <= st_stop;
end if;
when st_end =>
if txclk_rise = '1' then -- wait for stop-bit to end
tx_next_st <= st_done;
else
tx_next_st <= st_end;
end if;
when st_done =>
tx_next_st <= st_idle;
when others =>
......@@ -319,7 +329,7 @@ begin
tx_shift <= '0';
tx_shr_full <= '1';
en_tx_clk <= '1';
when st_start | st_b0 | st_b1 | st_b2 | st_b3 | st_b4 | st_b5 | st_b6 | st_b7 | st_stop =>
when st_start | st_b0 | st_b1 | st_b2 | st_b3 | st_b4 | st_b5 | st_b6 | st_b7 | st_stop | st_end =>
tx_shift <= '1';
tx_shr_full <= '1';
en_tx_clk <= '1';
......@@ -560,9 +570,9 @@ begin
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
2604/2 when others;
-- 2604/2 when others;
-- 3472/2 when b"110",
-- 5208/2 when others;
5208/2 when others;
-- 000: 1/4 CPU clock rate -- for VHDL/C debugging only
......@@ -572,11 +582,11 @@ begin
-- 100: 57.600 baud
-- 101: 38.400 baud
-- 110: 28.800 baud
-- 111: 19.200 baud
-- 111: 9.600 baus -- 19.200 baud
-- max divisor would be 50,000,000 / 1,200 bps = 46.667 < 64k-1
U_bit_rt_tx: process(clk, rst, tx_ld, en_tx_clk)
variable baud_cnt : integer range 0 to 50000000;
variable baud_cnt : integer range 0 to 65535;
begin
if rst = '0' then
baud_cnt := 0;
......@@ -612,12 +622,12 @@ begin
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
2604/2 when others;
-- 2604/2 when others;
-- 3472/2 when b"110",
-- 5208/2 when others;
5208/2 when others;
U_bit_rt_rx: process(clk, rst, reset_rxck, en_rx_clk)
variable baud_cnt : integer range 0 to 50000000;
variable baud_cnt : integer range 0 to 65535;
begin
if rst = '0' then
baud_cnt := 0;
......@@ -790,6 +800,7 @@ architecture behavior of remota is
st_stop, st_wait, st_done);
signal tx_current_st, tx_next_st : tx_state;
signal tx_dbg_st : integer; -- for debugging only
attribute SYN_ENCODING of tx_state : type is "safe";
signal tx_bit_rt : reg8;
signal tx_clk, tx_run : std_logic;
......@@ -804,6 +815,7 @@ architecture behavior of remota is
st_stop, st_done);
signal rx_current_st, rx_next_st : rx_state;
signal rx_dbg_st : integer; -- for debugging only
attribute SYN_ENCODING of rx_state : type is "safe";
signal recv, rx_bit_rt : reg8;
signal rx_clk, rx_run, reset_rxck : std_logic;
......@@ -1054,9 +1066,9 @@ begin
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
2604/2 when others;
-- 2604/2 when others;
-- 3472/2 when b"110",
-- 5208/2 when others;
5208/2 when others;
U_bit_rt_tx: process(clk, rst)
variable baud_cnt : integer;
......@@ -1084,9 +1096,9 @@ begin
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
2604/2 when others;
-- 2604/2 when others;
-- 3472/2 when b"110",
-- 5208/2 when others;
5208/2 when others;
U_bit_rt_rx: process(clk, rst, reset_rxck, rx_run)
variable baud_cnt : integer;
......
Markdown is supported
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