Commit 7d7f7d03 authored by Roberto Hexsel's avatar Roberto Hexsel

changes to STATUS.IE delay IRQs to avoi hazards. new baud rates for UART

parent 1ffcdd18
......@@ -26,6 +26,7 @@ unset WAVE
length=1
unit=m
gtkwconf=pipe
synth=
touch input.data input.txt serial.inp
......@@ -42,6 +43,7 @@ OPTIONS:
-n send simulator output do /dev/null, else to v_cMIPS.vcd
-w invoke GTKWAVE -- stdin will not read input from keyboard
-v F gtkwave configuration file (e.g. pipe.sav, default v.sav)
-syn run simulation with synthesis RAM/ROM addresses
EOF
}
......@@ -60,6 +62,8 @@ while true ; do
;;
-w) WAVE=true
;;
-syn | -mif ) synth="-syn"
;;
-v) gtkwconf=$2
shift
;;
......@@ -78,7 +82,7 @@ gfile=${gtkwconf%%.sav}
sav="${tree}"/${gfile}.sav
"${bin}"/build.sh || exit 1
"${bin}"/build.sh $synth || exit 1
options="--ieee-asserts=disable --stop-time=${length}${unit}s --vcd=${visual}"
......
......@@ -22,12 +22,13 @@
#define IO_DSP7SEG_ADDR (x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE)
#define IO_KEYBD_ADDR (x_IO_BASE_ADDR +10 * x_IO_ADDR_RANGE)
#define IO_LCD_ADDR (x_IO_BASE_ADDR +11 * x_IO_ADDR_RANGE)
#define IO_SDCARD_ADDR (x_IO_BASE_ADDR +12 * x_IO_ADDR_RANGE)
#define IO_SDC_ADDR (x_IO_BASE_ADDR +12 * x_IO_ADDR_RANGE)
extern void exit(int);
extern void cmips_delay(int);
extern void delay_cycle(int);
extern void delay_us(int);
extern void delay_ms(int);
......@@ -79,6 +80,11 @@ extern void DSP7SEGput(int, int, int, int, int);
extern int KBDget(void);
extern int SWget(void);
// RGB led color for DSP7SEGput (color must be in [0,7]
#define l_RED 0x4
#define l_GREEN 0x2
#define l_BLUE 0x1
// struct to access the cache system statistics "peripheral"
typedef struct sStats {
......
......@@ -19,7 +19,7 @@
.set HW_dsp7seg_addr,(x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE)
.set HW_keybd_addr, (x_IO_BASE_ADDR + 10 * x_IO_ADDR_RANGE)
.set HW_lcd_addr, (x_IO_BASE_ADDR + 11 * x_IO_ADDR_RANGE)
.set HW_SDcard_addr, (x_IO_BASE_ADDR + 12 * x_IO_ADDR_RANGE)
.set HW_sdc_addr, (x_IO_BASE_ADDR + 12 * x_IO_ADDR_RANGE)
# see vhdl/packageMemory.vhd for addresses
.set x_EXCEPTION_0000,0x00000130
......
......@@ -69,21 +69,23 @@ extCounter:
# interrupt handler for UART attached to IP6=HW4
# for UART's address see vhdl/packageMemory.vhd
#
.global Ud, _uart_buff
.bss
.align 2
.global Ud
Ud:
rx_hd: .space 4
rx_tl: .space 4
rx_q: .space 16 # reception queue and pointers
tx_hd: .space 4
tx_tl: .space 4
tx_q: .space 16 # transmission queue and pointers
rx_hd: .space 4 # reception queue head index
rx_tl: .space 4 # tail index
rx_q: .space 16 # reception queue
tx_hd: .space 4 # transmission queue head index
tx_tl: .space 4 # tail index
tx_q: .space 16 # transmission queue
nrx: .space 4 # characters in RX_queue
ntx: .space 4 # spaces left in TX_queue
_uart_buff: .space 16*4 # up to 16 registers to be saved here
# _uart_buff[0]=UARTstatus, [1]=UARTcontrol, [2]=data_inp, [3]=new,
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
.set UART_rx_irq,0x08
.set UART_tx_irq,0x10
......@@ -91,9 +93,6 @@ _uart_buff: .space 16*4 # up to 16 registers to be saved here
.set noreorder
.global UARTinterr
.ent UARTinterr
# _uart_buff[0]=UARTstatus, [1]=UARTcontrol, [2]=data_inp, [3]=new,
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
UARTinterr:
lui $k0, %hi(_uart_buff) # get buffer's address
......@@ -101,12 +100,12 @@ UARTinterr:
sw $a0, 5*4($k0) # save registers $a0,$a1, others?
sw $a1, 6*4($k0)
sw $a2, 7*4($k0)
lui $a0, %hi(HW_uart_addr)# get device's address
ori $a0, $a0, %lo(HW_uart_addr)
lw $k1, 0($a0) # Read status, remove interrupt request
nop
sw $k1, 0*4($k0) # and save UART status to memory
#----------------------------------
......@@ -121,12 +120,16 @@ UARTinterr:
# handle reception
lw $a1, 4($a0) # Read data from device
nop # and store it to UART's buffer
sw $a1, 2*4($k0) # and return from interrupt
lui $a2, %hi(Ud) # get address for data & flag
ori $a2, $a2, %lo(Ud)
sw $a1, 0*4($a2) # and return from interrupt
addiu $a1, $zero, 1
sw $a1, 3*4($k0) # Signal new arrival
sw $a1, 1*4($a2) # set flag to signal new arrival
UARTret:
lw $a2, 7*4($k0)
lw $a1, 6*4($k0) # restore registers $a0,$a1, others?
lw $a0, 5*4($k0)
......@@ -153,6 +156,7 @@ countCompare:
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status # except for re-enabling interrupts
ehb
eret # Return from interrupt
.end countCompare
#----------------------------------------------------------------
......@@ -171,8 +175,10 @@ startCount:
lui $v1, 0xf7ff
ori $v1, $v1, 0xffff
and $v0, $v0, $v1
jr $ra
mtc0 $v0, c0_cause
ehb
jr $ra
nop
.end startCount
#----------------------------------------------------------------
......@@ -220,7 +226,7 @@ enableInterr:
mfc0 $v0, c0_status # Read STATUS register
ori $v0, $v0, 1 # and enable interrupts
mtc0 $v0, c0_status
nop
ehb
jr $ra # return updated STATUS
nop
.end enableInterr
......@@ -231,7 +237,7 @@ disableInterr:
addiu $v1, $zero, -2 # and disable interrupts
and $v0, $v0, $v1 # -2 = 0xffff.fffe
mtc0 $v0, c0_status
nop
ehb
jr $ra # return updated STATUS
nop
.end disableInterr
......@@ -481,11 +487,13 @@ pu_miss: jr $ra
.ent cmips_delay
delay_cycle:
cmips_delay:
addiu $a0, $a0, -1
beq $a0, $zero, _d_cye
nop
_d_cy: addiu $a0, $a0, -1
nop
bne $a0, $zero, cmips_delay
bne $a0, $zero, _d_cy
nop
jr $ra
_d_cye: jr $ra
nop
.end cmips_delay
#----------------------------------------------------------------
......@@ -498,6 +506,8 @@ cmips_delay:
.set noreorder
.ent delay_us
delay_us:
beq $a0, $zero, _d_use
nop
li $v0, 10
mult $v0, $a0
nop
......@@ -508,7 +518,7 @@ _d_us: addiu $a0, $a0, -1
nop
bne $a0, $zero, _d_us
nop
jr $ra
_d_use: jr $ra
nop
.end delay_us
#----------------------------------------------------------------
......@@ -522,6 +532,8 @@ _d_us: addiu $a0, $a0, -1
.set noreorder
.ent delay_ms
delay_ms:
beq $a0, $zero, _d_mse
nop
li $v0, 10000
mul $a0, $v0, $a0
nop
......@@ -530,7 +542,7 @@ _d_ms: addiu $a0, $a0, -1
nop
bne $a0, $zero, _d_ms
nop
jr $ra
_d_mse: jr $ra
nop
.end delay_ms
#----------------------------------------------------------------
......
......@@ -24,19 +24,22 @@ void main(void) {
LCDtopLine();
#if 1
LCDput('c');
LCDput('M');
LCDput('I');
LCDput('P');
LCDput('S');
LCDput(' ');
LCDput('H');
LCDput('t');
LCDput('i');
LCDput('m');
LCDput('e');
LCDput('l');
LCDput('l');
LCDput('o');
LCDput(' ');
LCDput('w');
LCDput('o');
LCDput('r');
LCDput('l');
LCDput('d');
LCDput('!');
LCDput('[');
LCDput('h');
LCDput('e');
LCDput('x');
LCDput(']');
#else
LCDprint( print_sp() ); // for debugging only
#endif
......
......@@ -13,18 +13,20 @@
#include "uart_defs.c"
extern int _uart_buff[16]; // declared in include/handlers.s
#define U_DATA 0
#define U_FLAG 1
#define SPEED 2 // operate at 1/4 of the highest data rate
int main(void) { // receive a string through the UART serial interface
int main(void) { // receive a string through the UART serial interface
volatile Tserial *uart; // tell GCC not to optimize away code
Tcontrol ctrl;
volatile int *bfr = &(_uart_buff[0]);
extern int Ud[2]; // declared in include/handlers.s
volatile int *bfr;
volatile char c;
bfr = (int *)Ud;
uart = (void *)IO_UART_ADDR; // bottom of UART address range
ctrl.ign = 0;
......@@ -36,7 +38,7 @@ int main(void) { // receive a string through the UART serial interface
// handler sets flag=bfr[3] to 1 after new character is received;
// this program resets the flag on fetching a new character from buffer
bfr[3] = 0; // reset flag
bfr[U_FLAG] = 0; // reset flag
ctrl.ign = 0;
ctrl.rts = 1; // make RTS=1 to activate remote unit
......@@ -46,12 +48,12 @@ int main(void) { // receive a string through the UART serial interface
uart->cs.ctl = ctrl;
do {
while ( (c = (char)bfr[3]) == 0 )
{}; // nothing new
c = (char)bfr[2]; // get new character
bfr[3] = 0; // and reset flag
to_stdout( (int)c ); // and print new char
} while (c != '\0'); // end of string?
while ( (c = (char)bfr[U_FLAG]) == 0 ) // check flag in Ud[1]
{}; // nothing new
c = (char)bfr[U_DATA]; // get new character
bfr[U_FLAG] = 0; // and reset flag
to_stdout( (int)c ); // and print new char
} while (c != '\0'); // end of string?
return c;
......
This diff is collapsed.
......@@ -1809,8 +1809,17 @@ begin
-- delay the IRQ to make sure the interrupted instruction completes;
-- This is needed to ensure forward-progress: at least one instruction
-- must complete before another interrupt may be taken.
-- Also, delay the interrupt requests to avoid hazards while
-- the interrupt-enable bit is changed in the STATUS register.
dly_i0 <= '1' when is_exception = exERET else '0';
dly_i0 <= '1' when ( (EX_exception = exERET) or -- forward progress
(EX_exception = exEI) or -- interrupt hazard
(EX_exception = exDI) or -- interrupt hazard
(EX_exception = exEHB) or -- interrupt hazard
(EX_exception = exMTC0 -- interrupt hazard
and EX_cop0_reg = cop0reg_STATUS) ) else
'0';
U_DLY_INT1: FFD port map (clk, rst, '1',dly_i0, dly_i1);
U_DLY_INT2: FFD port map (clk, rst, '1',dly_i1, dly_i2);
dly_interr <= dly_i0 or dly_i1 or dly_i2;
......@@ -1864,7 +1873,7 @@ begin
-- STATUS -- pg 79 -- cop0_12 --------------------
COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS:
process (MM_a_rt, is_exception, cop0_inp,
MM_cop0_reg, MM_cop0_sel, MM_int_req,
MM_cop0_reg, MM_cop0_sel,
RF_is_delayslot, EX_is_delayslot, MM_is_delayslot, WB_is_delayslot,
rom_stall,ram_stall, MM_is_mfc0,
INDEX, RANDOM, EntryLo0, EntryLo1, CONTEXT, PAGEMASK, WIRED,
......
......@@ -977,14 +977,14 @@ entity SDcard is
sel : in std_logic;
rdy : out std_logic;
wr : in std_logic;
addr : in reg2; -- a03, a02
addr : in reg2; -- a03, a02
data_inp : in reg32;
data_out : out reg32;
sdc_cs : out std_logic; -- SDcard chip-select
sdc_clk : out std_logic; -- SDcard serial clock
sdc_mosi_o : out std_logic; -- SDcard serial data out (to card)
sdc_mosi_i : in std_logic; -- SDcard serial data inp (fro card)
irq : out std_logic); -- interrupt request (not yet used)
sdc_cs : out std_logic; -- SDcard chip-select
sdc_clk : out std_logic; -- SDcard serial clock
sdc_mosi_o : out std_logic; -- SDcard serial data out (to card)
sdc_miso_i : in std_logic; -- SDcard serial data inp (fro card)
irq : out std_logic); -- interrupt request (not yet used)
end SDCard;
architecture behavioral of SDcard is
......@@ -1033,27 +1033,30 @@ architecture behavioral of SDcard is
cs_bo : out std_logic; -- Active-low chip-select.
sclk_o : out std_logic; -- Serial clock to SD card.
mosi_o : out std_logic; -- Serial data output to SD card.
miso_i : in std_logic); -- Serial data input from SD card.
miso_i : in std_logic; -- Serial data input from SD card.
state : out std_logic_vector); -- state, debugging only
end component SdCardCtrl;
signal s_addr, s_stat, s_ctrl, s_read, s_write : std_logic;
signal continue, busy, hndShk_i, hndShk_o, wr_i, rd_i : std_logic;
signal wait1, waiting, new_trans, new_data_rd, sdc_rst : std_logic;
signal ctrl_err, set_wr_i, clr_wr_i, set_rd_i, clr_rd_i : std_logic;
signal ctrl_err, set_wr_i, set_rd_i : std_logic;
signal do_reset, do_reset1 : std_logic;
signal data_rd, data_rd_reg, data_wr_reg : reg8;
signal error_o : reg16;
signal addr_reg : reg32;
signal sel_data_out : reg3;
signal state : reg5;
signal w : reg5;
begin
U_SDcard: SdCardCtrl
generic map (50.0, 0.400, 25.0, 512, SD_CARD_E)
-- generic map (50.0, 0.400, 12.5, 512, SD_CARD_E)
generic map (50.0, 25.0, 25.0, 512, SD_CARD_E)
port map (clk, sdc_rst, rd_i, wr_i, '0', addr_reg,
data_wr_reg, data_rd, busy, hndshk_i, open, error_o,
-- data_wr_reg, data_rd, busy, hndshk_i, hndshk_o, error_o,
sdc_cs, sdc_clk, sdc_mosi_o, sdc_mosi_i);
sdc_cs, sdc_clk, sdc_mosi_o, sdc_miso_i, state);
hndshk_i <= waiting;
......@@ -1076,7 +1079,7 @@ begin
waiting <= w;
end process U_WAIT;
rdy <= not(wait1 or waiting); -- wait for 260ns
rdy <= not(wait1 or waiting); -- wait for controller
new_data_rd <= not(hndshk_o);
U_W1: FFDsimple port map (clk, rst, wait1, w(0));
......@@ -1103,25 +1106,21 @@ begin
s_write <= '0' when sel = '0' and addr = b"01" and wr = '0' else '1';
s_read <= '0' when sel = '0' and addr = b"01" and wr = '1' else '1';
s_ctrl <= '1' when sel = '0' and addr = b"10" and wr = '1' else '0';
s_ctrl <= '1' when sel = '0' and addr = b"10" and wr = '0' else '0';
s_stat <= '1' when sel = '0' and addr = b"11" and wr = '1' else '0';
do_reset <= '1' when s_ctrl = '1' and data_inp(4) = '1' else '0';
U_RESET1: FFDsimple port map (clk, rst, do_reset, do_reset1);
sdc_rst <= not(rst) or do_reset or do_reset1; -- held for 2 cycles
-- set_wr_i <= '1' when else '0';
-- clr_wr_i <= rst and s_write;
set_wr_i <= (s_ctrl and data_inp(0)) or (wr_i and s_write);
U_WR_STROBE: FFDsimple port map (clk, clr_wr_i, set_wr_i, wr_i);
sdc_rst <= not(rst) or do_reset or do_reset1; -- held HI for 2 cycles
-- set_rd_i <= '1' when s_ctrl = '1' and data_inp(1) = '1' else '0';
-- clr_rd_i <= rst and s_read;
-- hold wr_i active until first access to WR-register
set_wr_i <= ((s_ctrl and data_inp(0)) or (wr_i and s_write)) and s_write;
U_WR_STROBE: FFDsimple port map (clk, rst, set_wr_i, wr_i);
set_rd_i <= (s_ctrl and data_inp(1)) or (rd_i and s_read);
U_RD_STROBE: FFDsimple port map (clk, clr_rd_i, set_rd_i, rd_i);
-- hold rd_i active until first access to RD-register
set_rd_i <= ((s_ctrl and data_inp(1)) or (rd_i and s_read)) and s_read;
U_RD_STROBE: FFDsimple port map (clk, rst, set_rd_i, rd_i);
ctrl_err <= wr_i and rd_i; -- cannot both read AND write
......@@ -1140,7 +1139,7 @@ begin
data_out <= addr_reg when "000",
x"000000" & data_rd_reg when "001",
x"000000" & b"000" & ctrl_err & b"00" & rd_i & wr_i when "010",
busy & ctrl_err & b"00" & x"000" & error_o when "011",
busy & ctrl_err & b"00" & b"000" & state & x"0" & error_o when "011",
(others => 'X') when others;
end behavioral;
......
......@@ -41,13 +41,13 @@ architecture TB of tb_cMIPS is
sel : in std_logic;
rdy : out std_logic;
wr : in std_logic;
addr : in std_logic_vector; -- a03, a02
addr : in std_logic_vector; -- a03, a02
data_inp : in std_logic_vector;
data_out : out std_logic_vector;
sdc_cs : out std_logic; -- SDcard chip-select
sdc_clk : out std_logic; -- SDcard serial clock
sdc_mosi_o : out std_logic; -- SDcard serial data out (to card)
sdc_mosi_i : in std_logic; -- SDcard serial data inp (fro card)
sdc_miso_i : in std_logic; -- SDcard serial data inp (fro card)
irq : out std_logic); -- interrupt request (not yet used)
end component SDCard;
......@@ -477,7 +477,7 @@ architecture TB of tb_cMIPS is
signal LCD_DATA : std_logic_vector(7 downto 0); -- LCD data bus
signal LCD_RS, LCD_RW, LCD_EN, LCD_BLON : std_logic; -- LCD control
signal uart_txd, uart_rxd, uart_rts, uart_cts, uart_irq : std_logic;
signal sdc_cs, sdc_clk, sdc_mosi_o, sdc_mosi_i : std_logic;
signal sdc_cs, sdc_clk, sdc_mosi_o, sdc_miso_i : std_logic;
signal sdcke, sdscs, sdras, sdcas, sdwe : std_logic; -- SDRAM
......@@ -659,7 +659,7 @@ begin -- TB
U_sdcard: SDcard
port map (rst, clk, io_sdc_sel, io_sdc_wait,
wr, d_addr(3 downto 2), cpu_data, sdc_d_out,
sdc_cs, sdc_clk, sdc_mosi_o, sdc_mosi_i, open);
sdc_cs, sdc_clk, sdc_mosi_o, sdc_miso_i, open);
U_FPU: FPU
port map (rst,clk, io_FPU_sel, io_FPU_wait, wr, d_addr(5 downto 2),
......
......@@ -21,15 +21,16 @@
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- control register, least significant byte only
-- b0..b2: transmit/receive clock speed
-- b2..b0: transmit/receive clock speed
-- 000: 1/4 CPU clock rate -- for VHDL/C debugging only
-- 001: 1/8 CPU clock rate -- for VHDL/C debugging only
-- 010: 1/16 CPU clock rate -- for VHDL/C debugging only
-- 011: 115.200 baud
-- 100: 57.600 baud
-- 101: 38.400 baud
-- 110: 28.800 baud
-- 111: 19.200 baud
-- 011: 1/32 CPU clock rate -- for VHDL/C debugging only
-- 100: 230.400 baud
-- 100: 115.200 baud
-- 101: 57.600 baud
-- 110: 19.200 baud
-- 111: 9.600 baus
-- b3=1: signal interrupt on RX buffer full, when a new octet is available
-- b4=1: signal interrupt on TX buffer empty, when TX space is available
-- b5,b6: ignored, not used
......@@ -566,23 +567,22 @@ begin
tx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
-- 000: 1/4 CPU clock rate -- for VHDL/C debugging only
-- 001: 1/8 CPU clock rate -- for VHDL/C debugging only
-- 010: 1/16 CPU clock rate -- for VHDL/C debugging only
-- 011: 115.200 baud
-- 100: 57.600 baud
-- 101: 38.400 baud
-- 110: 28.800 baud
-- 111: 9.600 baus -- 19.200 baud
-- 011: 1/32 CPU clock rate -- for VHDL/C debugging only
-- 100: 230.400 baud
-- 100: 115.200 baud
-- 101: 57.600 baud
-- 110: 19.200 baud
-- 111: 9.600 baus
-- 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)
......@@ -618,13 +618,12 @@ begin
rx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
U_bit_rt_rx: process(clk, rst, reset_rxck, en_rx_clk)
variable baud_cnt : integer range 0 to 65535;
......@@ -1062,13 +1061,12 @@ begin
tx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
U_bit_rt_tx: process(clk, rst)
variable baud_cnt : integer;
......@@ -1092,13 +1090,12 @@ begin
rx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
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