diff --git a/cMIPS/bin/compile.sh b/cMIPS/bin/compile.sh index 0bc781eedc64c4bd481b4c52c411a947e7cbd8fe..2b0ef9afb510be89a5b0ed1e7cd92a52af972b55 100755 --- a/cMIPS/bin/compile.sh +++ b/cMIPS/bin/compile.sh @@ -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\ diff --git a/cMIPS/include/cMIPS.h b/cMIPS/include/cMIPS.h index ecf0eeee4e878b0ad51fc90ce18538fc62345eb4..4a60af9678a0b82a2392f8c2a6241e75697f93a7 100644 --- a/cMIPS/include/cMIPS.h +++ b/cMIPS/include/cMIPS.h @@ -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); diff --git a/cMIPS/include/cMIPSio.c b/cMIPS/include/cMIPSio.c index c21a1b07327782a410e4277cc9e7668c99f7b878..e6b3feb5dc8e74e99990f41f62a301c7c217ad58 100644 --- a/cMIPS/include/cMIPSio.c +++ b/cMIPS/include/cMIPSio.c @@ -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); diff --git a/cMIPS/include/syn_start.s b/cMIPS/include/syn_start.s index bb87e8878ddfac861f47c1d287e63e00631f4af1..e147b9552b9742642531bb53af90dc80d1821ade 100644 --- a/cMIPS/include/syn_start.s +++ b/cMIPS/include/syn_start.s @@ -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 diff --git a/cMIPS/tests/mac_uart_lb.c b/cMIPS/tests/mac_uart_lb.c index 0a6ece38c675ed45ec2893d6f736d7cee8b50109..616d4fb81d23d9135f5de875fcade06f0d73c374 100644 --- a/cMIPS/tests/mac_uart_lb.c +++ b/cMIPS/tests/mac_uart_lb.c @@ -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 diff --git a/cMIPS/tests/mac_uart_tx.c b/cMIPS/tests/mac_uart_tx.c index 9e2c6ed065b4bfd20ffce9c47bc536fbbaae9cb0..d15226adb790cf6e3f253364b15b34ecd21066a0 100644 --- a/cMIPS/tests/mac_uart_tx.c +++ b/cMIPS/tests/mac_uart_tx.c @@ -1,131 +1,150 @@ //======================================================================== // 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); } diff --git a/cMIPS/tests/mmu_context.s b/cMIPS/tests/mmu_context.s index 0b6e554d3bfc44647ae8ba78283963c96d79476d..542686d80fe7f18e44780db341d8843c5ee20db5 100644 --- a/cMIPS/tests/mmu_context.s +++ b/cMIPS/tests/mmu_context.s @@ -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) diff --git a/cMIPS/vhdl/io.vhd b/cMIPS/vhdl/io.vhd index ece5e4df23a8845ce794d00194d12a369e98f680..c9714fcce6b5f5dbf6ec5462e6be56f25a0a570d 100644 --- a/cMIPS/vhdl/io.vhd +++ b/cMIPS/vhdl/io.vhd @@ -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; diff --git a/cMIPS/vhdl/uart.vhd b/cMIPS/vhdl/uart.vhd index a25b953e90bc9f534915ff43c9004ecfd3df34a6..04f99d00cbf7c61b32de390054e7d6265fee04f1 100644 --- a/cMIPS/vhdl/uart.vhd +++ b/cMIPS/vhdl/uart.vhd @@ -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;