URL
https://opencores.org/ocsvn/eco32/eco32/trunk
Subversion Repositories eco32
Compare Revisions
- This comparison shows the changes necessary to convert path
/eco32
- from Rev 26 to Rev 27
- ↔ Reverse comparison
Rev 26 → Rev 27
/trunk/fpga/eco32-29.tar.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
trunk/fpga/eco32-29.tar.gz
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: trunk/fpga/src/ram/ram.v
===================================================================
--- trunk/fpga/src/ram/ram.v (nonexistent)
+++ trunk/fpga/src/ram/ram.v (revision 27)
@@ -0,0 +1,326 @@
+module ram(clk, clk_ok, reset,
+ en, wr, size, addr,
+ data_in, data_out, wt,
+ sdram_cke, sdram_cs_n,
+ sdram_udqm, sdram_ldqm,
+ sdram_ras_n, sdram_cas_n,
+ sdram_we_n, sdram_ba,
+ sdram_a, sdram_dq);
+ input clk;
+ input clk_ok;
+ input reset;
+ input en;
+ input wr;
+ input [1:0] size;
+ input [24:0] addr;
+ input [31:0] data_in;
+ output reg [31:0] data_out;
+ output reg wt;
+ output sdram_cke;
+ output sdram_cs_n;
+ output sdram_udqm;
+ output sdram_ldqm;
+ output sdram_ras_n;
+ output sdram_cas_n;
+ output sdram_we_n;
+ output [1:0] sdram_ba;
+ output [12:0] sdram_a;
+ inout [15:0] sdram_dq;
+
+ reg [3:0] state;
+ reg a0;
+ reg cntl_read;
+ reg cntl_write;
+ wire cntl_done;
+ wire [23:0] cntl_addr;
+ reg [15:0] cntl_din;
+ wire [15:0] cntl_dout;
+
+ wire sd_out_en;
+ wire [15:0] sd_out;
+
+//--------------------------------------------------------------
+
+ sdramCntl sdramCntl1(
+ // clock
+ .clk(clk),
+ .clk_ok(clk_ok),
+ // host side
+ .rd(cntl_read & ~cntl_done),
+ .wr(cntl_write & ~cntl_done),
+ .done(cntl_done),
+ .hAddr(cntl_addr),
+ .hDIn(cntl_din),
+ .hDOut(cntl_dout),
+ // SDRAM side
+ .cke(sdram_cke),
+ .ce_n(sdram_cs_n),
+ .ras_n(sdram_ras_n),
+ .cas_n(sdram_cas_n),
+ .we_n(sdram_we_n),
+ .ba(sdram_ba),
+ .sAddr(sdram_a),
+ .sDIn(sdram_dq),
+ .sDOut(sd_out),
+ .sDOutEn(sd_out_en),
+ .dqmh(sdram_udqm),
+ .dqml(sdram_ldqm)
+ );
+
+ assign sdram_dq = (sd_out_en == 1) ? sd_out : 16'hzzzz;
+
+//--------------------------------------------------------------
+
+ // the SDRAM is organized in 16-bit halfwords
+ // address line 0 is controlled by the state machine
+ // this is necessary for word accesses
+ assign cntl_addr[23:1] = addr[24:2];
+ assign cntl_addr[0] = a0;
+
+ // state machine for SDRAM access
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ state <= 4'b0000;
+ wt <= 1;
+ end else begin
+ case (state)
+ 4'b0000:
+ // wait for access
+ begin
+ if (en == 1) begin
+ // access
+ if (wr == 1) begin
+ // write
+ if (size[1] == 1) begin
+ // write word
+ state <= 4'b0001;
+ end else begin
+ if (size[0] == 1) begin
+ // write halfword
+ state <= 4'b0101;
+ end else begin
+ // write byte
+ state <= 4'b0111;
+ end
+ end
+ end else begin
+ // read
+ if (size[1] == 1) begin
+ // read word
+ state <= 4'b0011;
+ end else begin
+ if (size[0] == 1) begin
+ // read halfword
+ state <= 4'b0110;
+ end else begin
+ // read byte
+ state <= 4'b1001;
+ end
+ end
+ end
+ end
+ end
+ 4'b0001:
+ // write word, upper 16 bits
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b0010;
+ end
+ end
+ 4'b0010:
+ // write word, lower 16 bits
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b1111;
+ wt <= 0;
+ end
+ end
+ 4'b0011:
+ // read word, upper 16 bits
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b0100;
+ data_out[31:16] <= cntl_dout;
+ end
+ end
+ 4'b0100:
+ // read word, lower 16 bits
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b1111;
+ data_out[15:0] <= cntl_dout;
+ wt <= 0;
+ end
+ end
+ 4'b0101:
+ // write halfword
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b1111;
+ wt <= 0;
+ end
+ end
+ 4'b0110:
+ // read halfword
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b1111;
+ data_out[31:16] <= 16'h0000;
+ data_out[15:0] <= cntl_dout;
+ wt <= 0;
+ end
+ end
+ 4'b0111:
+ // write byte (read halfword cycle)
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b1000;
+ data_out[31:16] <= 16'h0000;
+ data_out[15:0] <= cntl_dout;
+ end
+ end
+ 4'b1000:
+ // write byte (write halfword cycle)
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b1111;
+ wt <= 0;
+ end
+ end
+ 4'b1001:
+ // read byte
+ begin
+ if (cntl_done == 1) begin
+ state <= 4'b1111;
+ data_out[31:8] <= 24'h000000;
+ if (addr[0] == 0) begin
+ data_out[7:0] <= cntl_dout[15:8];
+ end else begin
+ data_out[7:0] <= cntl_dout[7:0];
+ end
+ wt <= 0;
+ end
+ end
+ 4'b1111:
+ // end of bus cycle
+ begin
+ state <= 4'b0000;
+ wt <= 1;
+ end
+ default:
+ // all other states: reset
+ begin
+ state <= 4'b0000;
+ wt <= 1;
+ end
+ endcase
+ end
+ end
+
+ // output of state machine
+ always @(*) begin
+ case (state)
+ 4'b0000:
+ // wait for access
+ begin
+ a0 = 1'bx;
+ cntl_read = 0;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ 4'b0001:
+ // write word, upper 16 bits
+ begin
+ a0 = 1'b0;
+ cntl_read = 0;
+ cntl_write = 1;
+ cntl_din = data_in[31:16];
+ end
+ 4'b0010:
+ // write word, lower 16 bits
+ begin
+ a0 = 1'b1;
+ cntl_read = 0;
+ cntl_write = 1;
+ cntl_din = data_in[15:0];
+ end
+ 4'b0011:
+ // read word, upper 16 bits
+ begin
+ a0 = 1'b0;
+ cntl_read = 1;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ 4'b0100:
+ // read word, lower 16 bits
+ begin
+ a0 = 1'b1;
+ cntl_read = 1;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ 4'b0101:
+ // write halfword
+ begin
+ a0 = addr[1];
+ cntl_read = 0;
+ cntl_write = 1;
+ cntl_din = data_in[15:0];
+ end
+ 4'b0110:
+ // read halfword
+ begin
+ a0 = addr[1];
+ cntl_read = 1;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ 4'b0111:
+ // write byte (read halfword cycle)
+ begin
+ a0 = addr[1];
+ cntl_read = 1;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ 4'b1000:
+ // write byte (write halfword cycle)
+ begin
+ a0 = addr[1];
+ cntl_read = 0;
+ cntl_write = 1;
+ if (addr[0] == 0) begin
+ cntl_din = { data_in[7:0], data_out[7:0] };
+ end else begin
+ cntl_din = { data_out[15:8], data_in[7:0] };
+ end
+ end
+ 4'b1001:
+ // read byte
+ begin
+ a0 = addr[1];
+ cntl_read = 1;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ 4'b1111:
+ // end of bus cycle
+ begin
+ a0 = 1'bx;
+ cntl_read = 0;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ default:
+ // all other states: reset
+ begin
+ a0 = 1'bx;
+ cntl_read = 0;
+ cntl_write = 0;
+ cntl_din = 16'hxxxx;
+ end
+ endcase
+ end
+
+endmodule
Index: trunk/fpga/src/ram/sdramcntl.vhd
===================================================================
--- trunk/fpga/src/ram/sdramcntl.vhd (nonexistent)
+++ trunk/fpga/src/ram/sdramcntl.vhd (revision 27)
@@ -0,0 +1,595 @@
+--------------------------------------------------------------------
+-- Company : XESS Corp.
+-- Engineer : Dave Vanden Bout
+-- Creation Date : 05/17/2005
+-- Copyright : 2005, XESS Corp
+-- Tool Versions : WebPACK 6.3.03i
+--
+-- Description:
+-- SDRAM controller
+--
+-- Revision:
+-- n.a. (because of hacking by Hellwig Geisse)
+--
+-- Additional Comments:
+-- 1.4.0:
+-- Added generic parameter to enable/disable independent active rows in each bank.
+-- 1.3.0:
+-- Modified to allow independently active rows in each bank.
+-- 1.2.0:
+-- Modified to allow pipelining of read/write operations.
+-- 1.1.0:
+-- Initial release.
+--
+-- License:
+-- This code can be freely distributed and modified as long as
+-- this header is not removed.
+--------------------------------------------------------------------
+
+library IEEE, UNISIM;
+use IEEE.std_logic_1164.all;
+use IEEE.std_logic_unsigned.all;
+use IEEE.numeric_std.all;
+
+entity sdramCntl is
+ port(
+ -- host side
+ clk : in std_logic; -- master clock
+ clk_ok : in std_logic; -- true if clock is stable
+ rd : in std_logic; -- initiate read operation
+ wr : in std_logic; -- initiate write operation
+ done : out std_logic; -- read or write operation is done
+ hAddr : in std_logic_vector(23 downto 0); -- address from host to SDRAM
+ hDIn : in std_logic_vector(15 downto 0); -- data from host to SDRAM
+ hDOut : out std_logic_vector(15 downto 0); -- data from SDRAM to host
+
+ -- SDRAM side
+ cke : out std_logic; -- clock-enable to SDRAM
+ ce_n : out std_logic; -- chip-select to SDRAM
+ ras_n : out std_logic; -- SDRAM row address strobe
+ cas_n : out std_logic; -- SDRAM column address strobe
+ we_n : out std_logic; -- SDRAM write enable
+ ba : out std_logic_vector(1 downto 0); -- SDRAM bank address
+ sAddr : out std_logic_vector(12 downto 0); -- SDRAM row/column address
+ sDIn : in std_logic_vector(15 downto 0); -- data from SDRAM
+ sDOut : out std_logic_vector(15 downto 0); -- data to SDRAM
+ sDOutEn : out std_logic; -- true if data is output to SDRAM on sDOut
+ dqmh : out std_logic; -- enable upper-byte of SDRAM databus if true
+ dqml : out std_logic -- enable lower-byte of SDRAM databus if true
+ );
+end sdramCntl;
+
+
+architecture arch of sdramCntl is
+
+ constant YES : std_logic := '1';
+ constant NO : std_logic := '0';
+
+ -- select one of two integers based on a Boolean
+ function int_select(s : in boolean; a : in integer; b : in integer) return integer is
+ begin
+ if s then
+ return a;
+ else
+ return b;
+ end if;
+ return a;
+ end function int_select;
+
+ constant OUTPUT : std_logic := '1'; -- direction of dataflow w.r.t. this controller
+ constant INPUT : std_logic := '0';
+ constant NOP : std_logic := '0'; -- no operation
+ constant READ : std_logic := '1'; -- read operation
+ constant WRITE : std_logic := '1'; -- write operation
+
+ -- SDRAM timing parameters
+ constant Tinit : natural := 200; -- min initialization interval (us)
+ constant Tras : natural := 45; -- min interval between active to precharge commands (ns)
+ constant Trcd : natural := 20; -- min interval between active and R/W commands (ns)
+ constant Tref : natural := 64_000_000; -- maximum refresh interval (ns)
+ constant Trfc : natural := 66; -- duration of refresh operation (ns)
+ constant Trp : natural := 20; -- min precharge command duration (ns)
+ constant Twr : natural := 15; -- write recovery time (ns)
+ constant Txsr : natural := 75; -- exit self-refresh time (ns)
+
+ -- SDRAM timing parameters converted into clock cycles (based on FREQ = 50_000)
+ constant NORM : natural := 1_000_000; -- normalize ns * KHz
+ constant INIT_CYCLES : natural := 1+((Tinit*50_000)/1000); -- SDRAM power-on initialization interval
+ constant RAS_CYCLES : natural := 1+((Tras*50_000)/NORM); -- active-to-precharge interval
+ constant RCD_CYCLES : natural := 1+((Trcd*50_000)/NORM); -- active-to-R/W interval
+ constant REF_CYCLES : natural := 1+(((Tref/8192)*50_000)/NORM); -- interval between row refreshes
+ constant RFC_CYCLES : natural := 1+((Trfc*50_000)/NORM); -- refresh operation interval
+ constant RP_CYCLES : natural := 1+((Trp*50_000)/NORM); -- precharge operation interval
+ constant WR_CYCLES : natural := 1+((Twr*50_000)/NORM); -- write recovery time
+ constant XSR_CYCLES : natural := 1+((Txsr*50_000)/NORM); -- exit self-refresh time
+ constant MODE_CYCLES : natural := 2; -- mode register setup time
+ constant CAS_CYCLES : natural := 3; -- CAS latency
+ constant RFSH_OPS : natural := 8; -- number of refresh operations needed to init SDRAM
+
+ -- timer registers that count down times for various SDRAM operations
+ signal timer_r, timer_x : natural range 0 to INIT_CYCLES; -- current SDRAM op time
+ signal rasTimer_r, rasTimer_x : natural range 0 to RAS_CYCLES; -- active-to-precharge time
+ signal wrTimer_r, wrTimer_x : natural range 0 to WR_CYCLES; -- write-to-precharge time
+ signal refTimer_r, refTimer_x : natural range 0 to REF_CYCLES; -- time between row refreshes
+ signal rfshCntr_r, rfshCntr_x : natural range 0 to 8192; -- counts refreshes that are neede
+ signal nopCntr_r, nopCntr_x : natural range 0 to 10000; -- counts consecutive NOP operations
+
+ signal doSelfRfsh : std_logic; -- active when the NOP counter hits zero and self-refresh can start
+
+ -- states of the SDRAM controller state machine
+ type cntlState is (
+ INITWAIT, -- initialization - waiting for power-on initialization to complete
+ INITPCHG, -- initialization - initial precharge of SDRAM banks
+ INITSETMODE, -- initialization - set SDRAM mode
+ INITRFSH, -- initialization - do initial refreshes
+ RW, -- read/write/refresh the SDRAM
+ ACTIVATE, -- open a row of the SDRAM for reading/writing
+ REFRESHROW, -- refresh a row of the SDRAM
+ SELFREFRESH -- keep SDRAM in self-refresh mode with CKE low
+ );
+ signal state_r, state_x : cntlState; -- state register and next state
+
+ -- commands that are sent to the SDRAM to make it perform certain operations
+ -- commands use these SDRAM input pins (ce_n,ras_n,cas_n,we_n,dqmh,dqml)
+ subtype sdramCmd is unsigned(5 downto 0);
+ constant NOP_CMD : sdramCmd := "011100";
+ constant ACTIVE_CMD : sdramCmd := "001100";
+ constant READ_CMD : sdramCmd := "010100";
+ constant WRITE_CMD : sdramCmd := "010000";
+ constant PCHG_CMD : sdramCmd := "001011";
+ constant MODE_CMD : sdramCmd := "000011";
+ constant RFSH_CMD : sdramCmd := "000111";
+
+ -- SDRAM mode register
+ -- the SDRAM is placed in a non-burst mode (burst length = 1) with a 3-cycle CAS
+ subtype sdramMode is std_logic_vector(12 downto 0);
+ constant MODE : sdramMode := "000" & "0" & "00" & "011" & "0" & "000";
+
+ -- the host address is decomposed into these sets of SDRAM address components
+ constant ROW_LEN : natural := 13; -- number of row address bits
+ constant COL_LEN : natural := 9; -- number of column address bits
+ signal bank : std_logic_vector(ba'range); -- bank address bits
+ signal row : std_logic_vector(ROW_LEN - 1 downto 0); -- row address within bank
+ signal col : std_logic_vector(sAddr'range); -- column address within row
+
+ -- registers that store the currently active row in each bank of the SDRAM
+ constant NUM_ACTIVE_ROWS : integer := 1;
+ type activeRowType is array(0 to NUM_ACTIVE_ROWS-1) of std_logic_vector(row'range);
+ signal activeRow_r, activeRow_x : activeRowType;
+ signal activeFlag_r, activeFlag_x : std_logic_vector(0 to NUM_ACTIVE_ROWS-1); -- indicates that some row in a bank is active
+ signal bankIndex : natural range 0 to NUM_ACTIVE_ROWS-1; -- bank address bits
+ signal activeBank_r, activeBank_x : std_logic_vector(ba'range); -- indicates the bank with the active row
+ signal doActivate : std_logic; -- indicates when a new row in a bank needs to be activated
+
+ -- there is a command bit embedded within the SDRAM column address
+ constant CMDBIT_POS : natural := 10; -- position of command bit
+ constant AUTO_PCHG_ON : std_logic := '1'; -- CMDBIT value to auto-precharge the bank
+ constant AUTO_PCHG_OFF : std_logic := '0'; -- CMDBIT value to disable auto-precharge
+ constant ONE_BANK : std_logic := '0'; -- CMDBIT value to select one bank
+ constant ALL_BANKS : std_logic := '1'; -- CMDBIT value to select all banks
+
+ -- status signals that indicate when certain operations are in progress
+ signal wrInProgress : std_logic; -- write operation in progress
+ signal rdInProgress : std_logic; -- read operation in progress
+ signal activateInProgress : std_logic; -- row activation is in progress
+
+ -- these registers track the progress of read and write operations
+ signal rdPipeline_r, rdPipeline_x : std_logic_vector(CAS_CYCLES+1 downto 0); -- pipeline of read ops in progress
+ signal wrPipeline_r, wrPipeline_x : std_logic_vector(0 downto 0); -- pipeline of write ops (only need 1 cycle)
+
+ -- registered outputs to host
+ signal hDOut_r, hDOut_x : std_logic_vector(hDOut'range); -- holds data read from SDRAM and sent to the host
+
+ -- registered outputs to SDRAM
+ signal cke_r, cke_x : std_logic; -- clock enable
+ signal cmd_r, cmd_x : sdramCmd; -- SDRAM command bits
+ signal ba_r, ba_x : std_logic_vector(ba'range); -- SDRAM bank address bits
+ signal sAddr_r, sAddr_x : std_logic_vector(sAddr'range); -- SDRAM row/column address
+ signal sData_r, sData_x : std_logic_vector(sDOut'range); -- SDRAM out databus
+ signal sDataDir_r, sDataDir_x : std_logic; -- SDRAM databus direction control bit
+
+begin
+
+ -----------------------------------------------------------
+ -- attach some internal signals to the I/O ports
+ -----------------------------------------------------------
+
+ -- attach registered SDRAM control signals to SDRAM input pins
+ (ce_n, ras_n, cas_n, we_n, dqmh, dqml) <= cmd_r; -- SDRAM operation control bits
+ cke <= cke_r; -- SDRAM clock enable
+ ba <= ba_r; -- SDRAM bank address
+ sAddr <= sAddr_r; -- SDRAM address
+ sDOut <= sData_r; -- SDRAM output data bus
+ sDOutEn <= YES when sDataDir_r = OUTPUT else NO; -- output databus enable
+
+ -- attach some port signals
+ hDOut <= hDOut_r; -- data back to host
+
+
+ -----------------------------------------------------------
+ -- compute the next state and outputs
+ -----------------------------------------------------------
+
+ combinatorial : process(rd, wr, hAddr, hDIn, hDOut_r, sDIn, state_r,
+ activeFlag_r, activeRow_r, rdPipeline_r, wrPipeline_r,
+ nopCntr_r, rfshCntr_r, timer_r, rasTimer_r,
+ wrTimer_r, refTimer_r, cmd_r, cke_r)
+ begin
+
+ -----------------------------------------------------------
+ -- setup default values for signals
+ -----------------------------------------------------------
+
+ cke_x <= YES; -- enable SDRAM clock
+ cmd_x <= NOP_CMD; -- set SDRAM command to no-operation
+ sDataDir_x <= INPUT; -- accept data from the SDRAM
+ sData_x <= hDIn(sData_x'range); -- output data from host to SDRAM
+ state_x <= state_r; -- reload these registers and flags
+ activeFlag_x <= activeFlag_r; -- with their existing values
+ activeRow_x <= activeRow_r;
+ activeBank_x <= activeBank_r;
+ rfshCntr_x <= rfshCntr_r;
+
+ -----------------------------------------------------------
+ -- setup default value for the SDRAM address
+ -----------------------------------------------------------
+
+ -- extract bank field from host address
+ ba_x <= hAddr(ba'length + ROW_LEN + COL_LEN - 1 downto ROW_LEN + COL_LEN);
+ bank <= ba_x;
+ bankIndex <= 0;
+ -- extract row, column fields from host address
+ row <= hAddr(ROW_LEN + COL_LEN - 1 downto COL_LEN);
+ -- extend column (if needed) until it is as large as the (SDRAM address bus - 1)
+ col <= (others => '0'); -- set it to all zeroes
+ col(COL_LEN-1 downto 0) <= hAddr(COL_LEN-1 downto 0);
+ -- by default, set SDRAM address to the column address with interspersed
+ -- command bit set to disable auto-precharge
+ sAddr_x <= col(col'high-1 downto CMDBIT_POS) & AUTO_PCHG_OFF
+ & col(CMDBIT_POS-1 downto 0);
+
+ -----------------------------------------------------------
+ -- manage the read and write operation pipelines
+ -----------------------------------------------------------
+
+ -- determine if read operations are in progress by the presence of
+ -- READ flags in the read pipeline
+ if rdPipeline_r(rdPipeline_r'high downto 1) /= 0 then
+ rdInProgress <= YES;
+ else
+ rdInProgress <= NO;
+ end if;
+
+ -- enter NOPs into the read and write pipeline shift registers by default
+ rdPipeline_x <= NOP & rdPipeline_r(rdPipeline_r'high downto 1);
+ wrPipeline_x(0) <= NOP;
+
+ -- transfer data from SDRAM to the host data register if a read flag has exited the pipeline
+ -- (the transfer occurs 1 cycle before we tell the host the read operation is done)
+ if rdPipeline_r(1) = READ then
+ -- get the SDRAM data for the host directly from the SDRAM if the controller and SDRAM are in-phase
+ hDOut_x <= sDIn(hDOut'range);
+ else
+ -- retain contents of host data registers if no data from the SDRAM has arrived yet
+ hDOut_x <= hDOut_r;
+ end if;
+
+ done <= rdPipeline_r(0) or wrPipeline_r(0); -- a read or write operation is done
+
+ -----------------------------------------------------------
+ -- manage row activation
+ -----------------------------------------------------------
+
+ -- request a row activation operation if the row of the current address
+ -- does not match the currently active row in the bank, or if no row
+ -- in the bank is currently active
+ if (bank /= activeBank_r) or (row /= activeRow_r(bankIndex)) or (activeFlag_r(bankIndex) = NO) then
+ doActivate <= YES;
+ else
+ doActivate <= NO;
+ end if;
+
+ -----------------------------------------------------------
+ -- manage self-refresh
+ -----------------------------------------------------------
+
+ -- enter self-refresh if neither a read or write is requested for 10000 consecutive cycles.
+ if (rd = YES) or (wr = YES) then
+ -- any read or write resets NOP counter and exits self-refresh state
+ nopCntr_x <= 0;
+ doSelfRfsh <= NO;
+ elsif nopCntr_r /= 10000 then
+ -- increment NOP counter whenever there is no read or write operation
+ nopCntr_x <= nopCntr_r + 1;
+ doSelfRfsh <= NO;
+ else
+ -- start self-refresh when counter hits maximum NOP count and leave counter unchanged
+ nopCntr_x <= nopCntr_r;
+ doSelfRfsh <= YES;
+ end if;
+
+ -----------------------------------------------------------
+ -- update the timers
+ -----------------------------------------------------------
+
+ -- row activation timer
+ if rasTimer_r /= 0 then
+ -- decrement a non-zero timer and set the flag
+ -- to indicate the row activation is still inprogress
+ rasTimer_x <= rasTimer_r - 1;
+ activateInProgress <= YES;
+ else
+ -- on timeout, keep the timer at zero and reset the flag
+ -- to indicate the row activation operation is done
+ rasTimer_x <= rasTimer_r;
+ activateInProgress <= NO;
+ end if;
+
+ -- write operation timer
+ if wrTimer_r /= 0 then
+ -- decrement a non-zero timer and set the flag
+ -- to indicate the write operation is still inprogress
+ wrTimer_x <= wrTimer_r - 1;
+ wrInPRogress <= YES;
+ else
+ -- on timeout, keep the timer at zero and reset the flag that
+ -- indicates a write operation is in progress
+ wrTimer_x <= wrTimer_r;
+ wrInPRogress <= NO;
+ end if;
+
+ -- refresh timer
+ if refTimer_r /= 0 then
+ refTimer_x <= refTimer_r - 1;
+ else
+ -- on timeout, reload the timer with the interval between row refreshes
+ -- and increment the counter for the number of row refreshes that are needed
+ refTimer_x <= REF_CYCLES;
+ rfshCntr_x <= rfshCntr_r + 1;
+ end if;
+
+ -- main timer for sequencing SDRAM operations
+ if timer_r /= 0 then
+ -- decrement the timer and do nothing else since the previous operation has not completed yet.
+ timer_x <= timer_r - 1;
+ else
+ -- the previous operation has completed once the timer hits zero
+ timer_x <= timer_r; -- by default, leave the timer at zero
+
+ -----------------------------------------------------------
+ -- compute the next state and outputs
+ -----------------------------------------------------------
+ case state_r is
+
+ -----------------------------------------------------------
+ -- let clock stabilize and then wait for the SDRAM to initialize
+ -----------------------------------------------------------
+ when INITWAIT =>
+ -- wait for SDRAM power-on initialization once the clock is stable
+ timer_x <= INIT_CYCLES; -- set timer for initialization duration
+ state_x <= INITPCHG;
+
+ -----------------------------------------------------------
+ -- precharge all SDRAM banks after power-on initialization
+ -----------------------------------------------------------
+ when INITPCHG =>
+ cmd_x <= PCHG_CMD;
+ sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks
+ timer_x <= RP_CYCLES; -- set timer for precharge operation duration
+ rfshCntr_x <= RFSH_OPS; -- set counter for refresh ops needed after precharge
+ state_x <= INITRFSH;
+
+ -----------------------------------------------------------
+ -- refresh the SDRAM a number of times after initial precharge
+ -----------------------------------------------------------
+ when INITRFSH =>
+ cmd_x <= RFSH_CMD;
+ timer_x <= RFC_CYCLES; -- set timer to refresh operation duration
+ rfshCntr_x <= rfshCntr_r - 1; -- decrement refresh operation counter
+ if rfshCntr_r = 1 then
+ state_x <= INITSETMODE; -- set the SDRAM mode once all refresh ops are done
+ end if;
+
+ -----------------------------------------------------------
+ -- set the mode register of the SDRAM
+ -----------------------------------------------------------
+ when INITSETMODE =>
+ cmd_x <= MODE_CMD;
+ sAddr_x <= MODE; -- output mode register bits on the SDRAM address bits
+ timer_x <= MODE_CYCLES; -- set timer for mode setting operation duration
+ state_x <= RW;
+
+ -----------------------------------------------------------
+ -- process read/write/refresh operations after initialization is done
+ -----------------------------------------------------------
+ when RW =>
+ -----------------------------------------------------------
+ -- highest priority operation: row refresh
+ -- do a refresh operation if the refresh counter is non-zero
+ -----------------------------------------------------------
+ if rfshCntr_r /= 0 then
+ -- wait for any row activations, writes or reads to finish before doing a precharge
+ if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
+ cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM
+ sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks
+ timer_x <= RP_CYCLES; -- set timer for this operation
+ activeFlag_x <= (others => NO); -- all rows are inactive after a precharge operation
+ state_x <= REFRESHROW; -- refresh the SDRAM after the precharge
+ end if;
+ -----------------------------------------------------------
+ -- do a host-initiated read operation
+ -----------------------------------------------------------
+ elsif rd = YES then
+ -- Wait one clock cycle if the bank address has just changed and each bank has its own active row.
+ -- This gives extra time for the row activation circuitry.
+ if (true) then
+ -- activate a new row if the current read is outside the active row or bank
+ if doActivate = YES then
+ -- activate new row only if all previous activations, writes, reads are done
+ if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
+ cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM
+ sAddr_x(CMDBIT_POS) <= ONE_BANK; -- precharge this bank
+ timer_x <= RP_CYCLES; -- set timer for this operation
+ activeFlag_x(bankIndex) <= NO; -- rows in this bank are inactive after a precharge operation
+ state_x <= ACTIVATE; -- activate the new row after the precharge is done
+ end if;
+ -- read from the currently active row if no previous read operation
+ -- is in progress or if pipeline reads are enabled
+ -- we can always initiate a read even if a write is already in progress
+ elsif (rdInProgress = NO) then
+ cmd_x <= READ_CMD; -- initiate a read of the SDRAM
+ -- insert a flag into the pipeline shift register that will exit the end
+ -- of the shift register when the data from the SDRAM is available
+ rdPipeline_x <= READ & rdPipeline_r(rdPipeline_r'high downto 1);
+ end if;
+ end if;
+ -----------------------------------------------------------
+ -- do a host-initiated write operation
+ -----------------------------------------------------------
+ elsif wr = YES then
+ -- Wait one clock cycle if the bank address has just changed and each bank has its own active row.
+ -- This gives extra time for the row activation circuitry.
+ if (true) then
+ -- activate a new row if the current write is outside the active row or bank
+ if doActivate = YES then
+ -- activate new row only if all previous activations, writes, reads are done
+ if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
+ cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM
+ sAddr_x(CMDBIT_POS) <= ONE_BANK; -- precharge this bank
+ timer_x <= RP_CYCLES; -- set timer for this operation
+ activeFlag_x(bankIndex) <= NO; -- rows in this bank are inactive after a precharge operation
+ state_x <= ACTIVATE; -- activate the new row after the precharge is done
+ end if;
+ -- write to the currently active row if no previous read operations are in progress
+ elsif rdInProgress = NO then
+ cmd_x <= WRITE_CMD; -- initiate the write operation
+ sDataDir_x <= OUTPUT; -- turn on drivers to send data to SDRAM
+ -- set timer so precharge doesn't occur too soon after write operation
+ wrTimer_x <= WR_CYCLES;
+ -- insert a flag into the 1-bit pipeline shift register that will exit on the
+ -- next cycle. The write into SDRAM is not actually done by that time, but
+ -- this doesn't matter to the host
+ wrPipeline_x(0) <= WRITE;
+ end if;
+ end if;
+ -----------------------------------------------------------
+ -- do a host-initiated self-refresh operation
+ -----------------------------------------------------------
+ elsif doSelfRfsh = YES then
+ -- wait until all previous activations, writes, reads are done
+ if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
+ cmd_x <= PCHG_CMD; -- initiate precharge of the SDRAM
+ sAddr_x(CMDBIT_POS) <= ALL_BANKS; -- precharge all banks
+ timer_x <= RP_CYCLES; -- set timer for this operation
+ activeFlag_x <= (others => NO); -- all rows are inactive after a precharge operation
+ state_x <= SELFREFRESH; -- self-refresh the SDRAM after the precharge
+ end if;
+ -----------------------------------------------------------
+ -- no operation
+ -----------------------------------------------------------
+ else
+ state_x <= RW; -- continue to look for SDRAM operations to execute
+ end if;
+
+ -----------------------------------------------------------
+ -- activate a row of the SDRAM
+ -----------------------------------------------------------
+ when ACTIVATE =>
+ cmd_x <= ACTIVE_CMD;
+ sAddr_x <= (others => '0'); -- output the address for the row to be activated
+ sAddr_x(row'range) <= row;
+ activeBank_x <= bank;
+ activeRow_x(bankIndex) <= row; -- store the new active SDRAM row address
+ activeFlag_x(bankIndex) <= YES; -- the SDRAM is now active
+ rasTimer_x <= RAS_CYCLES; -- minimum time before another precharge can occur
+ timer_x <= RCD_CYCLES; -- minimum time before a read/write operation can occur
+ state_x <= RW; -- return to do read/write operation that initiated this activation
+
+ -----------------------------------------------------------
+ -- refresh a row of the SDRAM
+ -----------------------------------------------------------
+ when REFRESHROW =>
+ cmd_x <= RFSH_CMD;
+ timer_x <= RFC_CYCLES; -- refresh operation interval
+ rfshCntr_x <= rfshCntr_r - 1; -- decrement the number of needed row refreshes
+ state_x <= RW; -- process more SDRAM operations after refresh is done
+
+ -----------------------------------------------------------
+ -- place the SDRAM into self-refresh and keep it there until further notice
+ -----------------------------------------------------------
+ when SELFREFRESH =>
+ if (doSelfRfsh = YES) then
+ -- keep the SDRAM in self-refresh mode as long as requested and until there is a stable clock
+ cmd_x <= RFSH_CMD; -- output the refresh command; this is only needed on the first clock cycle
+ cke_x <= NO; -- disable the SDRAM clock
+ else
+ -- else exit self-refresh mode and start processing read and write operations
+ cke_x <= YES; -- restart the SDRAM clock
+ rfshCntr_x <= 0; -- no refreshes are needed immediately after leaving self-refresh
+ activeFlag_x <= (others => NO); -- self-refresh deactivates all rows
+ timer_x <= XSR_CYCLES; -- wait this long until read and write operations can resume
+ state_x <= RW;
+ end if;
+
+ -----------------------------------------------------------
+ -- unknown state
+ -----------------------------------------------------------
+ when others =>
+ state_x <= INITWAIT; -- reset state if in erroneous state
+
+ end case;
+ end if;
+ end process combinatorial;
+
+
+ -----------------------------------------------------------
+ -- update registers on the appropriate clock edge
+ -----------------------------------------------------------
+
+ update : process(clk_ok, clk)
+ begin
+
+ if clk_ok = NO then
+ -- asynchronous reset
+ state_r <= INITWAIT;
+ activeFlag_r <= (others => NO);
+ rfshCntr_r <= 0;
+ timer_r <= 0;
+ refTimer_r <= REF_CYCLES;
+ rasTimer_r <= 0;
+ wrTimer_r <= 0;
+ nopCntr_r <= 0;
+ rdPipeline_r <= (others => '0');
+ wrPipeline_r <= (others => '0');
+ cke_r <= NO;
+ cmd_r <= NOP_CMD;
+ ba_r <= (others => '0');
+ sAddr_r <= (others => '0');
+ sData_r <= (others => '0');
+ sDataDir_r <= INPUT;
+ hDOut_r <= (others => '0');
+ elsif rising_edge(clk) then
+ state_r <= state_x;
+ activeBank_r <= activeBank_x;
+ activeRow_r <= activeRow_x;
+ activeFlag_r <= activeFlag_x;
+ rfshCntr_r <= rfshCntr_x;
+ timer_r <= timer_x;
+ refTimer_r <= refTimer_x;
+ rasTimer_r <= rasTimer_x;
+ wrTimer_r <= wrTimer_x;
+ nopCntr_r <= nopCntr_x;
+ rdPipeline_r <= rdPipeline_x;
+ wrPipeline_r <= wrPipeline_x;
+ cke_r <= cke_x;
+ cmd_r <= cmd_x;
+ ba_r <= ba_x;
+ sAddr_r <= sAddr_x;
+ sData_r <= sData_x;
+ sDataDir_r <= sDataDir_x;
+ hDOut_r <= hDOut_x;
+ end if;
+
+ end process update;
+
+end arch;
Index: trunk/fpga/src/eco32.v
===================================================================
--- trunk/fpga/src/eco32.v (nonexistent)
+++ trunk/fpga/src/eco32.v (revision 27)
@@ -0,0 +1,436 @@
+//
+// eco32.v -- toplevel description of the ECO32 system
+//
+
+
+module eco32(clk_in,
+ reset_inout_n,
+ sdram_clk,
+ sdram_fb,
+ sdram_cke,
+ sdram_cs_n,
+ sdram_udqm,
+ sdram_ldqm,
+ sdram_ras_n,
+ sdram_cas_n,
+ sdram_we_n,
+ sdram_ba,
+ sdram_a,
+ sdram_dq,
+ flash_ce_n,
+ flash_oe_n,
+ flash_we_n,
+ flash_rst_n,
+ flash_byte_n,
+ flash_a,
+ flash_d,
+ hsync,
+ vsync,
+ r,
+ g,
+ b,
+ ps2_clk,
+ ps2_data,
+ rs232_0_rxd,
+ rs232_0_txd,
+ rs232_1_rxd,
+ rs232_1_txd,
+ pbus_d,
+ pbus_a,
+ pbus_read_n,
+ pbus_write_n,
+ ata_cs0_n,
+ ata_cs1_n,
+ ata_intrq,
+ ata_dmarq,
+ ata_dmack_n,
+ ata_iordy,
+ slot1_cs_n,
+ slot2_cs_n,
+ ether_cs_n);
+
+ // clock and reset
+ input clk_in;
+ inout reset_inout_n;
+ // SDRAM
+ output sdram_clk;
+ input sdram_fb;
+ output sdram_cke;
+ output sdram_cs_n;
+ output sdram_udqm;
+ output sdram_ldqm;
+ output sdram_ras_n;
+ output sdram_cas_n;
+ output sdram_we_n;
+ output [1:0] sdram_ba;
+ output [12:0] sdram_a;
+ inout [15:0] sdram_dq;
+ // flash ROM
+ output flash_ce_n;
+ output flash_oe_n;
+ output flash_we_n;
+ output flash_rst_n;
+ output flash_byte_n;
+ output [19:0] flash_a;
+ input [15:0] flash_d;
+ // VGA display
+ output hsync;
+ output vsync;
+ output [2:0] r;
+ output [2:0] g;
+ output [2:0] b;
+ // keyboard
+ input ps2_clk;
+ input ps2_data;
+ // serial line 0
+ input rs232_0_rxd;
+ output rs232_0_txd;
+ // serial line 1
+ input rs232_1_rxd;
+ output rs232_1_txd;
+ // peripheral bus
+ inout [15:0] pbus_d;
+ output [4:0] pbus_a;
+ output pbus_read_n;
+ output pbus_write_n;
+ // ATA adapter
+ output ata_cs0_n;
+ output ata_cs1_n;
+ input ata_intrq;
+ input ata_dmarq;
+ output ata_dmack_n;
+ input ata_iordy;
+ // expansion slot 1
+ output slot1_cs_n;
+ // expansion slot 2
+ output slot2_cs_n;
+ // ethernet
+ output ether_cs_n;
+
+ // clk_reset
+ wire clk;
+ wire clk_ok;
+ wire reset;
+ // cpu
+ wire cpu_en;
+ wire cpu_wr;
+ wire [1:0] cpu_size;
+ wire [31:0] cpu_addr;
+ wire [31:0] cpu_data_in;
+ wire [31:0] cpu_data_out;
+ wire cpu_wt;
+ wire [15:0] cpu_irq;
+ // ram
+ wire ram_en;
+ wire ram_wr;
+ wire [1:0] ram_size;
+ wire [24:0] ram_addr;
+ wire [31:0] ram_data_in;
+ wire [31:0] ram_data_out;
+ wire ram_wt;
+ // rom
+ wire rom_en;
+ wire rom_wr;
+ wire [1:0] rom_size;
+ wire [20:0] rom_addr;
+ wire [31:0] rom_data_out;
+ wire rom_wt;
+ // tmr
+ wire tmr_en;
+ wire tmr_wr;
+ wire tmr_addr2;
+ wire [31:0] tmr_data_in;
+ wire [31:0] tmr_data_out;
+ wire tmr_wt;
+ wire tmr_irq;
+ // dsp
+ wire dsp_en;
+ wire dsp_wr;
+ wire [13:2] dsp_addr;
+ wire [15:0] dsp_data_in;
+ wire [15:0] dsp_data_out;
+ wire dsp_wt;
+ // kbd
+ wire kbd_en;
+ wire kbd_wr;
+ wire kbd_addr2;
+ wire [7:0] kbd_data_in;
+ wire [7:0] kbd_data_out;
+ wire kbd_wt;
+ wire kbd_irq;
+ // ser0
+ wire ser0_en;
+ wire ser0_wr;
+ wire [3:2] ser0_addr;
+ wire [7:0] ser0_data_in;
+ wire [7:0] ser0_data_out;
+ wire ser0_wt;
+ wire ser0_irq_r;
+ wire ser0_irq_t;
+ // ser1
+ wire ser1_en;
+ wire ser1_wr;
+ wire [3:2] ser1_addr;
+ wire [7:0] ser1_data_in;
+ wire [7:0] ser1_data_out;
+ wire ser1_wt;
+ wire ser1_irq_r;
+ wire ser1_irq_t;
+ // dsk
+ wire dsk_en;
+ wire dsk_wr;
+ wire [19:2] dsk_addr;
+ wire [31:0] dsk_data_in;
+ wire [31:0] dsk_data_out;
+ wire dsk_wt;
+ wire dsk_irq;
+
+ clk_reset clk_reset1(
+ .clk_in(clk_in),
+ .reset_inout_n(reset_inout_n),
+ .sdram_clk(sdram_clk),
+ .sdram_fb(sdram_fb),
+ .clk(clk),
+ .clk_ok(clk_ok),
+ .reset(reset)
+ );
+
+ busctrl busctrl1(
+ // cpu
+ .cpu_en(cpu_en),
+ .cpu_wr(cpu_wr),
+ .cpu_size(cpu_size[1:0]),
+ .cpu_addr(cpu_addr[31:0]),
+ .cpu_data_in(cpu_data_in[31:0]),
+ .cpu_data_out(cpu_data_out[31:0]),
+ .cpu_wt(cpu_wt),
+ // ram
+ .ram_en(ram_en),
+ .ram_wr(ram_wr),
+ .ram_size(ram_size[1:0]),
+ .ram_addr(ram_addr[24:0]),
+ .ram_data_in(ram_data_in[31:0]),
+ .ram_data_out(ram_data_out[31:0]),
+ .ram_wt(ram_wt),
+ // rom
+ .rom_en(rom_en),
+ .rom_wr(rom_wr),
+ .rom_size(rom_size[1:0]),
+ .rom_addr(rom_addr[20:0]),
+ .rom_data_out(rom_data_out[31:0]),
+ .rom_wt(rom_wt),
+ // tmr
+ .tmr_en(tmr_en),
+ .tmr_wr(tmr_wr),
+ .tmr_addr2(tmr_addr2),
+ .tmr_data_in(tmr_data_in[31:0]),
+ .tmr_data_out(tmr_data_out[31:0]),
+ .tmr_wt(tmr_wt),
+ // dsp
+ .dsp_en(dsp_en),
+ .dsp_wr(dsp_wr),
+ .dsp_addr(dsp_addr[13:2]),
+ .dsp_data_in(dsp_data_in[15:0]),
+ .dsp_data_out(dsp_data_out[15:0]),
+ .dsp_wt(dsp_wt),
+ // kbd
+ .kbd_en(kbd_en),
+ .kbd_wr(kbd_wr),
+ .kbd_addr2(kbd_addr2),
+ .kbd_data_in(kbd_data_in[7:0]),
+ .kbd_data_out(kbd_data_out[7:0]),
+ .kbd_wt(kbd_wt),
+ // ser0
+ .ser0_en(ser0_en),
+ .ser0_wr(ser0_wr),
+ .ser0_addr(ser0_addr[3:2]),
+ .ser0_data_in(ser0_data_in[7:0]),
+ .ser0_data_out(ser0_data_out[7:0]),
+ .ser0_wt(ser0_wt),
+ // ser1
+ .ser1_en(ser1_en),
+ .ser1_wr(ser1_wr),
+ .ser1_addr(ser1_addr[3:2]),
+ .ser1_data_in(ser1_data_in[7:0]),
+ .ser1_data_out(ser1_data_out[7:0]),
+ .ser1_wt(ser1_wt),
+ // dsk
+ .dsk_en(dsk_en),
+ .dsk_wr(dsk_wr),
+ .dsk_addr(dsk_addr[19:2]),
+ .dsk_data_in(dsk_data_in[31:0]),
+ .dsk_data_out(dsk_data_out[31:0]),
+ .dsk_wt(dsk_wt)
+ );
+
+ cpu cpu1(
+ .clk(clk),
+ .reset(reset),
+ .bus_en(cpu_en),
+ .bus_wr(cpu_wr),
+ .bus_size(cpu_size[1:0]),
+ .bus_addr(cpu_addr[31:0]),
+ .bus_data_in(cpu_data_in[31:0]),
+ .bus_data_out(cpu_data_out[31:0]),
+ .bus_wt(cpu_wt),
+ .irq(cpu_irq[15:0])
+ );
+
+ assign cpu_irq[15] = 1'b0;
+ assign cpu_irq[14] = tmr_irq;
+ assign cpu_irq[13] = 1'b0;
+ assign cpu_irq[12] = 1'b0;
+ assign cpu_irq[11] = 1'b0;
+ assign cpu_irq[10] = 1'b0;
+ assign cpu_irq[ 9] = 1'b0;
+ assign cpu_irq[ 8] = dsk_irq;
+ assign cpu_irq[ 7] = 1'b0;
+ assign cpu_irq[ 6] = 1'b0;
+ assign cpu_irq[ 5] = 1'b0;
+ assign cpu_irq[ 4] = kbd_irq;
+ assign cpu_irq[ 3] = ser1_irq_r;
+ assign cpu_irq[ 2] = ser1_irq_t;
+ assign cpu_irq[ 1] = ser0_irq_r;
+ assign cpu_irq[ 0] = ser0_irq_t;
+
+ ram ram1(
+ .clk(clk),
+ .clk_ok(clk_ok),
+ .reset(reset),
+ .en(ram_en),
+ .wr(ram_wr),
+ .size(ram_size[1:0]),
+ .addr(ram_addr[24:0]),
+ .data_in(ram_data_in[31:0]),
+ .data_out(ram_data_out[31:0]),
+ .wt(ram_wt),
+ .sdram_cke(sdram_cke),
+ .sdram_cs_n(sdram_cs_n),
+ .sdram_udqm(sdram_udqm),
+ .sdram_ldqm(sdram_ldqm),
+ .sdram_ras_n(sdram_ras_n),
+ .sdram_cas_n(sdram_cas_n),
+ .sdram_we_n(sdram_we_n),
+ .sdram_ba(sdram_ba[1:0]),
+ .sdram_a(sdram_a[12:0]),
+ .sdram_dq(sdram_dq[15:0])
+ );
+
+ rom rom1(
+ .clk(clk),
+ .reset(reset),
+ .en(rom_en),
+ .wr(rom_wr),
+ .size(rom_size[1:0]),
+ .addr(rom_addr[20:0]),
+ .data_out(rom_data_out[31:0]),
+ .wt(rom_wt),
+ .ce_n(flash_ce_n),
+ .oe_n(flash_oe_n),
+ .we_n(flash_we_n),
+ .rst_n(flash_rst_n),
+ .byte_n(flash_byte_n),
+ .a(flash_a[19:0]),
+ .d(flash_d[15:0])
+ );
+
+ tmr tmr1(
+ .clk(clk),
+ .reset(reset),
+ .en(tmr_en),
+ .wr(tmr_wr),
+ .addr2(tmr_addr2),
+ .data_in(tmr_data_in[31:0]),
+ .data_out(tmr_data_out[31:0]),
+ .wt(tmr_wt),
+ .irq(tmr_irq)
+ );
+
+ dsp dsp1(
+ .clk(clk),
+ .reset(reset),
+ .en(dsp_en),
+ .wr(dsp_wr),
+ .addr(dsp_addr[13:2]),
+ .data_in(dsp_data_in[15:0]),
+ .data_out(dsp_data_out[15:0]),
+ .wt(dsp_wt),
+ .hsync(hsync),
+ .vsync(vsync),
+ .r(r[2:0]),
+ .g(g[2:0]),
+ .b(b[2:0])
+ );
+
+ kbd kbd1(
+ .ps2_clk(ps2_clk),
+ .ps2_data(ps2_data),
+ .clk(clk),
+ .reset(reset),
+ .en(kbd_en),
+ .wr(kbd_wr),
+ .addr2(kbd_addr2),
+ .data_in(kbd_data_in[7:0]),
+ .data_out(kbd_data_out[7:0]),
+ .wt(kbd_wt),
+ .irq(kbd_irq)
+ );
+
+ ser ser1_0(
+ .clk(clk),
+ .reset(reset),
+ .en(ser0_en),
+ .wr(ser0_wr),
+ .addr(ser0_addr[3:2]),
+ .data_in(ser0_data_in[7:0]),
+ .data_out(ser0_data_out[7:0]),
+ .wt(ser0_wt),
+ .irq_r(ser0_irq_r),
+ .irq_t(ser0_irq_t),
+ .rxd(rs232_0_rxd),
+ .txd(rs232_0_txd)
+ );
+
+ ser ser1_1(
+ .clk(clk),
+ .reset(reset),
+ .en(ser1_en),
+ .wr(ser1_wr),
+ .addr(ser1_addr[3:2]),
+ .data_in(ser1_data_in[7:0]),
+ .data_out(ser1_data_out[7:0]),
+ .wt(ser1_wt),
+ .irq_r(ser1_irq_r),
+ .irq_t(ser1_irq_t),
+ .rxd(rs232_1_rxd),
+ .txd(rs232_1_txd)
+ );
+
+ dsk dsk1(
+ .clk(clk),
+ .reset(reset),
+ .en(dsk_en),
+ .wr(dsk_wr),
+ .addr(dsk_addr[19:2]),
+ .data_in(dsk_data_in[31:0]),
+ .data_out(dsk_data_out[31:0]),
+ .wt(dsk_wt),
+ .irq(dsk_irq),
+ .ata_d(pbus_d[15:0]),
+ .ata_a(pbus_a[2:0]),
+ .ata_cs0_n(ata_cs0_n),
+ .ata_cs1_n(ata_cs1_n),
+ .ata_dior_n(pbus_read_n),
+ .ata_diow_n(pbus_write_n),
+ .ata_intrq(ata_intrq),
+ .ata_dmarq(ata_dmarq),
+ .ata_dmack_n(ata_dmack_n),
+ .ata_iordy(ata_iordy)
+ );
+
+ assign pbus_a[4:3] = 2'b00;
+ assign slot1_cs_n = 1;
+ assign slot2_cs_n = 1;
+ assign ether_cs_n = 1;
+
+endmodule
Index: trunk/fpga/src/kbd/keyboard.v
===================================================================
--- trunk/fpga/src/kbd/keyboard.v (nonexistent)
+++ trunk/fpga/src/kbd/keyboard.v (revision 27)
@@ -0,0 +1,123 @@
+module keyboard(ps2_clk, ps2_data,
+ clk, reset,
+ keyboard_data, keyboard_rdy);
+ input ps2_clk;
+ input ps2_data;
+ input clk;
+ input reset;
+ output [7:0] keyboard_data;
+ output keyboard_rdy;
+
+ reg ps2_clk_p;
+ reg ps2_clk_s;
+ reg ps2_data_p;
+ reg ps2_data_s;
+ wire [3:0] ps2_clk_int_x;
+ reg [3:0] ps2_clk_int_r;
+ reg ps2_clk_lvl;
+ reg ps2_clk_lvl_prv;
+ wire ps2_clk_fall;
+ wire ps2_clk_rise;
+ wire ps2_clk_edge;
+ wire [9:0] data_x;
+ reg [9:0] data_r;
+ wire [12:0] timer_x;
+ reg [12:0] timer_r;
+ wire ps2_clk_quiet;
+ wire [3:0] bitcnt_x;
+ reg [3:0] bitcnt_r;
+ wire rdy_x;
+ reg rdy_r;
+ wire err_x;
+ reg err_r;
+
+ // ps2 clock and data synchronizer
+ always @(posedge clk) begin
+ ps2_clk_p <= ps2_clk;
+ ps2_clk_s <= ps2_clk_p;
+ ps2_data_p <= ps2_data;
+ ps2_data_s <= ps2_data_p;
+ end
+
+ // integrate ps2 clock
+ assign ps2_clk_int_x =
+ (ps2_clk_int_r == 4'b1111 && ps2_clk_s == 1) ? 4'b1111 :
+ (ps2_clk_int_r == 4'b0000 && ps2_clk_s == 0) ? 4'b0000 :
+ (ps2_clk_s == 1) ? ps2_clk_int_r + 1 :
+ ps2_clk_int_r - 1;
+
+ // clock level detector with hysteresis
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ ps2_clk_lvl_prv <= 1;
+ ps2_clk_lvl <= 1;
+ end else begin
+ ps2_clk_lvl_prv <= ps2_clk_lvl;
+ if (ps2_clk_int_r == 4'b0100) begin
+ ps2_clk_lvl <= 0;
+ end
+ if (ps2_clk_int_r == 4'b1011) begin
+ ps2_clk_lvl <= 1;
+ end
+ end
+ end
+
+ // find clock edges
+ assign ps2_clk_fall = ps2_clk_lvl_prv & ~ps2_clk_lvl;
+ assign ps2_clk_rise = ~ps2_clk_lvl_prv & ps2_clk_lvl;
+ assign ps2_clk_edge = ps2_clk_fall | ps2_clk_rise;
+
+ // shift ps2 data into a register
+ assign data_x =
+ (ps2_clk_fall == 1) ? { ps2_data_s, data_r[9:1]} : data_r;
+
+ // clear timer if clock is pulsing, otherwise count
+ assign timer_x =
+ (ps2_clk_edge == 1) ? 13'b0000000000000 : timer_r + 1;
+
+ // determine if clock has stopped at high level
+ assign ps2_clk_quiet =
+ (timer_r == 13'b1010000000000 && ps2_clk_lvl == 1) ? 1 : 0;
+
+ // maintain bit counter
+ assign bitcnt_x =
+ (ps2_clk_fall == 1) ? bitcnt_r + 1 :
+ (ps2_clk_quiet == 1 || err_r == 1) ? 4'b0000:
+ bitcnt_r;
+
+ // check if data ready
+ assign rdy_x =
+ (bitcnt_r == 4'b1011 && ps2_clk_quiet == 1) ? 1 : 0;
+
+ // check for errors
+ assign err_x =
+ ((timer_r == 13'b1010000000000 &&
+ ps2_clk_lvl == 0) ||
+ (ps2_clk_quiet == 1 &&
+ bitcnt_r != 4'b1011 &&
+ bitcnt_r != 4'b0000)) ? 1 : err_r;
+
+ // update state registers
+ always @(posedge clk) begin
+ if (reset == 1 || err_r == 1) begin
+ ps2_clk_int_r <= 4'b1111;
+ data_r <= 10'b0000000000;
+ timer_r <= 13'b0000000000000;
+ bitcnt_r <= 4'b0000;
+ rdy_r <= 0;
+ err_r <= 0;
+ end else begin
+ ps2_clk_int_r <= ps2_clk_int_x;
+ data_r <= data_x;
+ timer_r <= timer_x;
+ bitcnt_r <= bitcnt_x;
+ rdy_r <= rdy_x;
+ err_r <= err_x;
+ end
+ end
+
+ // assign outputs
+ assign keyboard_data = data_r[7:0];
+ assign keyboard_rdy = rdy_r;
+
+endmodule
Index: trunk/fpga/src/kbd/kbd.v
===================================================================
--- trunk/fpga/src/kbd/kbd.v (nonexistent)
+++ trunk/fpga/src/kbd/kbd.v (revision 27)
@@ -0,0 +1,58 @@
+module kbd(ps2_clk, ps2_data,
+ clk, reset,
+ en, wr, addr2,
+ data_in, data_out,
+ wt, irq);
+ input ps2_clk;
+ input ps2_data;
+ input clk;
+ input reset;
+ input en;
+ input wr;
+ input addr2;
+ input [7:0] data_in;
+ output [7:0] data_out;
+ output wt;
+ output irq;
+
+ wire [7:0] keyboard_data;
+ wire keyboard_rdy;
+ reg [7:0] data;
+ reg rdy;
+ reg ien;
+
+ keyboard keyboard1(
+ .ps2_clk(ps2_clk),
+ .ps2_data(ps2_data),
+ .clk(clk),
+ .reset(reset),
+ .keyboard_data(keyboard_data[7:0]),
+ .keyboard_rdy(keyboard_rdy)
+ );
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ data <= 8'h00;
+ rdy <= 0;
+ ien <= 0;
+ end else begin
+ if (keyboard_rdy == 1) begin
+ data <= keyboard_data;
+ end
+ if (keyboard_rdy == 1 ||
+ (en == 1 && wr == 0 && addr2 == 1)) begin
+ rdy <= keyboard_rdy;
+ end
+ if (en == 1 && wr == 1 && addr2 == 0) begin
+ rdy <= data_in[0];
+ ien <= data_in[1];
+ end
+ end
+ end
+
+ assign data_out =
+ (addr2 == 0) ? { 6'b000000, ien, rdy } : data;
+ assign wt = 1'b0;
+ assign irq = ien & rdy;
+
+endmodule
Index: trunk/fpga/src/dsk/ataio.v
===================================================================
--- trunk/fpga/src/dsk/ataio.v (nonexistent)
+++ trunk/fpga/src/dsk/ataio.v (revision 27)
@@ -0,0 +1,111 @@
+module ata_io (clk, reset,
+ bus_en, bus_wr, bus_addr, bus_din, bus_dout, bus_wait,
+ ata_d, ata_a, ata_cs0_n, ata_cs1_n,
+ ata_dior_n, ata_diow_n, ata_iordy);
+ input clk;
+ input reset;
+ //
+ input bus_en;
+ input bus_wr;
+ input [3:0] bus_addr;
+ input [15:0] bus_din;
+ output reg [15:0] bus_dout;
+ output bus_wait;
+ //
+ inout [15:0] ata_d;
+ output reg [2:0] ata_a;
+ output reg ata_cs0_n;
+ output reg ata_cs1_n;
+ output reg ata_dior_n;
+ output reg ata_diow_n;
+ input ata_iordy;
+
+ reg [2:0] state;
+ reg [4:0] delay_counter;
+ reg ata_d_drive;
+
+ assign ata_d = ata_d_drive ? bus_din : 16'bzzzzzzzzzzzzzzzz;
+ assign bus_wait = bus_en & (state != 3'd5);
+
+ always @(posedge clk) begin
+ if (reset == 1'b1) begin
+ state <= 3'd0;
+ delay_counter <= 5'd31;
+ ata_d_drive <= 1'b0;
+ ata_a <= 3'b000;
+ ata_cs0_n <= 1'b1;
+ ata_cs1_n <= 1'b1;
+ ata_dior_n <= 1'b1;
+ ata_diow_n <= 1'b1;
+ bus_dout <= 16'd0;
+ end else begin
+ if (delay_counter == 5'd0) begin
+ case (state)
+
+ // ready - wait for request from the bus
+ 3'd0: begin
+ if (bus_en & ata_iordy) begin
+ // assert address and -> state 1, wait 3+1
+ // address mapping
+ // 0xxx : control block registers
+ // 1xxx : command block registers
+ ata_a[2:0] <= bus_addr[2:0];
+ ata_cs0_n <= ~bus_addr[3];
+ ata_cs1_n <= bus_addr[3];
+ state <= 3'd1;
+ delay_counter <= 5'd3;
+ end
+ end
+
+ // assert data-out and RW strobes, then -> state 2, wait 14+1
+ 3'd1: begin
+ ata_d_drive <= bus_wr;
+ ata_dior_n <= bus_wr;
+ ata_diow_n <= ~bus_wr;
+ state <= 3'd2;
+ delay_counter <= 5'd14;
+ end
+
+ // de-assert RW strobes and sample data-in,
+ // then -> state 3, wait 1+1
+ 3'd2: begin
+ bus_dout <= ata_d;
+ ata_dior_n <= 1'b1;
+ ata_diow_n <= 1'b1;
+ state <= 3'd3;
+ delay_counter <= 5'd1;
+ end
+
+ // de-assert data and address, then -> state 4, wait 7+1
+ // (such that 600 ns min cycle time is satisfied)
+ 3'd3: begin
+ ata_d_drive <= 1'b0;
+ ata_cs0_n <= 1'b1;
+ ata_cs1_n <= 1'b1;
+ state <= 3'd4;
+ delay_counter <= 5'd7;
+ end
+
+ // auxiliary state, for necessity see comment in state 5
+ 3'd4: begin
+ state <= 3'd5;
+ delay_counter <= 5'd0;
+ end
+
+ // finish - used to release bus wait
+ // WARNING: This state must not be entered with a delay!
+ // Otherwise bus wait will be released too early and
+ // subsequent bus cycles will not work properly.
+ 3'd5: begin
+ state <= 3'd0;
+ delay_counter <= 5'd0;
+ end
+
+ endcase
+ end else begin
+ delay_counter <= delay_counter - 1;
+ end
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/dsk/dsk.v
===================================================================
--- trunk/fpga/src/dsk/dsk.v (nonexistent)
+++ trunk/fpga/src/dsk/dsk.v (revision 27)
@@ -0,0 +1,50 @@
+module dsk(clk, reset,
+ en, wr, addr,
+ data_in, data_out,
+ wt, irq,
+ ata_d, ata_a, ata_cs0_n, ata_cs1_n,
+ ata_dior_n, ata_diow_n, ata_intrq,
+ ata_dmarq, ata_dmack_n, ata_iordy);
+ // internal interface signals
+ input clk;
+ input reset;
+ input en;
+ input wr;
+ input [19:2] addr;
+ input [31:0] data_in;
+ output [31:0] data_out;
+ output wt;
+ output irq;
+ // external interface signals
+ inout [15:0] ata_d;
+ output [2:0] ata_a;
+ output ata_cs0_n, ata_cs1_n;
+ output ata_dior_n, ata_diow_n;
+ input ata_intrq;
+ input ata_dmarq;
+ output ata_dmack_n;
+ input ata_iordy;
+
+ ata_ctrl ata_ctrl1 (
+ .clk(clk),
+ .reset(reset),
+ .bus_en(en),
+ .bus_wr(wr),
+ .bus_addr(addr),
+ .bus_din(data_in),
+ .bus_dout(data_out),
+ .bus_wait(wt),
+ .bus_irq(irq),
+ .ata_d(ata_d),
+ .ata_a(ata_a),
+ .ata_cs0_n(ata_cs0_n),
+ .ata_cs1_n(ata_cs1_n),
+ .ata_dior_n(ata_dior_n),
+ .ata_diow_n(ata_diow_n),
+ .ata_intrq(ata_intrq),
+ .ata_dmarq(ata_dmarq),
+ .ata_dmack_n(ata_dmack_n),
+ .ata_iordy(ata_iordy)
+ );
+
+endmodule
Index: trunk/fpga/src/dsk/atabuf.v
===================================================================
--- trunk/fpga/src/dsk/atabuf.v (nonexistent)
+++ trunk/fpga/src/dsk/atabuf.v (revision 27)
@@ -0,0 +1,91 @@
+module ata_buffer (clk,
+ bus_write, bus_addr, bus_din, bus_dout,
+ ata_write, ata_addr, ata_din, ata_dout);
+ input clk;
+ // bus interface
+ input bus_write;
+ input [11:2] bus_addr;
+ input [31:0] bus_din;
+ output [31:0] bus_dout;
+ // ata interface
+ input ata_write;
+ input [11:1] ata_addr;
+ input [15:0] ata_din;
+ output [15:0] ata_dout;
+
+ wire [9:0] internal_bus_addr;
+ wire [9:0] internal_ata_addr;
+ wire [15:0] lo_din_bus;
+ wire [15:0] hi_din_bus;
+ wire [15:0] lo_din_ata;
+ wire [15:0] hi_din_ata;
+ wire [15:0] lo_dout_bus;
+ wire [15:0] hi_dout_bus;
+ wire [15:0] lo_dout_ata;
+ wire [15:0] hi_dout_ata;
+ wire lo_write_bus;
+ wire hi_write_bus;
+ wire lo_write_ata;
+ wire hi_write_ata;
+ reg ata_out_muxctrl;
+
+ assign internal_bus_addr[9:0] = bus_addr[11:2];
+ assign internal_ata_addr[9:0] = ata_addr[11:2];
+
+ assign lo_din_bus = bus_din[15:0];
+ assign hi_din_bus = bus_din[31:16];
+ assign lo_din_ata = ata_din;
+ assign hi_din_ata = ata_din;
+
+ // pipeline register for ata output mux control
+ always @(posedge clk) begin
+ ata_out_muxctrl <= ata_addr[1];
+ end
+
+ assign bus_dout = { hi_dout_bus, lo_dout_bus };
+ assign ata_dout = ata_out_muxctrl ? lo_dout_ata : hi_dout_ata;
+
+ assign lo_write_bus = bus_write;
+ assign hi_write_bus = bus_write;
+ assign lo_write_ata = ata_write & ata_addr[1];
+ assign hi_write_ata = ata_write & ~ata_addr[1];
+
+ RAMB16_S18_S18 lo_buffer (
+ .DOA(lo_dout_bus),
+ .DOB(lo_dout_ata),
+ .ADDRA(internal_bus_addr),
+ .ADDRB(internal_ata_addr),
+ .CLKA(clk),
+ .CLKB(clk),
+ .DIA(lo_din_bus),
+ .DIB(lo_din_ata),
+ .DIPA(2'b00),
+ .DIPB(2'b00),
+ .ENA(1'b1),
+ .ENB(1'b1),
+ .SSRA(1'b0),
+ .SSRB(1'b0),
+ .WEA(lo_write_bus),
+ .WEB(lo_write_ata)
+ );
+
+ RAMB16_S18_S18 hi_buffer (
+ .DOA(hi_dout_bus),
+ .DOB(hi_dout_ata),
+ .ADDRA(internal_bus_addr),
+ .ADDRB(internal_ata_addr),
+ .CLKA(clk),
+ .CLKB(clk),
+ .DIA(hi_din_bus),
+ .DIB(hi_din_ata),
+ .DIPA(2'b00),
+ .DIPB(2'b00),
+ .ENA(1'b1),
+ .ENB(1'b1),
+ .SSRA(1'b0),
+ .SSRB(1'b0),
+ .WEA(hi_write_bus),
+ .WEB(hi_write_ata)
+ );
+
+endmodule
Index: trunk/fpga/src/dsk/atactrl.v
===================================================================
--- trunk/fpga/src/dsk/atactrl.v (nonexistent)
+++ trunk/fpga/src/dsk/atactrl.v (revision 27)
@@ -0,0 +1,501 @@
+`define ADDR_ALTERNATE_STATUS 4'b0110
+`define ADDR_DEVICE_CONTROL 4'b0110
+`define ADDR_DEVICE_ADDRESS 4'b0111
+`define ADDR_DATA 4'b1000
+`define ADDR_ERROR 4'b1001
+`define ADDR_FEATURES 4'b1001
+`define ADDR_SECTOR_COUNT 4'b1010
+`define ADDR_LBA0 4'b1011
+`define ADDR_LBA1 4'b1100
+`define ADDR_LBA2 4'b1101
+`define ADDR_LBA3_DRV 4'b1110
+`define ADDR_STATUS 4'b1111
+`define ADDR_COMMAND 4'b1111
+
+module ata_ctrl (
+ input clk, reset,
+
+ input bus_en, bus_wr,
+ input [19:2] bus_addr,
+ input [31:0] bus_din,
+ output [31:0] bus_dout,
+ output bus_wait,
+ output bus_irq,
+
+ inout [15:0] ata_d,
+ output [2:0] ata_a,
+ output ata_cs0_n, ata_cs1_n,
+ output ata_dior_n, ata_diow_n,
+ input ata_intrq,
+ input ata_dmarq,
+ output ata_dmack_n,
+ input ata_iordy
+);
+
+// --- ATA IRQ line debouncing
+reg debounced_ata_intrq, prev_ata_intrq;
+reg [3:0] ata_intrq_debounce_counter;
+
+// --- disk buffer
+
+// interface to the bus
+wire buffer_bus_wait;
+wire [31:0] buffer_bus_dout;
+
+// interface to the state machine
+wire buffer_ata_write;
+wire [11:1] buffer_ata_addr;
+wire [15:0] buffer_ata_din;
+wire [15:0] buffer_ata_dout;
+wire buffer_bus_addressed;
+wire buffer_bus_write;
+reg buffer_bus_second_cycle;
+
+ata_buffer buffer1 (
+ .clk (clk),
+ .bus_write (buffer_bus_write),
+ .bus_addr (bus_addr [11:2]),
+ .bus_din (bus_din),
+ .bus_dout (buffer_bus_dout),
+ .ata_write (buffer_ata_write),
+ .ata_addr (buffer_ata_addr),
+ .ata_din (buffer_ata_din),
+ .ata_dout (buffer_ata_dout)
+);
+
+assign buffer_bus_addressed = bus_addr [19];
+assign buffer_bus_wait = bus_en & !buffer_bus_second_cycle;
+assign buffer_bus_write = bus_en & bus_wr &
+ buffer_bus_addressed & !buffer_bus_second_cycle;
+
+// --- control registers
+
+// interface to the bus
+wire control_bus_wait;
+wire [31:0] control_bus_dout;
+
+// interface to the state machine
+reg [31:0] capacity;
+reg [27:0] requestedSectorAddress;
+reg [3:0] requestedSectorCount;
+wire commandUnlocked;
+reg enableInterrupts, requestedWrite, errorOutput;
+reg operationFinished, diskInitialized;
+wire control_bus_addressed;
+
+assign control_bus_addressed = !bus_addr[19];
+assign control_bus_wait = 0;
+assign control_bus_dout =
+ (bus_addr [3:2] == 2'b00) ? {ata_dmarq, 25'd0,
+ diskInitialized, operationFinished,
+ errorOutput, requestedWrite,
+ enableInterrupts, 1'b0} :
+ (bus_addr [3:2] == 2'b01) ? { 28'd0, requestedSectorCount } :
+ (bus_addr [3:2] == 2'b10) ? { 4'd0, requestedSectorAddress } :
+ capacity;
+
+// --- ATA IO component
+
+reg io_en, io_write;
+wire io_wait;
+reg [3:0] io_addr;
+reg [15:0] io_data_out;
+wire [15:0] io_data_in;
+
+assign ata_dmack_n = 1'b1;
+ata_io io (
+ .clk(clk),
+ .reset(reset),
+ .bus_en(io_en),
+ .bus_wr(io_write),
+ .bus_addr(io_addr),
+ .bus_din(io_data_out),
+ .bus_dout(io_data_in),
+ .bus_wait(io_wait),
+ .ata_d(ata_d),
+ .ata_a(ata_a),
+ .ata_cs0_n(ata_cs0_n),
+ .ata_cs1_n(ata_cs1_n),
+ .ata_dior_n(ata_dior_n),
+ .ata_diow_n(ata_diow_n),
+ .ata_iordy(ata_iordy)
+);
+
+// --- bus interface
+
+assign bus_dout = bus_addr [19] ? buffer_bus_dout : control_bus_dout;
+assign bus_wait = bus_addr [19] ? buffer_bus_wait : control_bus_wait;
+assign bus_irq = enableInterrupts & operationFinished;
+
+// --- state machine
+
+reg [4:0] state;
+reg [7:0] aux_counter;
+reg [2:0] sector_counter;
+/*
+ STARTUP DEBUG LOGGING
+reg [15:0] debugTimer;
+*/
+
+wire startBit;
+assign commandUnlocked = (state == 5'd8);
+assign startBit = bus_en & bus_wr &
+ (!bus_addr [19]) & (bus_addr [3:2] == 2'b00) &
+ bus_din [0];
+
+assign buffer_ata_write = (state == 5'd16) & (!io_wait);
+assign buffer_ata_addr = {sector_counter, aux_counter [7:0]};
+assign buffer_ata_din = io_data_in;
+
+always @(posedge clk) begin
+ if (reset) begin
+
+ prev_ata_intrq <= 1'b0;
+ debounced_ata_intrq <= 1'b0;
+ ata_intrq_debounce_counter <= 4'b0;
+
+ buffer_bus_second_cycle <= 1'b0;
+
+ capacity <= 32'd0;
+ requestedSectorAddress <= 32'd0;
+ requestedSectorCount <= 4'b0000;
+
+ enableInterrupts <= 1'b0;
+ requestedWrite <= 1'b0;
+ errorOutput <= 1'b0;
+ operationFinished <= 1'b0;
+ diskInitialized <= 1'b0;
+
+ io_en <= 1'b0;
+ io_write <= 1'b0;
+ io_addr <= 32'd0;
+ io_data_out <= 16'd0;
+
+ state <= 5'd0;
+ aux_counter <= 8'd0;
+ sector_counter <= 3'd0;
+
+/*
+ STARTUP DEBUG LOGGING
+ debugTimer <= 16'd0;
+*/
+
+ end else begin
+
+ if (ata_intrq == prev_ata_intrq) begin
+ if (ata_intrq_debounce_counter == 4'd0) begin
+ debounced_ata_intrq <= ata_intrq;
+ end else begin
+ ata_intrq_debounce_counter <= ata_intrq_debounce_counter - 1;
+ end
+ end else begin
+ ata_intrq_debounce_counter <= 4'd10;
+ end
+ prev_ata_intrq <= ata_intrq;
+
+/*
+ STARTUP DEBUG LOGGING
+ debugTimer <= debugTimer + 1;
+*/
+
+ if (bus_en)
+ buffer_bus_second_cycle <= !buffer_bus_second_cycle;
+ else
+ buffer_bus_second_cycle <= 1'b0;
+
+ if (bus_en & bus_wr & control_bus_addressed) begin
+ if (bus_addr [3:2] == 2'b00) begin
+ operationFinished <= bus_din [4];
+ if (commandUnlocked)
+ requestedWrite <= bus_din [2];
+ enableInterrupts <= bus_din [1];
+ end
+ else if (bus_addr [3:2] == 2'b01 & commandUnlocked) begin
+ requestedSectorCount <= bus_din [3:0];
+ end
+ else if (bus_addr [3:2] == 2'b10 & commandUnlocked) begin
+ requestedSectorAddress <= bus_din [27:0];
+ end
+ end
+
+ if (!io_wait) begin
+/*
+ STARTUP DEBUG LOGGING
+ buffer_ata_write <= 1;
+ if (buffer_ata_addr < 2000)
+ buffer_ata_addr <= buffer_ata_addr + 2;
+ buffer_ata_din <= io_data_in;
+*/
+ case (state)
+
+ // startup sequence: ask for access to command regs
+ // and drive
+ 5'd0: begin
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_ALTERNATE_STATUS;
+ state <= 5'd1;
+ end
+
+ // startup sequence: wait for command regs and
+ // drive, or select drive 0 if ready
+ 5'd1: begin
+ if (io_data_in [7:6] == 2'b01) begin
+ // ready, so select drive 0
+ io_write <= 1'b1;
+ io_addr <= `ADDR_LBA3_DRV;
+ io_data_out <= 8'b11100000;
+ state <= 5'd2;
+ end else begin
+ // busy, so keep asking
+ end
+ end
+
+ // startup sequence: send "identify drive" command
+ 5'd2: begin
+ io_write <= 1'b1;
+ io_addr <= `ADDR_COMMAND;
+ io_data_out <= 16'h00ec;
+ state <= 5'd3;
+ end
+
+ // wait for the ATA to send an IRQ, then read the status register
+ 5'd3: begin
+ if (debounced_ata_intrq) begin
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_STATUS;
+ aux_counter <= 8'd60;
+ state <= 5'd4;
+ end else begin
+ io_en <= 1'b0;
+ io_write <= 1'b0;
+ end
+ end
+
+
+ // skip 60 words from the data buffer, then read
+ // the high 16 bits of the capacity
+ 5'd4: begin
+ io_write <= 1'b0;
+ io_addr <= `ADDR_DATA;
+ if (aux_counter == 0) state <= 5'd5;
+ else aux_counter <= aux_counter - 1;
+ end
+
+ // store the high 16 bits of the capacity just
+ // read and read the low 16 bits
+ 5'd5: begin
+ io_write <= 1'b0;
+ io_addr <= `ADDR_DATA;
+ capacity [15:0] <= io_data_in;
+ state <= 5'd6;
+ end
+
+ // store the low 16 bits of the capacity,
+ // then read another 194 words to finish the
+ // "identify drive" buffer
+ 5'd6: begin
+ capacity [31:16] <= io_data_in;
+ state <= 5'd7;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_DATA;
+ aux_counter <= 8'd193; // one is read now
+ end
+
+ // skip another 193 words from the buffer
+ 5'd7: begin
+ if (aux_counter == 0) begin
+ io_en <= 1'b0;
+ io_write <= 1'b0;
+ state <= 5'd8;
+ diskInitialized <= 1'b1;
+ end else begin
+ aux_counter <= aux_counter - 1;
+ end
+ end
+
+ //----------------------------------------------------------
+
+ // ready and waiting for commands. Only on this
+ // state is write access from the on-chip bus
+ // allowed. When a request arrives, write the
+ // drive/head/lba3 register and goto state 9.
+ 5'd8: begin
+ if (startBit) begin
+ state <= 5'd19;
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_STATUS;
+ end else begin
+ io_en <= 1'b0;
+ end
+ end
+
+ 5'd19: begin
+ if (io_data_in[7] == 0) begin
+ state <= 5'd9;
+ io_en <= 1'b1;
+ io_write <= 1'b1;
+ io_addr <= `ADDR_LBA3_DRV;
+ io_data_out <=
+ { 8'd0, 4'b1110, requestedSectorAddress [27:24] };
+ sector_counter <= 3'd0;
+ end else begin
+ // read status again
+ end
+ end
+
+ // next, write the lba2 register
+ 5'd9: begin
+ io_addr <= `ADDR_LBA2;
+ io_data_out <= { 8'd0, requestedSectorAddress [23:16] };
+ state <= 5'd10;
+ end
+
+ // next, write the lba1 register
+ 5'd10: begin
+ io_addr <= `ADDR_LBA1;
+ io_data_out <= { 8'd0, requestedSectorAddress [15:8] };
+ state <= 5'd11;
+ end
+
+ // next, write the lba0 register
+ 5'd11: begin
+ io_addr <= `ADDR_LBA0;
+ io_data_out <= { 8'd0, requestedSectorAddress [7:0] };
+ state <= 5'd12;
+ end
+
+ // next, write the sector count register
+ 5'd12: begin
+ io_addr <= `ADDR_SECTOR_COUNT;
+ io_data_out <= { 8'd0, 4'd0, requestedSectorCount };
+ state <= 5'd13;
+ end
+
+ // finally, write the command register
+ 5'd13: begin
+ io_addr <= `ADDR_COMMAND;
+ io_data_out <= requestedWrite ? 16'h30 : 16'h20;
+ state <= 5'd14;
+ end
+
+ // now branch whether reading or writing.
+ // for reading, wait for IRQ, then read status
+ // for writing, wait for DRQ and simultaneously
+ // fetch the first word from the buffer
+ 5'd14: begin
+ if (requestedWrite) begin
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_STATUS;
+ state <= 5'd17;
+ aux_counter <= 8'd0;
+ end else begin
+ if (debounced_ata_intrq) begin
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_STATUS;
+ state <= 5'd15;
+ end else begin
+ io_en <= 1'b0;
+ end
+ end
+ end
+
+ // read 256 words of data
+ 5'd15: begin
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_DATA;
+ aux_counter <= 8'd0;
+ state <= 5'd16;
+ end
+
+ // sample data in, and read next if needed. Data sampling is
+ // done directly by the blockRAM, and the necessary wiring is
+ // defined above.
+ 5'd16: begin
+ if (aux_counter == 8'd255) begin
+ if (requestedSectorCount == 4'b0001) begin
+ io_en <= 1'b0;
+ state <= 5'd8;
+ errorOutput <= 1'b0;
+ operationFinished <= 1'b1;
+ end else begin
+ if (debounced_ata_intrq) begin
+ requestedSectorCount <= requestedSectorCount - 1;
+ sector_counter <= sector_counter + 1;
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_STATUS;
+ state <= 5'd15;
+ end else begin
+ io_en <= 1'b0;
+ // last word of finished sector is sampled
+ // repeatedly here (harmless)
+ end
+ end
+ end else begin
+ aux_counter <= aux_counter + 1;
+ end
+ end
+
+ // if DRQ is not yet set, wait for it. Otherwise send the
+ // first data word to the ATA and fetch the next one
+ 5'd17: begin
+ if (io_data_in[7] == 0 && io_data_in[3] == 1) begin
+ io_en <= 1'b1;
+ io_write <= 1'b1;
+ io_addr <= `ADDR_DATA;
+ io_data_out <= buffer_ata_dout;
+ aux_counter <= aux_counter + 1;
+ state <= 5'd18;
+ end else begin
+ // read status again
+ end
+ end
+
+ // write words to the buffer until finished. Note that since
+ // an ATA transfer cycle takes at least two clock cycles, the
+ // buffer is always read to buffer_ata_dout before that register
+ // is used. After the transfer is finished, wait for IRQ, then
+ // read the status register and select the correct next state
+ // depending on whether more sectors must follow.
+ 5'd18: begin
+ // loop until done. All addressing is done automatically.
+ if (aux_counter == 8'd0) begin
+ if (debounced_ata_intrq) begin
+ io_en <= 1'b1;
+ io_write <= 1'b0;
+ io_addr <= `ADDR_STATUS;
+ if (requestedSectorCount == 4'b0001) begin
+ state <= 5'd8;
+ errorOutput <= 1'b0;
+ operationFinished <= 1'b1;
+ end else begin
+ requestedSectorCount <= requestedSectorCount - 1;
+ sector_counter <= sector_counter + 1;
+ state <= 5'd17;
+ end
+ end else begin
+ io_en <= 1'b0;
+ end
+ end else begin
+ io_data_out <= buffer_ata_dout;
+ aux_counter <= aux_counter + 1;
+ end
+ end
+
+ endcase
+ end else begin
+/*
+ STARTUP DEBUG LOGGING
+ buffer_ata_write <= 0;
+*/
+ end
+ end
+end
+
+endmodule
Index: trunk/fpga/src/tmr/tmr.v
===================================================================
--- trunk/fpga/src/tmr/tmr.v (nonexistent)
+++ trunk/fpga/src/tmr/tmr.v (revision 27)
@@ -0,0 +1,88 @@
+module tmr(clk, reset,
+ en, wr, addr2,
+ data_in, data_out,
+ wt, irq);
+ input clk;
+ input reset;
+ input en;
+ input wr;
+ input addr2;
+ input [31:0] data_in;
+ output [31:0] data_out;
+ output wt;
+ output irq;
+
+ reg [15:0] prescaler;
+ reg tick;
+ reg [31:0] counter;
+ reg [31:0] divisor;
+ reg divisor_loaded;
+ reg expired;
+ reg alarm;
+ reg ien;
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ prescaler <= 16'd50000;
+ tick <= 0;
+ end else begin
+ if (prescaler == 16'd1) begin
+ prescaler <= 16'd50000;
+ tick <= 1;
+ end else begin
+ prescaler <= prescaler - 1;
+ tick <= 0;
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+ if (divisor_loaded == 1) begin
+ counter <= divisor;
+ expired <= 0;
+ end else begin
+ if (tick == 1) begin
+ if (counter == 32'h00000001) begin
+ counter <= divisor;
+ expired <= 1;
+ end else begin
+ counter <= counter - 1;
+ expired <= 0;
+ end
+ end else begin
+ expired <= 0;
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ divisor <= 32'hFFFFFFFF;
+ divisor_loaded <= 1;
+ alarm <= 0;
+ ien <= 0;
+ end else begin
+ if (expired == 1) begin
+ alarm <= 1;
+ end else begin
+ if (en == 1 && wr == 1 && addr2 == 0) begin
+ alarm <= data_in[0];
+ ien <= data_in[1];
+ end
+ if (en == 1 && wr == 1 && addr2 == 1) begin
+ divisor <= data_in;
+ divisor_loaded <= 1;
+ end else begin
+ divisor_loaded <= 0;
+ end
+ end
+ end
+ end
+
+ assign data_out =
+ (addr2 == 0) ? { 28'h0000000, 2'b00, ien, alarm } :
+ divisor;
+ assign wt = 0;
+ assign irq = ien & alarm;
+
+endmodule
Index: trunk/fpga/src/dsp/pixel.v
===================================================================
--- trunk/fpga/src/dsp/pixel.v (nonexistent)
+++ trunk/fpga/src/dsp/pixel.v (revision 27)
@@ -0,0 +1,64 @@
+module pixel(clk, pixclk, attcode,
+ pixel, blank, hsync_in, vsync_in, blink,
+ r, g, b, hsync, vsync);
+ input clk;
+ input pixclk;
+ input [7:0] attcode;
+ input pixel;
+ input blank;
+ input hsync_in;
+ input vsync_in;
+ input blink;
+ output reg [2:0] r;
+ output reg [2:0] g;
+ output reg [2:0] b;
+ output reg hsync;
+ output reg vsync;
+
+ wire blink_bit;
+ wire bg_red;
+ wire bg_green;
+ wire bg_blue;
+ wire inten_bit;
+ wire fg_red;
+ wire fg_green;
+ wire fg_blue;
+ wire foreground;
+ wire intensify;
+ wire red;
+ wire green;
+ wire blue;
+
+ assign blink_bit = attcode[7];
+ assign bg_red = attcode[6];
+ assign bg_green = attcode[5];
+ assign bg_blue = attcode[4];
+ assign inten_bit = attcode[3];
+ assign fg_red = attcode[2];
+ assign fg_green = attcode[1];
+ assign fg_blue = attcode[0];
+
+ assign foreground = pixel & ~(blink_bit & blink);
+ assign intensify = foreground & inten_bit;
+
+ assign red = (foreground ? fg_red : bg_red);
+ assign green = (foreground ? fg_green : bg_green);
+ assign blue = (foreground ? fg_blue : bg_blue);
+
+ always @(posedge clk) begin
+ if (pixclk == 1) begin
+ r[2] <= blank & red;
+ r[1] <= blank & intensify;
+ r[0] <= blank & red & intensify;
+ g[2] <= blank & green;
+ g[1] <= blank & intensify;
+ g[0] <= blank & green & intensify;
+ b[2] <= blank & blue;
+ b[1] <= blank & intensify;
+ b[0] <= blank & blue & intensify;
+ hsync <= hsync_in;
+ vsync <= vsync_in;
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/dsp/display.v
===================================================================
--- trunk/fpga/src/dsp/display.v (nonexistent)
+++ trunk/fpga/src/dsp/display.v (revision 27)
@@ -0,0 +1,118 @@
+module display(clk,
+ dsp_row, dsp_col, dsp_en, dsp_wr,
+ dsp_wr_data, dsp_rd_data,
+ hsync, vsync, r, g, b);
+
+ input clk;
+ input [4:0] dsp_row;
+ input [6:0] dsp_col;
+ input dsp_en;
+ input dsp_wr;
+ input [15:0] dsp_wr_data;
+ output [15:0] dsp_rd_data;
+ output hsync;
+ output vsync;
+ output [2:0] r;
+ output [2:0] g;
+ output [2:0] b;
+
+ wire pixclk;
+ wire [4:0] timing_txtrow;
+ wire [6:0] timing_txtcol;
+ wire [3:0] timing_chrrow;
+ wire [2:0] timing_chrcol;
+ wire timing_blank;
+ wire timing_hsync;
+ wire timing_vsync;
+ wire timing_blink;
+ wire [7:0] dspmem_attcode;
+ wire [7:0] dspmem_chrcode;
+ wire [3:0] dspmem_chrrow;
+ wire [2:0] dspmem_chrcol;
+ wire dspmem_blank;
+ wire dspmem_hsync;
+ wire dspmem_vsync;
+ wire dspmem_blink;
+ wire [7:0] chrgen_attcode;
+ wire chrgen_pixel;
+ wire chrgen_blank;
+ wire chrgen_hsync;
+ wire chrgen_vsync;
+ wire chrgen_blink;
+
+ timing timing1(
+ .clk(clk),
+ .pixclk(pixclk),
+ .txtrow(timing_txtrow[4:0]),
+ .txtcol(timing_txtcol[6:0]),
+ .chrrow(timing_chrrow[3:0]),
+ .chrcol(timing_chrcol[2:0]),
+ .blank(timing_blank),
+ .hsync(timing_hsync),
+ .vsync(timing_vsync),
+ .blink(timing_blink)
+ );
+
+ dspmem dspmem1(
+ .rdwr_row(dsp_row[4:0]),
+ .rdwr_col(dsp_col[6:0]),
+ .wr_data(dsp_wr_data[15:0]),
+ .rd_data(dsp_rd_data[15:0]),
+ .en(dsp_en),
+ .wr(dsp_wr),
+ .clk(clk),
+ .pixclk(pixclk),
+ .txtrow(timing_txtrow[4:0]),
+ .txtcol(timing_txtcol[6:0]),
+ .attcode(dspmem_attcode[7:0]),
+ .chrcode(dspmem_chrcode[7:0]),
+ .chrrow_in(timing_chrrow[3:0]),
+ .chrcol_in(timing_chrcol[2:0]),
+ .blank_in(timing_blank),
+ .hsync_in(timing_hsync),
+ .vsync_in(timing_vsync),
+ .blink_in(timing_blink),
+ .chrrow_out(dspmem_chrrow[3:0]),
+ .chrcol_out(dspmem_chrcol[2:0]),
+ .blank_out(dspmem_blank),
+ .hsync_out(dspmem_hsync),
+ .vsync_out(dspmem_vsync),
+ .blink_out(dspmem_blink)
+ );
+
+ chrgen chrgen1(
+ .clk(clk),
+ .pixclk(pixclk),
+ .chrcode(dspmem_chrcode[7:0]),
+ .chrrow(dspmem_chrrow[3:0]),
+ .chrcol(dspmem_chrcol[2:0]),
+ .pixel(chrgen_pixel),
+ .attcode_in(dspmem_attcode[7:0]),
+ .blank_in(dspmem_blank),
+ .hsync_in(dspmem_hsync),
+ .vsync_in(dspmem_vsync),
+ .blink_in(dspmem_blink),
+ .attcode_out(chrgen_attcode[7:0]),
+ .blank_out(chrgen_blank),
+ .hsync_out(chrgen_hsync),
+ .vsync_out(chrgen_vsync),
+ .blink_out(chrgen_blink)
+ );
+
+ pixel pixel1(
+ .clk(clk),
+ .pixclk(pixclk),
+ .attcode(chrgen_attcode[7:0]),
+ .pixel(chrgen_pixel),
+ .blank(chrgen_blank),
+ .hsync_in(chrgen_hsync),
+ .vsync_in(chrgen_vsync),
+ .blink(chrgen_blink),
+ .r(r[2:0]),
+ .g(g[2:0]),
+ .b(b[2:0]),
+ .hsync(hsync),
+ .vsync(vsync)
+ );
+
+endmodule
Index: trunk/fpga/src/dsp/dspmem.v
===================================================================
--- trunk/fpga/src/dsp/dspmem.v (nonexistent)
+++ trunk/fpga/src/dsp/dspmem.v (revision 27)
@@ -0,0 +1,488 @@
+module dspmem(rdwr_row, rdwr_col, wr_data, rd_data, en, wr,
+ clk, pixclk,
+ txtrow, txtcol, attcode, chrcode,
+ chrrow_in, chrcol_in, blank_in,
+ hsync_in, vsync_in, blink_in,
+ chrrow_out, chrcol_out, blank_out,
+ hsync_out, vsync_out, blink_out);
+ input [4:0] rdwr_row;
+ input [6:0] rdwr_col;
+ input [15:0] wr_data;
+ output [15:0] rd_data;
+ input en;
+ input wr;
+ input clk;
+ input pixclk;
+ input [4:0] txtrow;
+ input [6:0] txtcol;
+ output [7:0] attcode;
+ output [7:0] chrcode;
+ input [3:0] chrrow_in;
+ input [2:0] chrcol_in;
+ input blank_in;
+ input hsync_in;
+ input vsync_in;
+ input blink_in;
+ output reg [3:0] chrrow_out;
+ output reg [2:0] chrcol_out;
+ output reg blank_out;
+ output reg hsync_out;
+ output reg vsync_out;
+ output reg blink_out;
+
+ wire [11:0] rdwr_addr;
+ wire [3:0] rdwr_din_n3;
+ wire [3:0] rdwr_din_n2;
+ wire [3:0] rdwr_din_n1;
+ wire [3:0] rdwr_din_n0;
+ wire [3:0] rdwr_dout_n3;
+ wire [3:0] rdwr_dout_n2;
+ wire [3:0] rdwr_dout_n1;
+ wire [3:0] rdwr_dout_n0;
+
+ wire [11:0] rfsh_addr;
+ wire [3:0] rfsh_din_n3;
+ wire [3:0] rfsh_din_n2;
+ wire [3:0] rfsh_din_n1;
+ wire [3:0] rfsh_din_n0;
+ wire [3:0] rfsh_dout_n3;
+ wire [3:0] rfsh_dout_n2;
+ wire [3:0] rfsh_dout_n1;
+ wire [3:0] rfsh_dout_n0;
+
+ assign rdwr_addr[11:7] = rdwr_row[4:0];
+ assign rdwr_addr[6:0] = rdwr_col[6:0];
+ assign rdwr_din_n3 = wr_data[15:12];
+ assign rdwr_din_n2 = wr_data[11: 8];
+ assign rdwr_din_n1 = wr_data[ 7: 4];
+ assign rdwr_din_n0 = wr_data[ 3: 0];
+ assign rd_data[15:12] = rdwr_dout_n3;
+ assign rd_data[11: 8] = rdwr_dout_n2;
+ assign rd_data[ 7: 4] = rdwr_dout_n1;
+ assign rd_data[ 3: 0] = rdwr_dout_n0;
+
+ assign rfsh_addr[11:7] = txtrow[4:0];
+ assign rfsh_addr[6:0] = txtcol[6:0];
+ assign rfsh_din_n3 = 4'b0000;
+ assign rfsh_din_n2 = 4'b0000;
+ assign rfsh_din_n1 = 4'b0000;
+ assign rfsh_din_n0 = 4'b0000;
+ assign attcode[7:4] = rfsh_dout_n3;
+ assign attcode[3:0] = rfsh_dout_n2;
+ assign chrcode[7:4] = rfsh_dout_n1;
+ assign chrcode[3:0] = rfsh_dout_n0;
+
+//--------------------------------------------------------------
+
+ // RAMB16_S4_S4: Virtex-II/II-Pro, Spartan-3 4k x 4 Dual-Port RAM
+ // Xilinx HDL Language Template version 6.3.1i
+
+ RAMB16_S4_S4 display_att_hi (
+ .DOA(rdwr_dout_n3), // Port A 4-bit Data Output
+ .DOB(rfsh_dout_n3), // Port B 4-bit Data Output
+ .ADDRA(rdwr_addr), // Port A 12-bit Address Input
+ .ADDRB(rfsh_addr), // Port B 12-bit Address Input
+ .CLKA(clk), // Port A Clock
+ .CLKB(clk), // Port B Clock
+ .DIA(rdwr_din_n3), // Port A 4-bit Data Input
+ .DIB(rfsh_din_n3), // Port B 4-bit Data Input
+ .ENA(en), // Port A RAM Enable Input
+ .ENB(pixclk), // Port B RAM Enable Input
+ .SSRA(1'b0), // Port A Synchronous Set/Reset Input
+ .SSRB(1'b0), // Port B Synchronous Set/Reset Input
+ .WEA(wr), // Port A Write Enable Input
+ .WEB(1'b0) // Port B Write Enable Input
+ );
+
+ // The following defparam declarations are only necessary if you wish to change the default behavior
+ // of the RAM. If the instance name is changed, these defparams need to be updated accordingly.
+
+ defparam display_att_hi.INIT_A = 18'h0; // Value of output RAM registers on Port A at startup
+ defparam display_att_hi.INIT_B = 18'h0; // Value of output RAM registers on Port B at startup
+ defparam display_att_hi.SRVAL_A = 18'h0; // Port A ouput value upon SSR assertion
+ defparam display_att_hi.SRVAL_B = 18'h0; // Port B ouput value upon SSR assertion
+ defparam display_att_hi.WRITE_MODE_A = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+ defparam display_att_hi.WRITE_MODE_B = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+
+ // The following defparam INIT_xx declarations are only necessary if you wish to change the initial
+ // contents of the RAM to anything other than all zero's.
+
+ defparam display_att_hi.INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_hi.INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+//--------------------------------------------------------------
+
+ // RAMB16_S4_S4: Virtex-II/II-Pro, Spartan-3 4k x 4 Dual-Port RAM
+ // Xilinx HDL Language Template version 6.3.1i
+
+ RAMB16_S4_S4 display_att_lo (
+ .DOA(rdwr_dout_n2), // Port A 4-bit Data Output
+ .DOB(rfsh_dout_n2), // Port B 4-bit Data Output
+ .ADDRA(rdwr_addr), // Port A 12-bit Address Input
+ .ADDRB(rfsh_addr), // Port B 12-bit Address Input
+ .CLKA(clk), // Port A Clock
+ .CLKB(clk), // Port B Clock
+ .DIA(rdwr_din_n2), // Port A 4-bit Data Input
+ .DIB(rfsh_din_n2), // Port B 4-bit Data Input
+ .ENA(en), // Port A RAM Enable Input
+ .ENB(pixclk), // Port B RAM Enable Input
+ .SSRA(1'b0), // Port A Synchronous Set/Reset Input
+ .SSRB(1'b0), // Port B Synchronous Set/Reset Input
+ .WEA(wr), // Port A Write Enable Input
+ .WEB(1'b0) // Port B Write Enable Input
+ );
+
+ // The following defparam declarations are only necessary if you wish to change the default behavior
+ // of the RAM. If the instance name is changed, these defparams need to be updated accordingly.
+
+ defparam display_att_lo.INIT_A = 18'h0; // Value of output RAM registers on Port A at startup
+ defparam display_att_lo.INIT_B = 18'h0; // Value of output RAM registers on Port B at startup
+ defparam display_att_lo.SRVAL_A = 18'h0; // Port A ouput value upon SSR assertion
+ defparam display_att_lo.SRVAL_B = 18'h0; // Port B ouput value upon SSR assertion
+ defparam display_att_lo.WRITE_MODE_A = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+ defparam display_att_lo.WRITE_MODE_B = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+
+ // The following defparam INIT_xx declarations are only necessary if you wish to change the initial
+ // contents of the RAM to anything other than all zero's.
+
+ defparam display_att_lo.INIT_00 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_01 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_02 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_03 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_04 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_05 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_06 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_07 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_08 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_09 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_0A = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_0B = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_0C = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_0D = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_0E = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_0F = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_10 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_11 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_12 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_13 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_14 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_15 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_16 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_17 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_18 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_19 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_1A = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_1B = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_1C = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_1D = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_1E = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_1F = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_20 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_21 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_22 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_23 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_24 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_25 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_26 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_27 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_28 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_29 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_2A = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_2B = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_2C = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_2D = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_2E = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_2F = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_30 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_31 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_32 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_33 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_34 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_35 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_36 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_37 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_38 = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_39 = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_3A = 256'h7777777777777777777777777777777777777777777777777777777777777777;
+ defparam display_att_lo.INIT_3B = 256'h0000000000000000000000000000000000000000000000007777777777777777;
+ defparam display_att_lo.INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_lo.INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_lo.INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_att_lo.INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+//--------------------------------------------------------------
+
+ // RAMB16_S4_S4: Virtex-II/II-Pro, Spartan-3 4k x 4 Dual-Port RAM
+ // Xilinx HDL Language Template version 6.3.1i
+
+ RAMB16_S4_S4 display_chr_hi (
+ .DOA(rdwr_dout_n1), // Port A 4-bit Data Output
+ .DOB(rfsh_dout_n1), // Port B 4-bit Data Output
+ .ADDRA(rdwr_addr), // Port A 12-bit Address Input
+ .ADDRB(rfsh_addr), // Port B 12-bit Address Input
+ .CLKA(clk), // Port A Clock
+ .CLKB(clk), // Port B Clock
+ .DIA(rdwr_din_n1), // Port A 4-bit Data Input
+ .DIB(rfsh_din_n1), // Port B 4-bit Data Input
+ .ENA(en), // Port A RAM Enable Input
+ .ENB(pixclk), // Port B RAM Enable Input
+ .SSRA(1'b0), // Port A Synchronous Set/Reset Input
+ .SSRB(1'b0), // Port B Synchronous Set/Reset Input
+ .WEA(wr), // Port A Write Enable Input
+ .WEB(1'b0) // Port B Write Enable Input
+ );
+
+ // The following defparam declarations are only necessary if you wish to change the default behavior
+ // of the RAM. If the instance name is changed, these defparams need to be updated accordingly.
+
+ defparam display_chr_hi.INIT_A = 18'h0; // Value of output RAM registers on Port A at startup
+ defparam display_chr_hi.INIT_B = 18'h0; // Value of output RAM registers on Port B at startup
+ defparam display_chr_hi.SRVAL_A = 18'h0; // Port A ouput value upon SSR assertion
+ defparam display_chr_hi.SRVAL_B = 18'h0; // Port B ouput value upon SSR assertion
+ defparam display_chr_hi.WRITE_MODE_A = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+ defparam display_chr_hi.WRITE_MODE_B = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+
+ // The following defparam INIT_xx declarations are only necessary if you wish to change the initial
+ // contents of the RAM to anything other than all zero's.
+
+ defparam display_chr_hi.INIT_00 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_01 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_02 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_03 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_04 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_05 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_06 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_07 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_08 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_09 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_0A = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_0B = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_0C = 256'h2726262727262422272627262627262624222626272626252222222222222222;
+ defparam display_chr_hi.INIT_0D = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_0E = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_0F = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_10 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_11 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_12 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_13 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_14 = 256'h2727262726262726262422232322272227262626242223232222222222222222;
+ defparam display_chr_hi.INIT_15 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_16 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_17 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_18 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_19 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_1A = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_1B = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_1C = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_1D = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_1E = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_1F = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_20 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_21 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_22 = 256'h2222222222222227272627272627262625222222222222222222222222222222;
+ defparam display_chr_hi.INIT_23 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_24 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_25 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_26 = 256'h2222222222222222222222262622222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_27 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_28 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_29 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_2A = 256'h2222222227262626262626252226262626272724222222222222222222222222;
+ defparam display_chr_hi.INIT_2B = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_2C = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_2D = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_2E = 256'h2222222222222222226262727262624222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_2F = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_30 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_31 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_32 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_33 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_34 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_35 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_36 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_37 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_38 = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_39 = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_3A = 256'h2222222222222222222222222222222222222222222222222222222222222222;
+ defparam display_chr_hi.INIT_3B = 256'h0000000000000000000000000000000000000000000000002222222222222222;
+ defparam display_chr_hi.INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_hi.INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_hi.INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_hi.INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+//--------------------------------------------------------------
+
+ // RAMB16_S4_S4: Virtex-II/II-Pro, Spartan-3 4k x 4 Dual-Port RAM
+ // Xilinx HDL Language Template version 6.3.1i
+
+ RAMB16_S4_S4 display_chr_lo (
+ .DOA(rdwr_dout_n0), // Port A 4-bit Data Output
+ .DOB(rfsh_dout_n0), // Port B 4-bit Data Output
+ .ADDRA(rdwr_addr), // Port A 12-bit Address Input
+ .ADDRB(rfsh_addr), // Port B 12-bit Address Input
+ .CLKA(clk), // Port A Clock
+ .CLKB(clk), // Port B Clock
+ .DIA(rdwr_din_n0), // Port A 4-bit Data Input
+ .DIB(rfsh_din_n0), // Port B 4-bit Data Input
+ .ENA(en), // Port A RAM Enable Input
+ .ENB(pixclk), // Port B RAM Enable Input
+ .SSRA(1'b0), // Port A Synchronous Set/Reset Input
+ .SSRB(1'b0), // Port B Synchronous Set/Reset Input
+ .WEA(wr), // Port A Write Enable Input
+ .WEB(1'b0) // Port B Write Enable Input
+ );
+
+ // The following defparam declarations are only necessary if you wish to change the default behavior
+ // of the RAM. If the instance name is changed, these defparams need to be updated accordingly.
+
+ defparam display_chr_lo.INIT_A = 18'h0; // Value of output RAM registers on Port A at startup
+ defparam display_chr_lo.INIT_B = 18'h0; // Value of output RAM registers on Port B at startup
+ defparam display_chr_lo.SRVAL_A = 18'h0; // Port A ouput value upon SSR assertion
+ defparam display_chr_lo.SRVAL_B = 18'h0; // Port B ouput value upon SSR assertion
+ defparam display_chr_lo.WRITE_MODE_A = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+ defparam display_chr_lo.WRITE_MODE_B = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+
+ // The following defparam INIT_xx declarations are only necessary if you wish to change the initial
+ // contents of the RAM to anything other than all zero's.
+
+ defparam display_chr_lo.INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_0C = 256'h09010C000309040002050403010201080300050C000D09030000000000000000;
+ defparam display_chr_lo.INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_14 = 256'h0302050403010201080300000800080003050E090C0000030000000000000000;
+ defparam display_chr_lo.INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_22 = 256'h0000000000000009040903020506090E05000000000000000000000000000000;
+ defparam display_chr_lo.INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_26 = 256'h0000000000000000000000060F00000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_2A = 256'h000000000305030E05090303000405090C000001000000000000000000000000;
+ defparam display_chr_lo.INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_2E = 256'h000000000000000000E050303050907000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ defparam display_chr_lo.INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+//--------------------------------------------------------------
+
+ always @(posedge clk) begin
+ if (pixclk == 1) begin
+ chrrow_out <= chrrow_in;
+ chrcol_out <= chrcol_in;
+ blank_out <= blank_in;
+ hsync_out <= hsync_in;
+ vsync_out <= vsync_in;
+ blink_out <= blink_in;
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/dsp/chrgen.v
===================================================================
--- trunk/fpga/src/dsp/chrgen.v (nonexistent)
+++ trunk/fpga/src/dsp/chrgen.v (revision 27)
@@ -0,0 +1,222 @@
+module chrgen(clk, pixclk,
+ chrcode, chrrow, chrcol,
+ pixel,
+ attcode_in, blank_in, hsync_in, vsync_in, blink_in,
+ attcode_out, blank_out, hsync_out, vsync_out, blink_out);
+ input clk;
+ input pixclk;
+ input [7:0] chrcode;
+ input [3:0] chrrow;
+ input [2:0] chrcol;
+ output pixel;
+ input [7:0] attcode_in;
+ input blank_in;
+ input hsync_in;
+ input vsync_in;
+ input blink_in;
+ output reg [7:0] attcode_out;
+ output reg blank_out;
+ output reg hsync_out;
+ output reg vsync_out;
+ output reg blink_out;
+
+ wire [13:0] addr;
+ wire [0:0] pixel_lo;
+ wire [0:0] pixel_hi;
+
+ reg mux_ctrl;
+
+ assign addr[13:7] = chrcode[6:0];
+ assign addr[6:3] = chrrow[3:0];
+ assign addr[2:0] = chrcol[2:0];
+
+ assign pixel = (mux_ctrl == 0) ? pixel_lo[0] : pixel_hi[0];
+
+ // RAMB16_S1: Virtex-II/II-Pro, Spartan-3 16kx1 Single-Port RAM
+ // Xilinx HDL Language Template version 6.3.1i
+
+ RAMB16_S1 character_rom_lo (
+ .DO(pixel_lo), // 1-bit Data Output
+ .ADDR(addr), // 14-bit Address Input
+ .CLK(clk), // Clock
+ .DI(1'b0), // 1-bit Data Input
+ .EN(pixclk), // RAM Enable Input
+ .SSR(1'b0), // Synchronous Set/Reset Input
+ .WE(1'b0) // Write Enable Input
+ );
+
+ // The following defparam declarations are only necessary if you wish to change the default behavior
+ // of the RAM. If the instance name is changed, these defparams need to be updated accordingly.
+
+ defparam character_rom_lo.INIT = 1'h0; // Value of output RAM registers at startup
+ defparam character_rom_lo.SRVAL = 1'h0; // Ouput value upon SSR assertion
+ defparam character_rom_lo.WRITE_MODE = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+
+ // The following defparam INIT_xx declarations are only necessary if you wish to change the initial
+ // contents of the RAM to anything other than all zero's.
+
+ defparam character_rom_lo.INIT_00 = 256'h000000007E818199BD8181A5817E000000000000000000000000000000000000;
+ defparam character_rom_lo.INIT_01 = 256'h00000000081C3E7F7F7F7F3600000000000000007EFFFFE7C3FFFFDBFF7E0000;
+ defparam character_rom_lo.INIT_02 = 256'h000000003C1899E7E7E73C3C180000000000000000081C3E7F3E1C0800000000;
+ defparam character_rom_lo.INIT_03 = 256'h000000000000183C3C18000000000000000000003C18187EFFFF7E3C18000000;
+ defparam character_rom_lo.INIT_04 = 256'h00000000003C664242663C0000000000FFFFFFFFFFFFE7C3C3E7FFFFFFFFFFFF;
+ defparam character_rom_lo.INIT_05 = 256'h000000001E333333331E4C5870780000FFFFFFFFFFC399BDBD99C3FFFFFFFFFF;
+ defparam character_rom_lo.INIT_06 = 256'h00000000070F0E0C0C0C0CFCCCFC00000000000018187E183C666666663C0000;
+ defparam character_rom_lo.INIT_07 = 256'h000000001818DB3CE73CDB18180000000000000367E7E6C6C6C6C6FEC6FE0000;
+ defparam character_rom_lo.INIT_08 = 256'h00000000406070787C7F7C7870604000000000000103070F1F7F1F0F07030100;
+ defparam character_rom_lo.INIT_09 = 256'h0000000066660066666666666666000000000000183C7E181818187E3C180000;
+ defparam character_rom_lo.INIT_0A = 256'h0000003E63301C366363361C06633E0000000000D8D8D8D8D8DEDBDBDBFE0000;
+ defparam character_rom_lo.INIT_0B = 256'h0000007E183C7E181818187E3C180000000000007F7F7F7F0000000000000000;
+ defparam character_rom_lo.INIT_0C = 256'h00000000183C7E18181818181818000000000000181818181818187E3C180000;
+ defparam character_rom_lo.INIT_0D = 256'h0000000000000C067F060C000000000000000000000018307F30180000000000;
+ defparam character_rom_lo.INIT_0E = 256'h00000000000014367F361400000000000000000000007F030303030000000000;
+ defparam character_rom_lo.INIT_0F = 256'h0000000000081C1C3E3E7F7F0000000000000000007F7F3E3E1C1C0800000000;
+ defparam character_rom_lo.INIT_10 = 256'h000000001818001818183C3C3C18000000000000000000000000000000000000;
+ defparam character_rom_lo.INIT_11 = 256'h0000000036367F3636367F363600000000000000000000000000002466666600;
+ defparam character_rom_lo.INIT_12 = 256'h000000006163060C183063430000000000000018183E6361603E0343633E1818;
+ defparam character_rom_lo.INIT_13 = 256'h0000000000000000000000060C0C0C00000000006E3333333B6E1C36361C0000;
+ defparam character_rom_lo.INIT_14 = 256'h000000000C18303030303030180C00000000000030180C0C0C0C0C0C18300000;
+ defparam character_rom_lo.INIT_15 = 256'h00000000000018187E18180000000000000000000000663CFF3C660000000000;
+ defparam character_rom_lo.INIT_16 = 256'h00000000000000007F000000000000000000000C181818000000000000000000;
+ defparam character_rom_lo.INIT_17 = 256'h000000000103060C183060400000000000000000181800000000000000000000;
+ defparam character_rom_lo.INIT_18 = 256'h000000007E1818181818181E1C180000000000003E6363676B6B7363633E0000;
+ defparam character_rom_lo.INIT_19 = 256'h000000003E636060603C6060633E0000000000007F6303060C183060633E0000;
+ defparam character_rom_lo.INIT_1A = 256'h000000003E636060703F0303037F000000000000783030307F33363C38300000;
+ defparam character_rom_lo.INIT_1B = 256'h000000000C0C0C0C18306060637F0000000000003E636363633F0303061C0000;
+ defparam character_rom_lo.INIT_1C = 256'h000000001E306060607E6363633E0000000000003E636363633E6363633E0000;
+ defparam character_rom_lo.INIT_1D = 256'h000000000C181800000018180000000000000000001818000000181800000000;
+ defparam character_rom_lo.INIT_1E = 256'h0000000000007F00007F000000000000000000006030180C060C183060000000;
+ defparam character_rom_lo.INIT_1F = 256'h000000001818001818183063633E000000000000060C18306030180C06000000;
+ defparam character_rom_lo.INIT_20 = 256'h00000000636363637F6363361C080000000000003E033B7B7B7B63633E000000;
+ defparam character_rom_lo.INIT_21 = 256'h000000003C66430303030343663C0000000000003F666666663E6666663F0000;
+ defparam character_rom_lo.INIT_22 = 256'h000000007F664606161E1646667F0000000000001F36666666666666361F0000;
+ defparam character_rom_lo.INIT_23 = 256'h000000005C6663637B030343663C0000000000000F060606161E1646667F0000;
+ defparam character_rom_lo.INIT_24 = 256'h000000003C18181818181818183C00000000000063636363637F636363630000;
+ defparam character_rom_lo.INIT_25 = 256'h00000000676666361E1E363666670000000000001E3333333030303030780000;
+ defparam character_rom_lo.INIT_26 = 256'h0000000063636363636B7F7F77630000000000007F66460606060606060F0000;
+ defparam character_rom_lo.INIT_27 = 256'h000000001C36636363636363361C00000000000063636363737B7F6F67630000;
+ defparam character_rom_lo.INIT_28 = 256'h000070303E7B6B6363636363633E0000000000000F060606063E6666663F0000;
+ defparam character_rom_lo.INIT_29 = 256'h000000003E636360301C0663633E00000000000067666666363E6666663F0000;
+ defparam character_rom_lo.INIT_2A = 256'h000000003E6363636363636363630000000000003C1818181818185A7E7E0000;
+ defparam character_rom_lo.INIT_2B = 256'h0000000036367F6B6B6363636363000000000000081C36636363636363630000;
+ defparam character_rom_lo.INIT_2C = 256'h000000003C181818183C66666666000000000000636336361C1C363663630000;
+ defparam character_rom_lo.INIT_2D = 256'h000000003C0C0C0C0C0C0C0C0C3C0000000000007F6343060C183061637F0000;
+ defparam character_rom_lo.INIT_2E = 256'h000000003C30303030303030303C000000000000406070381C0E070301000000;
+ defparam character_rom_lo.INIT_2F = 256'h0000FF0000000000000000000000000000000000000000000000000063361C08;
+ defparam character_rom_lo.INIT_30 = 256'h000000006E3333333E301E000000000000000000000000000000000000180C0C;
+ defparam character_rom_lo.INIT_31 = 256'h000000003E63030303633E0000000000000000003B66666666361E0606070000;
+ defparam character_rom_lo.INIT_32 = 256'h000000003E6303037F633E0000000000000000006E33333333363C3030380000;
+ defparam character_rom_lo.INIT_33 = 256'h001E33303E33333333336E0000000000000000000F060606060F0626361C0000;
+ defparam character_rom_lo.INIT_34 = 256'h000000003C18181818181C00181800000000000067666666666E360606070000;
+ defparam character_rom_lo.INIT_35 = 256'h000000006766361E1E36660606070000003C6666606060606060700060600000;
+ defparam character_rom_lo.INIT_36 = 256'h000000006B6B6B6B6B7F370000000000000000003C18181818181818181C0000;
+ defparam character_rom_lo.INIT_37 = 256'h000000003E63636363633E0000000000000000006666666666663B0000000000;
+ defparam character_rom_lo.INIT_38 = 256'h007830303E33333333336E0000000000000F06063E66666666663B0000000000;
+ defparam character_rom_lo.INIT_39 = 256'h000000003E63301C06633E0000000000000000000F060606466E3B0000000000;
+ defparam character_rom_lo.INIT_3A = 256'h000000006E333333333333000000000000000000386C0C0C0C0C3F0C0C080000;
+ defparam character_rom_lo.INIT_3B = 256'h00000000367F6B6B636363000000000000000000183C66666666660000000000;
+ defparam character_rom_lo.INIT_3C = 256'h001F30607E63636363636300000000000000000063361C1C1C36630000000000;
+ defparam character_rom_lo.INIT_3D = 256'h0000000070181818180E181818700000000000007F63060C18337F0000000000;
+ defparam character_rom_lo.INIT_3E = 256'h000000000E18181818701818180E000000000000181818181800181818180000;
+ defparam character_rom_lo.INIT_3F = 256'h00000000007F636363361C08000000000000000000000000000000003B6E0000;
+
+ // RAMB16_S1: Virtex-II/II-Pro, Spartan-3 16kx1 Single-Port RAM
+ // Xilinx HDL Language Template version 6.3.1i
+
+ RAMB16_S1 character_rom_hi (
+ .DO(pixel_hi), // 1-bit Data Output
+ .ADDR(addr), // 14-bit Address Input
+ .CLK(clk), // Clock
+ .DI(1'b0), // 1-bit Data Input
+ .EN(pixclk), // RAM Enable Input
+ .SSR(1'b0), // Synchronous Set/Reset Input
+ .WE(1'b0) // Write Enable Input
+ );
+
+ // The following defparam declarations are only necessary if you wish to change the default behavior
+ // of the RAM. If the instance name is changed, these defparams need to be updated accordingly.
+
+ defparam character_rom_hi.INIT = 1'h0; // Value of output RAM registers at startup
+ defparam character_rom_hi.SRVAL = 1'h0; // Ouput value upon SSR assertion
+ defparam character_rom_hi.WRITE_MODE = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
+
+ // The following defparam INIT_xx declarations are only necessary if you wish to change the initial
+ // contents of the RAM to anything other than all zero's.
+
+ defparam character_rom_hi.INIT_00 = 256'h000000006E333333333333003333000000003E60303C664303030343663C0000;
+ defparam character_rom_hi.INIT_01 = 256'h000000006E3333333E301E00361C0800000000003E6303037F633E000C183000;
+ defparam character_rom_hi.INIT_02 = 256'h000000006E3333333E301E00180C0600000000006E3333333E301E0033330000;
+ defparam character_rom_hi.INIT_03 = 256'h0000003C60303C660606663C00000000000000006E3333333E301E001C361C00;
+ defparam character_rom_hi.INIT_04 = 256'h000000003E6303037F633E0063630000000000003E6303037F633E00361C0800;
+ defparam character_rom_hi.INIT_05 = 256'h000000003C18181818181C0066660000000000003E6303037F633E00180C0600;
+ defparam character_rom_hi.INIT_06 = 256'h000000003C18181818181C00180C0600000000003C18181818181C00663C1800;
+ defparam character_rom_hi.INIT_07 = 256'h000000006363637F6363361C001C361C000000006363637F6363361C08636300;
+ defparam character_rom_hi.INIT_08 = 256'h00000000761B1B7E6C6E330000000000000000007F6606063E06667F00060C18;
+ defparam character_rom_hi.INIT_09 = 256'h000000003E63636363633E00361C08000000000073333333337F3333367C0000;
+ defparam character_rom_hi.INIT_0A = 256'h000000003E63636363633E00180C0600000000003E63636363633E0063630000;
+ defparam character_rom_hi.INIT_0B = 256'h000000006E33333333333300180C0600000000006E33333333333300331E0C00;
+ defparam character_rom_hi.INIT_0C = 256'h000000001C3663636363361C00636300001E30607E6363636363630063630000;
+ defparam character_rom_hi.INIT_0D = 256'h0000000018183C66060606663C181800000000003E6363636363636300636300;
+ defparam character_rom_hi.INIT_0E = 256'h000000001818187E187E183C66660000000000003F67060606060F0626361C00;
+ defparam character_rom_hi.INIT_0F = 256'h00000E1B18181818187E181818D8700000000000633333337B33231F33331F00;
+ defparam character_rom_hi.INIT_10 = 256'h000000003C18181818181C000C183000000000006E3333333E301E00060C1800;
+ defparam character_rom_hi.INIT_11 = 256'h000000006E33333333333300060C1800000000003E63636363633E00060C1800;
+ defparam character_rom_hi.INIT_12 = 256'h00000000636363737B7F6F6763003B6E000000006666666666663B003B6E0000;
+ defparam character_rom_hi.INIT_13 = 256'h0000000000000000003E001C36361C000000000000000000007E007C36363C00;
+ defparam character_rom_hi.INIT_14 = 256'h0000000000030303037F000000000000000000003E636303060C0C000C0C0000;
+ defparam character_rom_hi.INIT_15 = 256'h0000F83060C973060C183363430303000000000000606060607F000000000000;
+ defparam character_rom_hi.INIT_16 = 256'h00000000183C3C3C18181800181800000000F060FC5973660C18336343030300;
+ defparam character_rom_hi.INIT_17 = 256'h0000000000003366CC66330000000000000000000000CC663366CC0000000000;
+ defparam character_rom_hi.INIT_18 = 256'h55AA55AA55AA55AA55AA55AA55AA55AA22882288228822882288228822882288;
+ defparam character_rom_hi.INIT_19 = 256'h18181818181818181818181818181818EEBBEEBBEEBBEEBBEEBBEEBBEEBBEEBB;
+ defparam character_rom_hi.INIT_1A = 256'h18181818181818181F181F181818181818181818181818181F18181818181818;
+ defparam character_rom_hi.INIT_1B = 256'h6C6C6C6C6C6C6C6C7F000000000000006C6C6C6C6C6C6C6C6F6C6C6C6C6C6C6C;
+ defparam character_rom_hi.INIT_1C = 256'h6C6C6C6C6C6C6C6C6F606F6C6C6C6C6C18181818181818181F181F0000000000;
+ defparam character_rom_hi.INIT_1D = 256'h6C6C6C6C6C6C6C6C6F607F00000000006C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C;
+ defparam character_rom_hi.INIT_1E = 256'h00000000000000007F6C6C6C6C6C6C6C00000000000000007F606F6C6C6C6C6C;
+ defparam character_rom_hi.INIT_1F = 256'h18181818181818181F0000000000000000000000000000001F181F1818181818;
+ defparam character_rom_hi.INIT_20 = 256'h0000000000000000FF181818181818180000000000000000F818181818181818;
+ defparam character_rom_hi.INIT_21 = 256'h1818181818181818F8181818181818181818181818181818FF00000000000000;
+ defparam character_rom_hi.INIT_22 = 256'h1818181818181818FF181818181818180000000000000000FF00000000000000;
+ defparam character_rom_hi.INIT_23 = 256'h6C6C6C6C6C6C6C6CEC6C6C6C6C6C6C6C1818181818181818F818F81818181818;
+ defparam character_rom_hi.INIT_24 = 256'h6C6C6C6C6C6C6C6CEC0CFC00000000000000000000000000FC0CEC6C6C6C6C6C;
+ defparam character_rom_hi.INIT_25 = 256'h6C6C6C6C6C6C6C6CEF00FF00000000000000000000000000FF00EF6C6C6C6C6C;
+ defparam character_rom_hi.INIT_26 = 256'h0000000000000000FF00FF00000000006C6C6C6C6C6C6C6CEC0CEC6C6C6C6C6C;
+ defparam character_rom_hi.INIT_27 = 256'h0000000000000000FF00FF18181818186C6C6C6C6C6C6C6CEF00EF6C6C6C6C6C;
+ defparam character_rom_hi.INIT_28 = 256'h1818181818181818FF00FF00000000000000000000000000FF6C6C6C6C6C6C6C;
+ defparam character_rom_hi.INIT_29 = 256'h0000000000000000FC6C6C6C6C6C6C6C6C6C6C6C6C6C6C6CFF00000000000000;
+ defparam character_rom_hi.INIT_2A = 256'h1818181818181818F818F800000000000000000000000000F818F81818181818;
+ defparam character_rom_hi.INIT_2B = 256'h6C6C6C6C6C6C6C6CFF6C6C6C6C6C6C6C6C6C6C6C6C6C6C6CFC00000000000000;
+ defparam character_rom_hi.INIT_2C = 256'h00000000000000001F181818181818181818181818181818FF18FF1818181818;
+ defparam character_rom_hi.INIT_2D = 256'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1818181818181818F800000000000000;
+ defparam character_rom_hi.INIT_2E = 256'h0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0FFFFFFFFFFFFFFFFFFF00000000000000;
+ defparam character_rom_hi.INIT_2F = 256'h000000000000000000FFFFFFFFFFFFFFF0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0;
+ defparam character_rom_hi.INIT_30 = 256'h00000303033F63633F633F0000000000000000006E3B1B1B1B3B6E0000000000;
+ defparam character_rom_hi.INIT_31 = 256'h000000003636363636367F0100000000000000000303030303030363637F0000;
+ defparam character_rom_hi.INIT_32 = 256'h000000000E1B1B1B1B1B7E0000000000000000007F63060C180C06637F000000;
+ defparam character_rom_hi.INIT_33 = 256'h000000001818181818183B6E000000000000000306063E666666666600000000;
+ defparam character_rom_hi.INIT_34 = 256'h000000001C3663637F6363361C000000000000007E183C6666663C187E000000;
+ defparam character_rom_hi.INIT_35 = 256'h000000003C666666667C30180C780000000000007736363636636363361C0000;
+ defparam character_rom_hi.INIT_36 = 256'h0000000003067ECFDBF37E60C00000000000000000007EDBDBDB7E0000000000;
+ defparam character_rom_hi.INIT_37 = 256'h0000000063636363636363633E00000000000000380C0606063E06060C380000;
+ defparam character_rom_hi.INIT_38 = 256'h00000000FF000018187E18180000000000000000007F00007F00007F00000000;
+ defparam character_rom_hi.INIT_39 = 256'h000000007E0030180C060C1830000000000000007E000C18306030180C000000;
+ defparam character_rom_hi.INIT_3A = 256'h000000000E1B1B1B18181818181818181818181818181818181818D8D8700000;
+ defparam character_rom_hi.INIT_3B = 256'h0000000000003B6E003B6E000000000000000000001818007E00181800000000;
+ defparam character_rom_hi.INIT_3C = 256'h0000000000000018180000000000000000000000000000000000001C36361C00;
+ defparam character_rom_hi.INIT_3D = 256'h00000000383C3636373030303030F00000000000000000180000000000000000;
+ defparam character_rom_hi.INIT_3E = 256'h0000000000000000001F13060C190E0000000000000000000036363636361B00;
+ defparam character_rom_hi.INIT_3F = 256'h0000000000000000000000000000000000000000003E3E3E3E3E3E3E00000000;
+
+ always @(posedge clk) begin
+ if (pixclk == 1) begin
+ attcode_out[7:0] <= attcode_in[7:0];
+ blank_out <= blank_in;
+ hsync_out <= hsync_in;
+ vsync_out <= vsync_in;
+ blink_out <= blink_in;
+ mux_ctrl <= chrcode[7];
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/dsp/dsp.v
===================================================================
--- trunk/fpga/src/dsp/dsp.v (nonexistent)
+++ trunk/fpga/src/dsp/dsp.v (revision 27)
@@ -0,0 +1,57 @@
+module dsp(clk, reset,
+ addr, en, wr, wt,
+ data_in, data_out,
+ hsync, vsync,
+ r, g, b);
+
+ input clk;
+ input reset;
+ input [13:2] addr;
+ input en;
+ input wr;
+ output wt;
+ input [15:0] data_in;
+ output [15:0] data_out;
+ output hsync;
+ output vsync;
+ output [2:0] r;
+ output [2:0] g;
+ output [2:0] b;
+
+ reg state;
+
+ display display1 (.clk(clk),
+ .dsp_row(addr[13:9]),
+ .dsp_col(addr[8:2]),
+ .dsp_en(en),
+ .dsp_wr(wr),
+ .dsp_wr_data(data_in[15:0]),
+ .dsp_rd_data(data_out[15:0]),
+ .hsync(hsync),
+ .vsync(vsync),
+ .r(r[2:0]),
+ .g(g[2:0]),
+ .b(b[2:0]));
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ state <= 1'b0;
+ end else begin
+ case (state)
+ 1'b0:
+ begin
+ if (en == 1 && wr == 0) begin
+ state <= 1'b1;
+ end
+ end
+ 1'b1:
+ begin
+ state <= 1'b0;
+ end
+ endcase
+ end
+ end
+
+ assign wt = (en == 1 && wr == 0 && state == 1'b0) ? 1 : 0;
+
+endmodule
Index: trunk/fpga/src/dsp/timing.v
===================================================================
--- trunk/fpga/src/dsp/timing.v (nonexistent)
+++ trunk/fpga/src/dsp/timing.v (revision 27)
@@ -0,0 +1,93 @@
+module timing(clk, pixclk,
+ txtrow, txtcol,
+ chrrow, chrcol,
+ blank, hsync, vsync, blink);
+ input clk;
+ output pixclk;
+ output [4:0] txtrow;
+ output [6:0] txtcol;
+ output [3:0] chrrow;
+ output [2:0] chrcol;
+ output blank;
+ output hsync;
+ output vsync;
+ output reg blink;
+
+ reg pclk;
+ reg [9:0] hcnt;
+ reg hblank, hsynch;
+ reg [9:0] vcnt;
+ reg vblank, vsynch;
+ reg [5:0] bcnt;
+
+ always @(posedge clk) begin
+ pclk <= ~pclk;
+ end
+
+ assign pixclk = pclk;
+
+ always @(posedge clk) begin
+ if (pclk == 1) begin
+ if (hcnt == 10'd799) begin
+ hcnt <= 10'd0;
+ hblank <= 1;
+ end else begin
+ hcnt <= hcnt + 1;
+ end
+ if (hcnt == 10'd639) begin
+ hblank <= 0;
+ end
+ if (hcnt == 10'd655) begin
+ hsynch <= 0;
+ end
+ if (hcnt == 10'd751) begin
+ hsynch <= 1;
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+ if (pclk == 1 && hcnt == 10'd799) begin
+ if (vcnt == 10'd524) begin
+ vcnt <= 10'd0;
+ vblank <= 1;
+ end else begin
+ vcnt <= vcnt + 1;
+ end
+ if (vcnt == 10'd479) begin
+ vblank <= 0;
+ end
+ if (vcnt == 10'd489) begin
+ vsynch <= 0;
+ end
+ if (vcnt == 10'd491) begin
+ vsynch <= 1;
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+ if (pclk == 1 && hcnt == 10'd799 && vcnt == 10'd524) begin
+ if (bcnt == 6'd59) begin
+ bcnt <= 6'd0;
+ blink <= 1;
+ end else begin
+ bcnt <= bcnt + 1;
+ end
+ if (bcnt == 6'd29) begin
+ blink <= 0;
+ end
+ end
+ end
+
+ assign blank = hblank & vblank;
+
+ assign hsync = hsynch;
+ assign vsync = vsynch;
+
+ assign txtrow[4:0] = vcnt[8:4];
+ assign txtcol[6:0] = hcnt[9:3];
+ assign chrrow[3:0] = vcnt[3:0];
+ assign chrcol[2:0] = hcnt[2:0];
+
+endmodule
Index: trunk/fpga/src/cpu/cpu.v
===================================================================
--- trunk/fpga/src/cpu/cpu.v (nonexistent)
+++ trunk/fpga/src/cpu/cpu.v (revision 27)
@@ -0,0 +1,2853 @@
+//
+// cpu.v -- the ECO32 CPU
+//
+
+
+module cpu(clk, reset,
+ bus_en, bus_wr, bus_size, bus_addr,
+ bus_wt, bus_data_in, bus_data_out,
+ irq);
+ input clk; // system clock
+ input reset; // system reset
+ output bus_en; // bus enable
+ output bus_wr; // bus write
+ output [1:0] bus_size; // 00: byte, 01: halfword, 10: word
+ output [31:0] bus_addr; // bus address
+ input bus_wt; // bus wait
+ input [31:0] bus_data_in; // bus data input, for reads
+ output [31:0] bus_data_out; // bus data output, for writes
+ input [15:0] irq; // interrupt requests
+
+ // program counter
+ wire [31:0] pc; // program counter
+ wire pc_we; // pc write enable
+ wire [2:0] pc_src; // pc source selector
+ wire [31:0] pc_next; // value written into pc
+
+ // bus & mmu
+ wire [31:0] mar; // memory address register
+ wire mar_we; // mar write enable
+ wire ma_src; // memory address source selector
+ wire [2:0] mmu_fnc; // mmu function
+ wire [31:0] virt_addr; // virtual address
+ wire [31:0] phys_addr; // physical address
+ wire [31:0] mdor; // memory data out register
+ wire mdor_we; // mdor write enable
+ wire [31:0] mdir; // memory data in register
+ wire mdir_we; // mdir write enable
+ wire mdir_sx; // mdir sign-extend
+
+ // instruction register & decoder
+ wire ir_we; // ir write enable
+ wire [5:0] opcode; // opcode part of ir
+ wire [4:0] reg1; // register 1 part of ir
+ wire [4:0] reg2; // register 2 part of ir
+ wire [4:0] reg3; // register 3 part of ir
+ wire [31:0] sx16; // sign-extended 16-bit immediate
+ wire [31:0] zx16; // zero-extended 16-bit immediate
+ wire [31:0] hi16; // high 16-bit immediate
+ wire [31:0] sx16s2; // sign-extended 16-bit immediate << 2
+ wire [31:0] sx26s2; // sign-extended 26-bit immediate << 2
+
+ // register file
+ wire [4:0] reg_a1; // register address 1
+ wire [31:0] reg_do1; // register data out 1
+ wire [1:0] reg_src2; // register source 2 selector
+ wire [4:0] reg_a2; // register address 2
+ wire [31:0] reg_do2; // register data out 2
+ wire reg_we2; // register write enable 2
+ wire reg_we2_prot; // register write enable 2,
+ // protected against writes with a2 = 0
+ wire [2:0] reg_di2_src; // register data in 2 source selector
+ wire [31:0] reg_di2; // register data in 2
+
+ // alu, shift, and muldiv units
+ wire alu_src1; // alu source 1 selector
+ wire [31:0] alu_op1; // alu operand 1
+ wire [2:0] alu_src2; // alu source 2 selector
+ wire [31:0] alu_op2; // alu operand 2
+ wire [2:0] alu_fnc; // alu function
+ wire [31:0] alu_res; // alu result
+ wire alu_equ; // alu operand 1 = operand 2
+ wire alu_ult; // alu operand 1 < operand 2 (unsigned)
+ wire alu_slt; // alu operand 1 < operand 2 (signed)
+ wire [1:0] shift_fnc; // shift function
+ wire [31:0] shift_res; // shift result
+ wire [2:0] muldiv_fnc; // muldiv function
+ wire muldiv_start; // muldiv should start
+ wire muldiv_done; // muldiv has finished
+ wire muldiv_error; // muldiv detected division by zero
+ wire [31:0] muldiv_res; // muldiv result
+
+ // special registers
+ wire [1:0] sreg_num; // special register number
+ wire sreg_we; // special register write enable
+ wire [31:0] sreg_di; // special register data in
+ wire [31:0] sreg_do; // special register data out
+ wire [31:0] psw; // special register 0 (psw) contents
+ wire psw_we; // psw write enable
+ wire [31:0] psw_new; // new psw contents
+ wire [31:0] tlb_index; // special register 1 (tlb index) contents
+ wire tlb_index_we; // tlb index write enable
+ wire [31:0] tlb_index_new; // new tlb index contents
+ wire [31:0] tlb_entry_hi; // special register 2 (tlb entry hi) contents
+ wire tlb_entry_hi_we; // tlb entry hi write enable
+ wire [31:0] tlb_entry_hi_new; // new tlb entry hi contents
+ wire [31:0] tlb_entry_lo; // special register 3 (tlb entry lo) contents
+ wire tlb_entry_lo_we; // tlb entry lo write enable
+ wire [31:0] tlb_entry_lo_new; // new tlb entry lo contents
+
+ // mmu & tlb
+ wire tlb_kmissed; // page not found in tlb, MSB of addr is 1
+ wire tlb_umissed; // page not found in tlb, MSB of addr is 0
+ wire tlb_invalid; // tlb entry is invalid
+ wire tlb_wrtprot; // frame is write-protected
+
+ //------------------------------------------------------------
+
+ // program counter
+ assign pc_next = (pc_src == 3'b000) ? alu_res :
+ (pc_src == 3'b001) ? 32'hE0000000 :
+ (pc_src == 3'b010) ? 32'hE0000004 :
+ (pc_src == 3'b011) ? 32'hC0000004 :
+ (pc_src == 3'b100) ? 32'hE0000008 :
+ (pc_src == 3'b101) ? 32'hC0000008 :
+ 32'hxxxxxxxx;
+ pc pc1(clk, pc_we, pc_next, pc);
+
+ // bus & mmu
+ mar mar1(clk, mar_we, alu_res, mar);
+ assign virt_addr = (ma_src == 0) ? pc : mar;
+ mmu mmu1(clk, reset, mmu_fnc, virt_addr, phys_addr,
+ tlb_index, tlb_index_new,
+ tlb_entry_hi, tlb_entry_hi_new,
+ tlb_entry_lo, tlb_entry_lo_new,
+ tlb_kmissed, tlb_umissed,
+ tlb_invalid, tlb_wrtprot);
+ assign bus_addr = phys_addr;
+ mdor mdor1(clk, mdor_we, reg_do2, mdor);
+ assign bus_data_out = mdor;
+ mdir mdir1(clk, mdir_we, bus_data_in, bus_size, mdir_sx, mdir);
+
+ // instruction register & decoder
+ ir ir1(clk,
+ ir_we, bus_data_in,
+ opcode, reg1, reg2, reg3,
+ sx16, zx16, hi16, sx16s2, sx26s2);
+
+ // register file
+ assign reg_a1 = reg1;
+ assign reg_a2 = (reg_src2 == 2'b00) ? reg2 :
+ (reg_src2 == 2'b01) ? reg3 :
+ (reg_src2 == 2'b10) ? 5'b11111 :
+ (reg_src2 == 2'b11) ? 5'b11110 :
+ 5'bxxxxx;
+ assign reg_we2_prot = reg_we2 & (| reg_a2[4:0]);
+ assign reg_di2 = (reg_di2_src == 3'b000) ? alu_res :
+ (reg_di2_src == 3'b001) ? shift_res :
+ (reg_di2_src == 3'b010) ? muldiv_res :
+ (reg_di2_src == 3'b011) ? mdir :
+ (reg_di2_src == 3'b100) ? sreg_do :
+ 32'hxxxxxxxx;
+ regs regs1(clk,
+ reg_a1, reg_do1,
+ reg_a2, reg_do2, reg_we2_prot, reg_di2);
+
+ // alu, shift, and muldiv units
+ assign alu_op1 = (alu_src1 == 0) ? pc : reg_do1;
+ assign alu_op2 = (alu_src2 == 3'b000) ? 32'h00000004 :
+ (alu_src2 == 3'b001) ? reg_do2 :
+ (alu_src2 == 3'b010) ? sx16 :
+ (alu_src2 == 3'b011) ? zx16 :
+ (alu_src2 == 3'b100) ? hi16 :
+ (alu_src2 == 3'b101) ? sx16s2 :
+ (alu_src2 == 3'b110) ? sx26s2 :
+ 32'hxxxxxxxx;
+ alu alu1(alu_op1, alu_op2, alu_fnc,
+ alu_res, alu_equ, alu_ult, alu_slt);
+ shift shift1(clk, alu_op1, alu_op2[4:0], shift_fnc, shift_res);
+ muldiv muldiv1(clk, alu_op1, alu_op2, muldiv_fnc, muldiv_start,
+ muldiv_done, muldiv_error, muldiv_res);
+
+ // special registers
+ assign sreg_num = zx16[1:0];
+ assign sreg_di = reg_do2;
+ sregs sregs1(clk, reset,
+ sreg_num, sreg_we, sreg_di, sreg_do,
+ psw, psw_we, psw_new,
+ tlb_index, tlb_index_we, tlb_index_new,
+ tlb_entry_hi, tlb_entry_hi_we, tlb_entry_hi_new,
+ tlb_entry_lo, tlb_entry_lo_we, tlb_entry_lo_new);
+
+ // ctrl
+ ctrl ctrl1(clk, reset,
+ opcode, alu_equ, alu_ult, alu_slt,
+ bus_wt, bus_en, bus_wr, bus_size,
+ pc_src, pc_we,
+ mar_we, ma_src, mmu_fnc,
+ mdor_we, mdir_we, mdir_sx, ir_we,
+ reg_src2, reg_di2_src, reg_we2,
+ alu_src1, alu_src2, alu_fnc, shift_fnc,
+ muldiv_fnc, muldiv_start,
+ muldiv_done, muldiv_error,
+ sreg_we, irq, psw, psw_we, psw_new,
+ virt_addr[31], virt_addr[1], virt_addr[0],
+ tlb_kmissed, tlb_umissed, tlb_invalid, tlb_wrtprot,
+ tlb_index_we, tlb_entry_hi_we, tlb_entry_lo_we);
+
+endmodule
+
+
+//--------------------------------------------------------------
+// ctrl -- the finite state machine within the CPU
+//--------------------------------------------------------------
+
+
+module ctrl(clk, reset,
+ opcode, alu_equ, alu_ult, alu_slt,
+ bus_wt, bus_en, bus_wr, bus_size,
+ pc_src, pc_we,
+ mar_we, ma_src, mmu_fnc,
+ mdor_we, mdir_we, mdir_sx, ir_we,
+ reg_src2, reg_di2_src, reg_we2,
+ alu_src1, alu_src2, alu_fnc, shift_fnc,
+ muldiv_fnc, muldiv_start,
+ muldiv_done, muldiv_error,
+ sreg_we, irq, psw, psw_we, psw_new,
+ va_31, va_1, va_0,
+ tlb_kmissed, tlb_umissed, tlb_invalid, tlb_wrtprot,
+ tlb_index_we, tlb_entry_hi_we, tlb_entry_lo_we);
+ input clk;
+ input reset;
+ input [5:0] opcode;
+ input alu_equ;
+ input alu_ult;
+ input alu_slt;
+ input bus_wt;
+ output reg bus_en;
+ output reg bus_wr;
+ output reg [1:0] bus_size;
+ output reg [2:0] pc_src;
+ output reg pc_we;
+ output reg mar_we;
+ output reg ma_src;
+ output reg [2:0] mmu_fnc;
+ output reg mdor_we;
+ output reg mdir_we;
+ output reg mdir_sx;
+ output reg ir_we;
+ output reg [1:0] reg_src2;
+ output reg [2:0] reg_di2_src;
+ output reg reg_we2;
+ output reg alu_src1;
+ output reg [2:0] alu_src2;
+ output reg [2:0] alu_fnc;
+ output reg [1:0] shift_fnc;
+ output reg [2:0] muldiv_fnc;
+ output reg muldiv_start;
+ input muldiv_done;
+ input muldiv_error;
+ output reg sreg_we;
+ input [15:0] irq;
+ input [31:0] psw;
+ output reg psw_we;
+ output reg [31:0] psw_new;
+ input va_31, va_1, va_0;
+ input tlb_kmissed;
+ input tlb_umissed;
+ input tlb_invalid;
+ input tlb_wrtprot;
+ output reg tlb_index_we;
+ output reg tlb_entry_hi_we;
+ output reg tlb_entry_lo_we;
+
+ wire type_rrr; // instr type is RRR
+ wire type_rrs; // instr type is RRS
+ wire type_rrh; // instr type is RRH
+ wire type_rhh; // instr type is RHH
+ wire type_rrb; // instr type is RRB
+ wire type_j; // instr type is J
+ wire type_jr; // instr type is JR
+ wire type_link; // instr saves PC+4 in $31
+ wire type_ld; // instr loads data
+ wire type_st; // instr stores data
+ wire type_ldst; // instr loads or stores data
+ wire [1:0] ldst_size; // load/store transfer size
+ wire type_shift; // instr uses the shift unit
+ wire type_muldiv; // instr uses the muldiv unit
+ wire type_fast; // instr is not shift or muldiv
+ wire type_mvfs; // instr is mvfs
+ wire type_mvts; // instr is mvts
+ wire type_rfx; // instr is rfx
+ wire type_trap; // instr is trap
+ wire type_tb; // instr is a TLB instr
+ reg [4:0] state; // cpu internal state
+ // 0: reset
+ // 1: fetch instr (addr xlat)
+ // 2: decode instr
+ // increment pc by 4
+ // possibly store pc+4 in $31
+ // 3: execute RRR-type instr
+ // 4: execute RRS-type instr
+ // 5: execute RRH-type instr
+ // 6: execute RHH-type instr
+ // 7: execute RRB-type instr (1)
+ // 8: execute RRB-type instr (2)
+ // 9: execute J-type instr
+ // 10: execute JR-type instr
+ // 11: execute LDST-type instr (1)
+ // 12: execute LD-type instr (addr xlat)
+ // 13: execute LD-type instr (3)
+ // 14: execute ST-type instr (addr xlat)
+ // 15: interrupt
+ // 16: extra state for RRR shift instr
+ // 17: extra state for RRH shift instr
+ // 18: extra state for RRR muldiv instr
+ // 19: extra state for RRS muldiv instr
+ // 20: extra state for RRH muldiv instr
+ // 21: execute mvfs instr
+ // 22: execute mvts instr
+ // 23: execute rfx instr
+ // 24: irq_trigger check for mvts and rfx
+ // 25: exception (locus is PC-4)
+ // 26: exception (locus is PC)
+ // 27: execute TLB instr
+ // 28: fetch instr (bus cycle)
+ // 29: execute LD-type instr (bus cycle)
+ // 30: execute ST-type instr (bus cycle)
+ // all other: unused
+ reg branch; // take the branch iff true
+ wire [15:0] irq_pending; // the vector of pending unmasked irqs
+ wire irq_trigger; // true iff any pending irq is present
+ // and interrupts are globally enabled
+ reg [3:0] irq_priority; // highest priority of pending interrupts
+ reg [3:0] exc_priority; // exception, when entering state 25 or 26
+ reg [7:0] bus_count; // counter to detect bus timeout
+ wire bus_timeout; // bus timeout detected
+ wire exc_prv_addr; // privileged address exception detected
+ wire exc_ill_addr; // illegal address exception detected
+ wire exc_tlb_but_wrtprot; // any tlb exception but write protection
+ wire exc_tlb_any; // any tlb exception
+
+ //------------------------------------------------------------
+
+ // decode instr type
+ assign type_rrr = ((opcode == 6'h00) ||
+ (opcode == 6'h02) ||
+ (opcode == 6'h04) ||
+ (opcode == 6'h06) ||
+ (opcode == 6'h08) ||
+ (opcode == 6'h0A) ||
+ (opcode == 6'h0C) ||
+ (opcode == 6'h0E) ||
+ (opcode == 6'h10) ||
+ (opcode == 6'h12) ||
+ (opcode == 6'h14) ||
+ (opcode == 6'h16) ||
+ (opcode == 6'h18) ||
+ (opcode == 6'h1A) ||
+ (opcode == 6'h1C)) ? 1 : 0;
+ assign type_rrs = ((opcode == 6'h01) ||
+ (opcode == 6'h03) ||
+ (opcode == 6'h05) ||
+ (opcode == 6'h09) ||
+ (opcode == 6'h0D)) ? 1 : 0;
+ assign type_rrh = ((opcode == 6'h07) ||
+ (opcode == 6'h0B) ||
+ (opcode == 6'h0F) ||
+ (opcode == 6'h11) ||
+ (opcode == 6'h13) ||
+ (opcode == 6'h15) ||
+ (opcode == 6'h17) ||
+ (opcode == 6'h19) ||
+ (opcode == 6'h1B) ||
+ (opcode == 6'h1D)) ? 1 : 0;
+ assign type_rhh = (opcode == 6'h1F) ? 1 : 0;
+ assign type_rrb = ((opcode == 6'h20) ||
+ (opcode == 6'h21) ||
+ (opcode == 6'h22) ||
+ (opcode == 6'h23) ||
+ (opcode == 6'h24) ||
+ (opcode == 6'h25) ||
+ (opcode == 6'h26) ||
+ (opcode == 6'h27) ||
+ (opcode == 6'h28) ||
+ (opcode == 6'h29)) ? 1 : 0;
+ assign type_j = ((opcode == 6'h2A) ||
+ (opcode == 6'h2C)) ? 1 : 0;
+ assign type_jr = ((opcode == 6'h2B) ||
+ (opcode == 6'h2D)) ? 1 : 0;
+ assign type_link = ((opcode == 6'h2C) ||
+ (opcode == 6'h2D)) ? 1 : 0;
+ assign type_ld = ((opcode == 6'h30) ||
+ (opcode == 6'h31) ||
+ (opcode == 6'h32) ||
+ (opcode == 6'h33) ||
+ (opcode == 6'h34)) ? 1 : 0;
+ assign type_st = ((opcode == 6'h35) ||
+ (opcode == 6'h36) ||
+ (opcode == 6'h37)) ? 1 : 0;
+ assign type_ldst = type_ld | type_st;
+ assign ldst_size = ((opcode == 6'h30) ||
+ (opcode == 6'h35)) ? 2'b10 :
+ ((opcode == 6'h31) ||
+ (opcode == 6'h32) ||
+ (opcode == 6'h36)) ? 2'b01 :
+ ((opcode == 6'h33) ||
+ (opcode == 6'h34) ||
+ (opcode == 6'h37)) ? 2'b00 :
+ 2'bxx;
+ assign type_shift = ((opcode == 6'h18) ||
+ (opcode == 6'h19) ||
+ (opcode == 6'h1A) ||
+ (opcode == 6'h1B) ||
+ (opcode == 6'h1C) ||
+ (opcode == 6'h1D)) ? 1 : 0;
+ assign type_muldiv = ((opcode == 6'h04) ||
+ (opcode == 6'h05) ||
+ (opcode == 6'h06) ||
+ (opcode == 6'h07) ||
+ (opcode == 6'h08) ||
+ (opcode == 6'h09) ||
+ (opcode == 6'h0A) ||
+ (opcode == 6'h0B) ||
+ (opcode == 6'h0C) ||
+ (opcode == 6'h0D) ||
+ (opcode == 6'h0E) ||
+ (opcode == 6'h0F)) ? 1 : 0;
+ assign type_fast = ~(type_shift | type_muldiv);
+ assign type_mvfs = (opcode == 6'h38) ? 1 : 0;
+ assign type_mvts = (opcode == 6'h39) ? 1 : 0;
+ assign type_rfx = (opcode == 6'h2F) ? 1 : 0;
+ assign type_trap = (opcode == 6'h2E) ? 1 : 0;
+ assign type_tb = ((opcode == 6'h3A) ||
+ (opcode == 6'h3B) ||
+ (opcode == 6'h3C) ||
+ (opcode == 6'h3D)) ? 1 : 0;
+
+ // state machine
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ state <= 0;
+ end else begin
+ case (state)
+ 5'd0: // reset
+ begin
+ state <= 5'd1;
+ end
+ 5'd1: // fetch instr (addr xlat)
+ begin
+ if (exc_prv_addr) begin
+ state <= 26;
+ exc_priority <= 4'd9;
+ end else
+ if (exc_ill_addr) begin
+ state <= 26;
+ exc_priority <= 4'd8;
+ end else begin
+ state <= 5'd28;
+ end
+ end
+ 5'd2: // decode instr
+ // increment pc by 4
+ // possibly store pc+4 in $31
+ begin
+ if (type_rrr) begin
+ // RRR-type instruction
+ state <= 5'd3;
+ end else
+ if (type_rrs) begin
+ // RRS-type instruction
+ state <= 5'd4;
+ end else
+ if (type_rrh) begin
+ // RRH-type instruction
+ state <= 5'd5;
+ end else
+ if (type_rhh) begin
+ // RHH-type instruction
+ state <= 5'd6;
+ end else
+ if (type_rrb) begin
+ // RRB-type instr
+ state <= 5'd7;
+ end else
+ if (type_j) begin
+ // J-type instr
+ state <= 5'd9;
+ end else
+ if (type_jr) begin
+ // JR-type instr
+ state <= 5'd10;
+ end else
+ if (type_ldst) begin
+ // LDST-type instr
+ state <= 5'd11;
+ end else
+ if (type_mvfs) begin
+ // mvfs instr
+ state <= 5'd21;
+ end else
+ if (type_mvts) begin
+ // mvts instr
+ if (psw[26] == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd2;
+ end else begin
+ state <= 5'd22;
+ end
+ end else
+ if (type_rfx) begin
+ // rfx instr
+ if (psw[26] == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd2;
+ end else begin
+ state <= 5'd23;
+ end
+ end else
+ if (type_trap) begin
+ // trap instr
+ state <= 5'd25;
+ exc_priority <= 4'd4;
+ end else
+ if (type_tb) begin
+ // TLB instr
+ if (psw[26] == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd2;
+ end else begin
+ state <= 5'd27;
+ end
+ end else begin
+ // illegal instruction
+ state <= 5'd25;
+ exc_priority <= 4'd1;
+ end
+ end
+ 5'd3: // execute RRR-type instr
+ begin
+ if (type_muldiv) begin
+ state <= 5'd18;
+ end else
+ if (type_shift) begin
+ state <= 5'd16;
+ end else begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ end
+ 5'd4: // execute RRS-type instr
+ begin
+ if (type_muldiv) begin
+ state <= 5'd19;
+ end else begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ end
+ 5'd5: // execute RRH-type instr
+ begin
+ if (type_muldiv) begin
+ state <= 5'd20;
+ end else
+ if (type_shift) begin
+ state <= 5'd17;
+ end else begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ end
+ 5'd6: // execute RHH-type instr
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd7: // execute RRB-type instr (1)
+ begin
+ if (branch) begin
+ state <= 5'd8;
+ end else begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ end
+ 5'd8: // execute RRB-type instr (2)
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd9: // execute J-type instr
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd10: // execute JR-type instr
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd11: // execute LDST-type instr (1)
+ begin
+ if (type_ld) begin
+ state <= 5'd12;
+ end else begin
+ state <= 5'd14;
+ end
+ end
+ 5'd12: // execute LD-type instr (addr xlat)
+ begin
+ if (exc_prv_addr) begin
+ state <= 25;
+ exc_priority <= 4'd9;
+ end else
+ if (exc_ill_addr) begin
+ state <= 25;
+ exc_priority <= 4'd8;
+ end else begin
+ state <= 5'd29;
+ end
+ end
+ 5'd13: // execute LD-type instr (3)
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd14: // execute ST-type instr (addr xlat)
+ begin
+ if (exc_prv_addr) begin
+ state <= 25;
+ exc_priority <= 4'd9;
+ end else
+ if (exc_ill_addr) begin
+ state <= 25;
+ exc_priority <= 4'd8;
+ end else begin
+ state <= 5'd30;
+ end
+ end
+ 5'd15: // interrupt
+ begin
+ state <= 5'd1;
+ end
+ 5'd16: // extra state for RRR shift instr
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd17: // extra state for RRH shift instr
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd18: // extra state for RRR muldiv instr
+ begin
+ if (muldiv_done) begin
+ if (muldiv_error) begin
+ state <= 5'd25;
+ exc_priority <= 4'd3;
+ end else
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end else begin
+ state <= 5'd18;
+ end
+ end
+ 5'd19: // extra state for RRS muldiv instr
+ begin
+ if (muldiv_done) begin
+ if (muldiv_error) begin
+ state <= 5'd25;
+ exc_priority <= 4'd3;
+ end else
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end else begin
+ state <= 5'd19;
+ end
+ end
+ 5'd20: // extra state for RRH muldiv instr
+ begin
+ if (muldiv_done) begin
+ if (muldiv_error) begin
+ state <= 5'd25;
+ exc_priority <= 4'd3;
+ end else
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end else begin
+ state <= 5'd20;
+ end
+ end
+ 5'd21: // execute mvfs instr
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd22: // execute mvts instr
+ begin
+ state <= 5'd24;
+ end
+ 5'd23: // execute rfx instr
+ begin
+ state <= 5'd24;
+ end
+ 5'd24: // irq_trigger check for mvts and rfx
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd25: // exception (locus is PC-4)
+ begin
+ state <= 5'd1;
+ end
+ 5'd26: // exception (locus is PC)
+ begin
+ state <= 5'd1;
+ end
+ 5'd27: // execute TLB instr
+ begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ 5'd28: // fetch instr (bus cycle)
+ begin
+ if (tlb_kmissed == 1 || tlb_umissed == 1) begin
+ state <= 5'd26;
+ exc_priority <= 4'd5;
+ end else
+ if (tlb_invalid == 1) begin
+ state <= 5'd26;
+ exc_priority <= 4'd7;
+ end else
+ if (bus_wt == 1) begin
+ if (bus_timeout == 1) begin
+ state <= 5'd26;
+ exc_priority <= 4'd0;
+ end else begin
+ state <= 5'd28;
+ end
+ end else begin
+ state <= 5'd2;
+ end
+ end
+ 5'd29: // execute LD-type instr (bus cycle)
+ begin
+ if (tlb_kmissed == 1 || tlb_umissed == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd5;
+ end else
+ if (tlb_invalid == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd7;
+ end else
+ if (bus_wt == 1) begin
+ if (bus_timeout == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd0;
+ end else begin
+ state <= 5'd29;
+ end
+ end else begin
+ state <= 5'd13;
+ end
+ end
+ 5'd30: // execute ST-type instr (bus cycle)
+ begin
+ if (tlb_kmissed == 1 || tlb_umissed == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd5;
+ end else
+ if (tlb_invalid == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd7;
+ end else
+ if (tlb_wrtprot == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd6;
+ end else
+ if (bus_wt == 1) begin
+ if (bus_timeout == 1) begin
+ state <= 5'd25;
+ exc_priority <= 4'd0;
+ end else begin
+ state <= 5'd30;
+ end
+ end else begin
+ if (irq_trigger) begin
+ state <= 5'd15;
+ end else begin
+ state <= 5'd1;
+ end
+ end
+ end
+ default: // all other states: unused
+ begin
+ state <= 5'd0;
+ end
+ endcase
+ end
+ end
+
+ // bus timeout detector
+ assign bus_timeout = (bus_count == 8'h00) ? 1 : 0;
+ always @(posedge clk) begin
+ if (bus_en == 1 && bus_wt == 1) begin
+ // bus is waiting
+ bus_count <= bus_count - 1;
+ end else begin
+ // bus is not waiting
+ bus_count <= 8'hFF;
+ end
+ end
+
+ // output logic
+ always @(*) begin
+ case (state)
+ 5'd0: // reset
+ begin
+ pc_src = 3'b001;
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd1: // fetch instr (addr xlat)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'b0;
+ mmu_fnc = (exc_prv_addr | exc_ill_addr) ? 3'b000 : 3'b001;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'b10; // enable illegal address detection
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd2: // decode instr
+ // increment pc by 4
+ // possibly store pc+4 in $31
+ begin
+ pc_src = 3'b000;
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = (type_link == 1) ? 2'b10 :
+ (type_rfx == 1) ? 2'b11 :
+ 2'b00;
+ reg_di2_src = (type_link == 1) ? 3'b000 : 3'bxxx;
+ reg_we2 = (type_link == 1) ? 1'b1 : 1'b0;
+ alu_src1 = 1'b0;
+ alu_src2 = 3'b000;
+ alu_fnc = 3'b000;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd3: // execute RRR-type instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b01;
+ reg_di2_src = 3'b000;
+ reg_we2 = type_fast;
+ alu_src1 = 1'b1;
+ alu_src2 = 3'b001;
+ alu_fnc = { opcode[4], opcode[2], opcode[1] };
+ shift_fnc = { opcode[2], opcode[1] };
+ muldiv_fnc = { opcode[3], opcode[2], opcode[1] };
+ muldiv_start = type_muldiv;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd4: // execute RRS-type instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b000;
+ reg_we2 = type_fast;
+ alu_src1 = 1'b1;
+ alu_src2 = 3'b010;
+ alu_fnc = { opcode[4], opcode[2], opcode[1] };
+ shift_fnc = 2'bxx;
+ muldiv_fnc = { opcode[3], opcode[2], opcode[1] };
+ muldiv_start = type_muldiv;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd5: // execute RRH-type instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b000;
+ reg_we2 = type_fast;
+ alu_src1 = 1'b1;
+ alu_src2 = 3'b011;
+ alu_fnc = { opcode[4], opcode[2], opcode[1] };
+ shift_fnc = { opcode[2], opcode[1] };
+ muldiv_fnc = { opcode[3], opcode[2], opcode[1] };
+ muldiv_start = type_muldiv;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd6: // execute RHH-type instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b000;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'b100;
+ alu_fnc = 3'b011;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd7: // execute RRB-type instr (1)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'b1;
+ alu_src2 = 3'b001;
+ alu_fnc = 3'b001;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd8: // execute RRB-type instr (2)
+ begin
+ pc_src = 3'b000;
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'b0;
+ alu_src2 = 3'b101;
+ alu_fnc = 3'b000;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd9: // execute J-type instr
+ begin
+ pc_src = 3'b000;
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'b0;
+ alu_src2 = 3'b110;
+ alu_fnc = 3'b000;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd10: // execute JR-type instr
+ begin
+ pc_src = 3'b000;
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'b1;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'b010;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd11: // execute LDST-type instr (1)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b1;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b1;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'b1;
+ alu_src2 = 3'b010;
+ alu_fnc = 3'b000;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd12: // execute LD-type instr (addr xlat)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'b1;
+ mmu_fnc = (exc_prv_addr | exc_ill_addr) ? 3'b000 : 3'b001;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = ldst_size; // enable illegal address detection
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd13: // execute LD-type instr (3)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = ldst_size;
+ mdir_we = 1'b0;
+ mdir_sx = opcode[0];
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b011;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd14: // execute ST-type instr (addr xlat)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'b1;
+ mmu_fnc = (exc_prv_addr | exc_ill_addr) ? 3'b000 : 3'b001;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = ldst_size; // enable illegal address detection
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd15: // interrupt
+ begin
+ pc_src = (psw[27] == 0) ? 3'b010 : 3'b011;
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b11;
+ reg_di2_src = 3'b000;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'b0;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'b010;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b1;
+ psw_new = {
+ 4'b0000,
+ psw[27],
+ 1'b0, psw[26], psw[25],
+ 1'b0, psw[23], psw[22],
+ 1'b0, irq_priority,
+ psw[15:0]
+ };
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd16: // extra state for RRR shift instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b01;
+ reg_di2_src = 3'b001;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd17: // extra state for RRH shift instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b001;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd18: // extra state for RRR muldiv instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b01;
+ reg_di2_src = 3'b010;
+ reg_we2 = muldiv_done & ~muldiv_error;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd19: // extra state for RRS muldiv instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b010;
+ reg_we2 = muldiv_done & ~muldiv_error;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd20: // extra state for RRH muldiv instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b010;
+ reg_we2 = muldiv_done & ~muldiv_error;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd21: // execute mvfs instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b00;
+ reg_di2_src = 3'b100;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd22: // execute mvts instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b1;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd23: // execute rfx instr
+ begin
+ pc_src = 3'b000;
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'b001;
+ alu_fnc = 3'b011;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b1;
+ psw_new = {
+ 4'b0000,
+ psw[27],
+ psw[25], psw[24], psw[24],
+ psw[22], psw[21], psw[21],
+ psw[20:16],
+ psw[15:0]
+ };
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd24: // irq_trigger check for mvts and rfx
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd25: // exception (locus is PC-4)
+ begin
+ pc_src = (psw[27] != 0) ?
+ ((tlb_umissed != 0) ? 3'b101 : 3'b011) :
+ ((tlb_umissed != 0) ? 3'b100 : 3'b010);
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b11;
+ reg_di2_src = 3'b000;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'b0;
+ alu_src2 = 3'b000;
+ alu_fnc = 3'b001;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b1;
+ psw_new = {
+ 4'b0000,
+ psw[27],
+ 1'b0, psw[26], psw[25],
+ 1'b0, psw[23], psw[22],
+ 1'b1, exc_priority,
+ psw[15:0]
+ };
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd26: // exception (locus is PC)
+ begin
+ pc_src = (psw[27] != 0) ?
+ ((tlb_umissed != 0) ? 3'b101 : 3'b011) :
+ ((tlb_umissed != 0) ? 3'b100 : 3'b010);
+ pc_we = 1'b1;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'b11;
+ reg_di2_src = 3'b000;
+ reg_we2 = 1'b1;
+ alu_src1 = 1'b0;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'b010;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b1;
+ psw_new = {
+ 4'b0000,
+ psw[27],
+ 1'b0, psw[26], psw[25],
+ 1'b0, psw[23], psw[22],
+ 1'b1, exc_priority,
+ psw[15:0]
+ };
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = 1'b0;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd27: // execute TLB instr
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = opcode[2:0];
+ mdor_we = 1'b0;
+ bus_en = 1'b0;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = (opcode[2:0] == 3'b010) ? 1 : 0;
+ tlb_entry_hi_we = (opcode[2:0] == 3'b100) ? 1 : 0;
+ tlb_entry_lo_we = (opcode[2:0] == 3'b100) ? 1 : 0;
+ end
+ 5'd28: // fetch instr (bus cycle)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = ~exc_tlb_but_wrtprot;
+ bus_wr = 1'b0;
+ bus_size = 2'b10;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b1;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = exc_tlb_but_wrtprot;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd29: // execute LD-type instr (bus cycle)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = ~exc_tlb_but_wrtprot;
+ bus_wr = 1'b0;
+ bus_size = ldst_size;
+ mdir_we = 1'b1;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = exc_tlb_but_wrtprot;
+ tlb_entry_lo_we = 1'b0;
+ end
+ 5'd30: // execute ST-type instr (bus cycle)
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'b0;
+ mar_we = 1'b0;
+ ma_src = 1'bx;
+ mmu_fnc = 3'b000;
+ mdor_we = 1'b0;
+ bus_en = ~exc_tlb_any;
+ bus_wr = 1'b1;
+ bus_size = ldst_size;
+ mdir_we = 1'b0;
+ mdir_sx = 1'bx;
+ ir_we = 1'b0;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'b0;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'b0;
+ sreg_we = 1'b0;
+ psw_we = 1'b0;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'b0;
+ tlb_entry_hi_we = exc_tlb_any;
+ tlb_entry_lo_we = 1'b0;
+ end
+ default: // all other states: unused
+ begin
+ pc_src = 3'bxxx;
+ pc_we = 1'bx;
+ mar_we = 1'bx;
+ ma_src = 1'bx;
+ mmu_fnc = 3'bxxx;
+ mdor_we = 1'bx;
+ bus_en = 1'bx;
+ bus_wr = 1'bx;
+ bus_size = 2'bxx;
+ mdir_we = 1'bx;
+ mdir_sx = 1'bx;
+ ir_we = 1'bx;
+ reg_src2 = 2'bxx;
+ reg_di2_src = 3'bxxx;
+ reg_we2 = 1'bx;
+ alu_src1 = 1'bx;
+ alu_src2 = 3'bxxx;
+ alu_fnc = 3'bxxx;
+ shift_fnc = 2'bxx;
+ muldiv_fnc = 3'bxxx;
+ muldiv_start = 1'bx;
+ sreg_we = 1'bx;
+ psw_we = 1'bx;
+ psw_new = 32'hxxxxxxxx;
+ tlb_index_we = 1'bx;
+ tlb_entry_hi_we = 1'bx;
+ tlb_entry_lo_we = 1'bx;
+ end
+ endcase
+ end
+
+ // branch logic
+ always @(*) begin
+ casex ( { opcode[3:0], alu_equ, alu_ult, alu_slt } )
+ // eq
+ 7'b00000xx: branch = 0;
+ 7'b00001xx: branch = 1;
+ // ne
+ 7'b00010xx: branch = 1;
+ 7'b00011xx: branch = 0;
+ // le
+ 7'b00100x0: branch = 0;
+ 7'b00101xx: branch = 1;
+ 7'b0010xx1: branch = 1;
+ // leu
+ 7'b001100x: branch = 0;
+ 7'b00111xx: branch = 1;
+ 7'b0011x1x: branch = 1;
+ // lt
+ 7'b0100xx0: branch = 0;
+ 7'b0100xx1: branch = 1;
+ // ltu
+ 7'b0101x0x: branch = 0;
+ 7'b0101x1x: branch = 1;
+ // ge
+ 7'b0110xx0: branch = 1;
+ 7'b0110xx1: branch = 0;
+ // geu
+ 7'b0111x0x: branch = 1;
+ 7'b0111x1x: branch = 0;
+ // gt
+ 7'b10000x0: branch = 1;
+ 7'b10001xx: branch = 0;
+ 7'b1000xx1: branch = 0;
+ // gtu
+ 7'b100100x: branch = 1;
+ 7'b10011xx: branch = 0;
+ 7'b1001x1x: branch = 0;
+ // other
+ default: branch = 1'bx;
+ endcase
+ end
+
+ // interrupts
+ assign irq_pending = irq[15:0] & psw[15:0];
+ assign irq_trigger = (| irq_pending) & psw[23];
+ always @(*) begin
+ if ((| irq_pending[15:8]) != 0) begin
+ if ((| irq_pending[15:12]) != 0) begin
+ if ((| irq_pending[15:14]) != 0) begin
+ if (irq_pending[15] != 0) begin
+ irq_priority = 4'd15;
+ end else begin
+ irq_priority = 4'd14;
+ end
+ end else begin
+ if (irq_pending[13] != 0) begin
+ irq_priority = 4'd13;
+ end else begin
+ irq_priority = 4'd12;
+ end
+ end
+ end else begin
+ if ((| irq_pending[11:10]) != 0) begin
+ if (irq_pending[11] != 0) begin
+ irq_priority = 4'd11;
+ end else begin
+ irq_priority = 4'd10;
+ end
+ end else begin
+ if (irq_pending[9] != 0) begin
+ irq_priority = 4'd9;
+ end else begin
+ irq_priority = 4'd8;
+ end
+ end
+ end
+ end else begin
+ if ((| irq_pending[7:4]) != 0) begin
+ if ((| irq_pending[7:6]) != 0) begin
+ if (irq_pending[7] != 0) begin
+ irq_priority = 4'd7;
+ end else begin
+ irq_priority = 4'd6;
+ end
+ end else begin
+ if (irq_pending[5] != 0) begin
+ irq_priority = 4'd5;
+ end else begin
+ irq_priority = 4'd4;
+ end
+ end
+ end else begin
+ if ((| irq_pending[3:2]) != 0) begin
+ if (irq_pending[3] != 0) begin
+ irq_priority = 4'd3;
+ end else begin
+ irq_priority = 4'd2;
+ end
+ end else begin
+ if (irq_pending[1] != 0) begin
+ irq_priority = 4'd1;
+ end else begin
+ irq_priority = 4'd0;
+ end
+ end
+ end
+ end
+ end
+
+ // exceptions
+ assign exc_prv_addr = psw[26] & va_31;
+ assign exc_ill_addr = (bus_size[0] & va_0) |
+ (bus_size[1] & va_0) |
+ (bus_size[1] & va_1);
+ assign exc_tlb_but_wrtprot = tlb_kmissed | tlb_umissed | tlb_invalid;
+ assign exc_tlb_any = exc_tlb_but_wrtprot | tlb_wrtprot;
+
+endmodule
+
+
+//--------------------------------------------------------------
+// pc -- the program counter
+//--------------------------------------------------------------
+
+
+module pc(clk, pc_we, pc_next, pc);
+ input clk;
+ input pc_we;
+ input [31:0] pc_next;
+ output reg [31:0] pc;
+
+ always @(posedge clk) begin
+ if (pc_we == 1) begin
+ pc <= pc_next;
+ end
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// mar -- the memory address register
+//--------------------------------------------------------------
+
+
+module mar(clk, mar_we, mar_next, mar);
+ input clk;
+ input mar_we;
+ input [31:0] mar_next;
+ output reg [31:0] mar;
+
+ always @(posedge clk) begin
+ if (mar_we == 1) begin
+ mar <= mar_next;
+ end
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// mdor -- the memory data out register
+//--------------------------------------------------------------
+
+
+module mdor(clk, mdor_we, mdor_next, mdor);
+ input clk;
+ input mdor_we;
+ input [31:0] mdor_next;
+ output reg [31:0] mdor;
+
+ always @(posedge clk) begin
+ if (mdor_we == 1) begin
+ mdor <= mdor_next;
+ end
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// mdir -- the memory data in register
+//--------------------------------------------------------------
+
+
+module mdir(clk, mdir_we, mdir_next, size, sx, mdir);
+ input clk;
+ input mdir_we;
+ input [31:0] mdir_next;
+ input [1:0] size;
+ input sx;
+ output reg [31:0] mdir;
+
+ reg [31:0] data;
+
+ always @(posedge clk) begin
+ if (mdir_we == 1) begin
+ data <= mdir_next;
+ end
+ end
+
+ always @(*) begin
+ case ({ size, sx })
+ 3'b000:
+ begin
+ mdir[31:0] = { 24'h000000, data[7:0] };
+ end
+ 3'b001:
+ begin
+ if (data[7] == 1) begin
+ mdir[31:0] = { 24'hFFFFFF, data[7:0] };
+ end else begin
+ mdir[31:0] = { 24'h000000, data[7:0] };
+ end
+ end
+ 3'b010:
+ begin
+ mdir[31:0] = { 16'h0000, data[15:0] };
+ end
+ 3'b011:
+ begin
+ if (data[15] == 1) begin
+ mdir[31:0] = { 16'hFFFF, data[15:0] };
+ end else begin
+ mdir[31:0] = { 16'h0000, data[15:0] };
+ end
+ end
+ default:
+ begin
+ mdir[31:0] = data[31:0];
+ end
+ endcase
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// ir -- the instruction register and decoder
+//--------------------------------------------------------------
+
+
+module ir(clk,
+ ir_we, instr,
+ opcode, reg1, reg2, reg3,
+ sx16, zx16, hi16, sx16s2, sx26s2);
+ input clk;
+ input ir_we;
+ input [31:0] instr;
+ output [5:0] opcode;
+ output [4:0] reg1;
+ output [4:0] reg2;
+ output [4:0] reg3;
+ output [31:0] sx16;
+ output [31:0] zx16;
+ output [31:0] hi16;
+ output [31:0] sx16s2;
+ output [31:0] sx26s2;
+
+ reg [31:0] ir;
+ wire [15:0] copy_sign_16; // 16-bit copy of a 16-bit immediate's sign
+ wire [3:0] copy_sign_26; // 4-bit copy of a 26-bit immediate's sign
+
+ always @(posedge clk) begin
+ if (ir_we) begin
+ ir <= instr;
+ end
+ end
+
+ assign opcode[5:0] = ir[31:26];
+ assign reg1[4:0] = ir[25:21];
+ assign reg2[4:0] = ir[20:16];
+ assign reg3[4:0] = ir[15:11];
+ assign copy_sign_16[15:0] = (ir[15] == 1) ? 16'hFFFF : 16'h0000;
+ assign copy_sign_26[3:0] = (ir[25] == 1) ? 4'hF : 4'h0;
+ assign sx16[31:0] = { copy_sign_16[15:0], ir[15:0] };
+ assign zx16[31:0] = { 16'h0000, ir[15:0] };
+ assign hi16[31:0] = { ir[15:0], 16'h0000 };
+ assign sx16s2[31:0] = { copy_sign_16[13:0], ir[15:0], 2'b00 };
+ assign sx26s2[31:0] = { copy_sign_26[3:0], ir[25:0], 2'b00 };
+
+endmodule
+
+
+//--------------------------------------------------------------
+// regs -- the register file
+//--------------------------------------------------------------
+
+
+module regs(clk,
+ rn1, do1,
+ rn2, do2, we2, di2);
+ input clk;
+ input [4:0] rn1;
+ output reg [31:0] do1;
+ input [4:0] rn2;
+ output reg [31:0] do2;
+ input we2;
+ input [31:0] di2;
+
+ reg [31:0] r[0:31];
+
+ always @(posedge clk) begin
+ do1 <= r[rn1];
+ if (we2 == 0) begin
+ do2 <= r[rn2];
+ end else begin
+ do2 <= di2;
+ r[rn2] <= di2;
+ end
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// alu -- the arithmetic/logic unit
+//--------------------------------------------------------------
+
+
+module alu(a, b, fnc,
+ res, equ, ult, slt);
+ input [31:0] a;
+ input [31:0] b;
+ input [2:0] fnc;
+ output [31:0] res;
+ output equ;
+ output ult;
+ output slt;
+
+ wire [32:0] a1;
+ wire [32:0] b1;
+ reg [32:0] res1;
+
+ assign a1 = { 1'b0, a };
+ assign b1 = { 1'b0, b };
+
+ always @(*) begin
+ case (fnc)
+ 3'b000: res1 = a1 + b1;
+ 3'b001: res1 = a1 - b1;
+ 3'b010: res1 = a1;
+ 3'b011: res1 = b1;
+ 3'b100: res1 = a1 & b1;
+ 3'b101: res1 = a1 | b1;
+ 3'b110: res1 = a1 ^ b1;
+ 3'b111: res1 = a1 ~^ b1;
+ default: res1 = 33'hxxxxxxxx;
+ endcase
+ end
+
+ assign res = res1[31:0];
+ assign equ = ~| res1[31:0];
+ assign ult = res1[32];
+ assign slt = res1[32] ^ a[31] ^ b[31];
+
+endmodule
+
+
+//--------------------------------------------------------------
+// shift -- the shift unit
+//--------------------------------------------------------------
+
+
+module shift(clk, data_in, shamt, fnc, data_out);
+ input clk;
+ input [31:0] data_in;
+ input [4:0] shamt;
+ input [1:0] fnc;
+ output reg [31:0] data_out;
+
+ always @(posedge clk) begin
+ if (fnc == 2'b00) begin
+ // sll
+ data_out <= data_in << shamt;
+ end else
+ if (fnc == 2'b01) begin
+ // slr
+ data_out <= data_in >> shamt;
+ end else
+ if (fnc == 2'b10) begin
+ // sar
+ if (data_in[31] == 1) begin
+ data_out <= ~(32'hFFFFFFFF >> shamt) |
+ (data_in >> shamt);
+ end else begin
+ data_out <= data_in >> shamt;
+ end
+ end else begin
+ data_out <= 32'hxxxxxxxx;
+ end
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// muldiv -- the multiplier/divide unit
+//--------------------------------------------------------------
+
+
+module muldiv(clk, a, b, fnc, start, done, error, res);
+ input clk;
+ input [31:0] a;
+ input [31:0] b;
+ input [2:0] fnc;
+ input start;
+ output reg done;
+ output reg error;
+ output reg [31:0] res;
+
+ // fnc = 000 op = undefined
+ // 001 undefined
+ // 010 mul
+ // 011 mulu
+ // 100 div
+ // 101 divu
+ // 110 rem
+ // 111 remu
+
+ reg div;
+ reg rem;
+ reg [5:0] count;
+ reg a_neg;
+ reg b_neg;
+ reg [31:0] b_abs;
+ reg [64:0] q;
+ wire [64:1] s;
+ wire [64:0] d;
+
+ assign s[64:32] = q[64:32] + { 1'b0, b_abs };
+ assign s[31: 1] = q[31: 1];
+ assign d[64:32] = q[64:32] - { 1'b0, b_abs };
+ assign d[31: 0] = q[31: 0];
+
+ always @(posedge clk) begin
+ if (start == 1) begin
+ if (fnc[2] == 1 && (| b[31:0]) == 0) begin
+ // division by zero
+ done <= 1;
+ error <= 1;
+ end else begin
+ // operands are ok
+ done <= 0;
+ error <= 0;
+ end
+ div <= fnc[2];
+ rem <= fnc[1];
+ count <= 6'd0;
+ if (fnc[0] == 0 && a[31] == 1) begin
+ // negate first operand
+ a_neg <= 1;
+ if (fnc[2] == 0) begin
+ // initialize q for multiplication
+ q[64:32] <= 33'b0;
+ q[31: 0] <= ~a + 1;
+ end else begin
+ // initialize q for division and remainder
+ q[64:33] <= 32'b0;
+ q[32: 1] <= ~a + 1;
+ q[ 0: 0] <= 1'b0;
+ end
+ end else begin
+ // use first operand as is
+ a_neg <= 0;
+ if (fnc[2] == 0) begin
+ // initialize q for multiplication
+ q[64:32] <= 33'b0;
+ q[31: 0] <= a;
+ end else begin
+ // initialize q for division and remainder
+ q[64:33] <= 32'b0;
+ q[32: 1] <= a;
+ q[ 0: 0] <= 1'b0;
+ end
+ end
+ if (fnc[0] == 0 && b[31] == 1) begin
+ // negate second operand
+ b_neg <= 1;
+ b_abs <= ~b + 1;
+ end else begin
+ // use second operand as is
+ b_neg <= 0;
+ b_abs <= b;
+ end
+ end else begin
+ if (done == 0) begin
+ // algorithm not yet finished
+ if (div == 0) begin
+ //
+ // multiplication
+ //
+ if (count == 6'd32) begin
+ // last step
+ done <= 1;
+ if (a_neg == b_neg) begin
+ res <= q[31:0];
+ end else begin
+ res <= ~q[31:0] + 1;
+ end
+ end else begin
+ // all other steps
+ count <= count + 1;
+ if (q[0] == 1) begin
+ q <= { 1'b0, s[64:1] };
+ end else begin
+ q <= { 1'b0, q[64:1] };
+ end
+ end
+ end else begin
+ //
+ // division and remainder
+ //
+ if (count == 6'd32) begin
+ // last step
+ done <= 1;
+ if (rem == 0) begin
+ // result <= quotient
+ if (a_neg == b_neg) begin
+ res <= q[31:0];
+ end else begin
+ res <= ~q[31:0] + 1;
+ end
+ end else begin
+ // result <= remainder
+ if (a_neg == 0) begin
+ res <= q[64:33];
+ end else begin
+ res <= ~q[64:33] + 1;
+ end
+ end
+ end else begin
+ // all other steps
+ count <= count + 1;
+ if (d[64] == 0) begin
+ q <= { d[63:0], 1'b1 };
+ end else begin
+ q <= { q[63:0], 1'b0 };
+ end
+ end
+ end
+ end
+ end
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// sregs -- the special registers
+//--------------------------------------------------------------
+
+
+module sregs(clk, reset,
+ rn, we, di, do,
+ psw, psw_we, psw_new,
+ tlb_index, tlb_index_we, tlb_index_new,
+ tlb_entry_hi, tlb_entry_hi_we, tlb_entry_hi_new,
+ tlb_entry_lo, tlb_entry_lo_we, tlb_entry_lo_new);
+ input clk;
+ input reset;
+ input [1:0] rn;
+ input we;
+ input [31:0] di;
+ output [31:0] do;
+ output [31:0] psw;
+ input psw_we;
+ input [31:0] psw_new;
+ output [31:0] tlb_index;
+ input tlb_index_we;
+ input [31:0] tlb_index_new;
+ output [31:0] tlb_entry_hi;
+ input tlb_entry_hi_we;
+ input [31:0] tlb_entry_hi_new;
+ output [31:0] tlb_entry_lo;
+ input tlb_entry_lo_we;
+ input [31:0] tlb_entry_lo_new;
+
+ // rn = 00 register = PSW
+ // 01 TLB index
+ // 10 TLB entry high
+ // 11 TLB entry low
+
+ reg [31:0] sr[0:3];
+
+ assign do = sr[rn];
+ assign psw = sr[0];
+ assign tlb_index = sr[1];
+ assign tlb_entry_hi = sr[2];
+ assign tlb_entry_lo = sr[3];
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ sr[0] <= 32'h00000000;
+ end else begin
+ if (we == 1) begin
+ sr[rn] <= di;
+ end else begin
+ if (psw_we) begin
+ sr[0] <= psw_new;
+ end
+ if (tlb_index_we) begin
+ sr[1] <= tlb_index_new;
+ end
+ if (tlb_entry_hi_we) begin
+ sr[2] <= tlb_entry_hi_new;
+ end
+ if (tlb_entry_lo_we) begin
+ sr[3] <= tlb_entry_lo_new;
+ end
+ end
+ end
+ end
+
+endmodule
+
+
+//--------------------------------------------------------------
+// mmu -- the memory management unit
+//--------------------------------------------------------------
+
+
+module mmu(clk, reset, fnc, virt, phys,
+ tlb_index, tlb_index_new,
+ tlb_entry_hi, tlb_entry_hi_new,
+ tlb_entry_lo, tlb_entry_lo_new,
+ tlb_kmissed, tlb_umissed,
+ tlb_invalid, tlb_wrtprot);
+ input clk;
+ input reset;
+ input [2:0] fnc;
+ input [31:0] virt;
+ output [31:0] phys;
+ input [31:0] tlb_index;
+ output [31:0] tlb_index_new;
+ input [31:0] tlb_entry_hi;
+ output [31:0] tlb_entry_hi_new;
+ input [31:0] tlb_entry_lo;
+ output [31:0] tlb_entry_lo_new;
+ output tlb_kmissed;
+ output tlb_umissed;
+ output tlb_invalid;
+ output tlb_wrtprot;
+
+ // fnc = 000 no operation, hold output
+ // 001 map virt to phys address
+ // 010 tbs
+ // 011 tbwr
+ // 100 tbri
+ // 101 tbwi
+ // 110 undefined
+ // 111 undefined
+
+ wire map;
+ wire tbs;
+ wire tbwr;
+ wire tbri;
+ wire tbwi;
+ reg [19:0] page;
+ reg [11:0] offset;
+ wire [19:0] tlb_page;
+ wire tlb_miss;
+ wire [4:0] tlb_found;
+ wire tlb_enable;
+ wire [19:0] tlb_frame;
+ wire tlb_wbit;
+ wire tlb_vbit;
+ wire [4:0] rw_index;
+ wire [19:0] r_page;
+ wire [19:0] r_frame;
+ wire w_enable;
+ wire [19:0] w_page;
+ wire [19:0] w_frame;
+ wire direct;
+ wire [17:0] frame;
+ reg [4:0] random_index;
+ reg tlb_miss_delayed;
+
+ // decode function
+ assign map = (fnc == 3'b001) ? 1 : 0;
+ assign tbs = (fnc == 3'b010) ? 1 : 0;
+ assign tbwr = (fnc == 3'b011) ? 1 : 0;
+ assign tbri = (fnc == 3'b100) ? 1 : 0;
+ assign tbwi = (fnc == 3'b101) ? 1 : 0;
+
+ // latch virtual address
+ always @(posedge clk) begin
+ if (map == 1) begin
+ page <= virt[31:12];
+ offset <= virt[11:0];
+ end
+ end
+
+ // create tlb instance
+ assign tlb_page = (tbs == 1) ? tlb_entry_hi[31:12] : virt[31:12];
+ assign tlb_enable = map;
+ assign tlb_wbit = tlb_frame[1];
+ assign tlb_vbit = tlb_frame[0];
+ assign rw_index = (tbwr == 1) ? random_index : tlb_index[4:0];
+ assign tlb_index_new = { tlb_miss, 26'b0, tlb_found };
+ assign tlb_entry_hi_new = { ((tbri == 1) ? r_page : page), 12'h000 };
+ assign tlb_entry_lo_new = { 2'b00, r_frame[19:2], 10'h000, r_frame[1:0] };
+ assign w_enable = tbwr | tbwi;
+ assign w_page = tlb_entry_hi[31:12];
+ assign w_frame = { tlb_entry_lo[29:12], tlb_entry_lo[1:0] };
+ tlb tlb1(tlb_page, tlb_miss, tlb_found,
+ clk, tlb_enable, tlb_frame,
+ rw_index, r_page, r_frame,
+ w_enable, w_page, w_frame);
+
+ // construct physical address
+ assign direct = (page[19:18] == 2'b11) ? 1 : 0;
+ assign frame = (direct == 1) ? page[17:0] : tlb_frame[19:2];
+ assign phys = { 2'b00, frame, offset };
+
+ // generate "random" index
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ // the index register is counting down
+ // so we must start at topmost index
+ random_index <= 5'd31;
+ end else begin
+ // decrement index register "randomly"
+ // (whenever there is a mapping operation)
+ // skip "fixed" entries (0..3)
+ if (map == 1) begin
+ if (random_index == 5'd4) begin
+ random_index <= 5'd31;
+ end else begin
+ random_index <= random_index - 1;
+ end
+ end
+ end
+ end
+
+ // generate TLB exceptions
+ always @(posedge clk) begin
+ if (map == 1) begin
+ tlb_miss_delayed <= tlb_miss;
+ end
+ end
+ assign tlb_kmissed = tlb_miss_delayed & ~direct & page[19];
+ assign tlb_umissed = tlb_miss_delayed & ~direct & ~page[19];
+ assign tlb_invalid = ~tlb_vbit & ~direct;
+ assign tlb_wrtprot = ~tlb_wbit & ~direct;
+
+endmodule
+
+
+//--------------------------------------------------------------
+// tlb -- the translation lookaside buffer
+//--------------------------------------------------------------
+
+
+module tlb(page_in, miss, found,
+ clk, enable, frame_out,
+ rw_index, r_page, r_frame,
+ w_enable, w_page, w_frame);
+ input [19:0] page_in;
+ output miss;
+ output reg [4:0] found;
+ input clk;
+ input enable;
+ output reg [19:0] frame_out;
+ input [4:0] rw_index;
+ output reg [19:0] r_page;
+ output reg [19:0] r_frame;
+ input w_enable;
+ input [19:0] w_page;
+ input [19:0] w_frame;
+
+ reg [19:0] page[0:31];
+ reg [19:0] frame[0:31];
+
+ wire [19:0] p00, p01, p02, p03;
+ wire [19:0] p04, p05, p06, p07;
+ wire [19:0] p08, p09, p10, p11;
+ wire [19:0] p12, p13, p14, p15;
+ wire [19:0] p16, p17, p18, p19;
+ wire [19:0] p20, p21, p22, p23;
+ wire [19:0] p24, p25, p26, p27;
+ wire [19:0] p28, p29, p30, p31;
+ wire [31:0] match;
+
+ assign p00 = page[ 0];
+ assign p01 = page[ 1];
+ assign p02 = page[ 2];
+ assign p03 = page[ 3];
+ assign p04 = page[ 4];
+ assign p05 = page[ 5];
+ assign p06 = page[ 6];
+ assign p07 = page[ 7];
+ assign p08 = page[ 8];
+ assign p09 = page[ 9];
+ assign p10 = page[10];
+ assign p11 = page[11];
+ assign p12 = page[12];
+ assign p13 = page[13];
+ assign p14 = page[14];
+ assign p15 = page[15];
+ assign p16 = page[16];
+ assign p17 = page[17];
+ assign p18 = page[18];
+ assign p19 = page[19];
+ assign p20 = page[20];
+ assign p21 = page[21];
+ assign p22 = page[22];
+ assign p23 = page[23];
+ assign p24 = page[24];
+ assign p25 = page[25];
+ assign p26 = page[26];
+ assign p27 = page[27];
+ assign p28 = page[28];
+ assign p29 = page[29];
+ assign p30 = page[30];
+ assign p31 = page[31];
+
+ assign match[ 0] = (page_in == p00) ? 1 : 0;
+ assign match[ 1] = (page_in == p01) ? 1 : 0;
+ assign match[ 2] = (page_in == p02) ? 1 : 0;
+ assign match[ 3] = (page_in == p03) ? 1 : 0;
+ assign match[ 4] = (page_in == p04) ? 1 : 0;
+ assign match[ 5] = (page_in == p05) ? 1 : 0;
+ assign match[ 6] = (page_in == p06) ? 1 : 0;
+ assign match[ 7] = (page_in == p07) ? 1 : 0;
+ assign match[ 8] = (page_in == p08) ? 1 : 0;
+ assign match[ 9] = (page_in == p09) ? 1 : 0;
+ assign match[10] = (page_in == p10) ? 1 : 0;
+ assign match[11] = (page_in == p11) ? 1 : 0;
+ assign match[12] = (page_in == p12) ? 1 : 0;
+ assign match[13] = (page_in == p13) ? 1 : 0;
+ assign match[14] = (page_in == p14) ? 1 : 0;
+ assign match[15] = (page_in == p15) ? 1 : 0;
+ assign match[16] = (page_in == p16) ? 1 : 0;
+ assign match[17] = (page_in == p17) ? 1 : 0;
+ assign match[18] = (page_in == p18) ? 1 : 0;
+ assign match[19] = (page_in == p19) ? 1 : 0;
+ assign match[20] = (page_in == p20) ? 1 : 0;
+ assign match[21] = (page_in == p21) ? 1 : 0;
+ assign match[22] = (page_in == p22) ? 1 : 0;
+ assign match[23] = (page_in == p23) ? 1 : 0;
+ assign match[24] = (page_in == p24) ? 1 : 0;
+ assign match[25] = (page_in == p25) ? 1 : 0;
+ assign match[26] = (page_in == p26) ? 1 : 0;
+ assign match[27] = (page_in == p27) ? 1 : 0;
+ assign match[28] = (page_in == p28) ? 1 : 0;
+ assign match[29] = (page_in == p29) ? 1 : 0;
+ assign match[30] = (page_in == p30) ? 1 : 0;
+ assign match[31] = (page_in == p31) ? 1 : 0;
+
+ assign miss = ~(| match[31:0]);
+
+ always @(*) begin
+ if ((| match[31:16]) != 0) begin
+ if ((| match[31:24]) != 0) begin
+ if ((| match[31:28]) != 0) begin
+ if ((| match[31:30]) != 0) begin
+ if (match[31] != 0) begin
+ found = 5'd31;
+ end else begin
+ found = 5'd30;
+ end
+ end else begin
+ if (match[29] != 0) begin
+ found = 5'd29;
+ end else begin
+ found = 5'd28;
+ end
+ end
+ end else begin
+ if ((| match[27:26]) != 0) begin
+ if (match[27] != 0) begin
+ found = 5'd27;
+ end else begin
+ found = 5'd26;
+ end
+ end else begin
+ if (match[25] != 0) begin
+ found = 5'd25;
+ end else begin
+ found = 5'd24;
+ end
+ end
+ end
+ end else begin
+ if ((| match[23:20]) != 0) begin
+ if ((| match[23:22]) != 0) begin
+ if (match[23] != 0) begin
+ found = 5'd23;
+ end else begin
+ found = 5'd22;
+ end
+ end else begin
+ if (match[21] != 0) begin
+ found = 5'd21;
+ end else begin
+ found = 5'd20;
+ end
+ end
+ end else begin
+ if ((| match[19:18]) != 0) begin
+ if (match[19] != 0) begin
+ found = 5'd19;
+ end else begin
+ found = 5'd18;
+ end
+ end else begin
+ if (match[17] != 0) begin
+ found = 5'd17;
+ end else begin
+ found = 5'd16;
+ end
+ end
+ end
+ end
+ end else begin
+ if ((| match[15:8]) != 0) begin
+ if ((| match[15:12]) != 0) begin
+ if ((| match[15:14]) != 0) begin
+ if (match[15] != 0) begin
+ found = 5'd15;
+ end else begin
+ found = 5'd14;
+ end
+ end else begin
+ if (match[13] != 0) begin
+ found = 5'd13;
+ end else begin
+ found = 5'd12;
+ end
+ end
+ end else begin
+ if ((| match[11:10]) != 0) begin
+ if (match[11] != 0) begin
+ found = 5'd11;
+ end else begin
+ found = 5'd10;
+ end
+ end else begin
+ if (match[9] != 0) begin
+ found = 5'd9;
+ end else begin
+ found = 5'd8;
+ end
+ end
+ end
+ end else begin
+ if ((| match[7:4]) != 0) begin
+ if ((| match[7:6]) != 0) begin
+ if (match[7] != 0) begin
+ found = 5'd7;
+ end else begin
+ found = 5'd6;
+ end
+ end else begin
+ if (match[5] != 0) begin
+ found = 5'd5;
+ end else begin
+ found = 5'd4;
+ end
+ end
+ end else begin
+ if ((| match[3:2]) != 0) begin
+ if (match[3] != 0) begin
+ found = 5'd3;
+ end else begin
+ found = 5'd2;
+ end
+ end else begin
+ if (match[1] != 0) begin
+ found = 5'd1;
+ end else begin
+ found = 5'd0;
+ end
+ end
+ end
+ end
+ end
+ end
+
+ always @(posedge clk) begin
+ if (enable == 1) begin
+ frame_out <= frame[found];
+ end
+ end
+
+ always @(posedge clk) begin
+ if (w_enable == 1) begin
+ page[rw_index] <= w_page;
+ frame[rw_index] <= w_frame;
+ end else begin
+ r_page <= page[rw_index];
+ r_frame <= frame[rw_index];
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/ser/xmtbuf.v
===================================================================
--- trunk/fpga/src/ser/xmtbuf.v (nonexistent)
+++ trunk/fpga/src/ser/xmtbuf.v (revision 27)
@@ -0,0 +1,70 @@
+module xmtbuf(clk, reset, write, ready, data_in, serial_out);
+ input clk;
+ input reset;
+ input write;
+ output reg ready;
+ input [7:0] data_in;
+ output serial_out;
+
+ reg [1:0] state;
+ reg [7:0] data_hold;
+ reg load;
+ wire empty;
+
+ xmt xmt1(clk, reset, load, empty, data_hold, serial_out);
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ state <= 2'b00;
+ ready <= 1;
+ load <= 0;
+ end else begin
+ case (state)
+ 2'b00:
+ begin
+ if (write == 1) begin
+ state <= 2'b01;
+ data_hold <= data_in;
+ ready <= 0;
+ load <= 1;
+ end
+ end
+ 2'b01:
+ begin
+ state <= 2'b10;
+ ready <= 1;
+ load <= 0;
+ end
+ 2'b10:
+ begin
+ if (empty == 1 && write == 0) begin
+ state <= 2'b00;
+ ready <= 1;
+ load <= 0;
+ end else
+ if (empty == 1 && write == 1) begin
+ state <= 2'b01;
+ data_hold <= data_in;
+ ready <= 0;
+ load <= 1;
+ end else
+ if (empty == 0 && write == 1) begin
+ state <= 2'b11;
+ data_hold <= data_in;
+ ready <= 0;
+ load <= 0;
+ end
+ end
+ 2'b11:
+ begin
+ if (empty == 1) begin
+ state <= 2'b01;
+ ready <= 0;
+ load <= 1;
+ end
+ end
+ endcase
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/ser/rcvbuf.v
===================================================================
--- trunk/fpga/src/ser/rcvbuf.v (nonexistent)
+++ trunk/fpga/src/ser/rcvbuf.v (revision 27)
@@ -0,0 +1,27 @@
+module rcvbuf(clk, reset, read, ready, data_out, serial_in);
+ input clk;
+ input reset;
+ input read;
+ output reg ready;
+ output reg [7:0] data_out;
+ input serial_in;
+
+ wire full;
+ wire [7:0] parallel_out;
+
+ rcv rcv1(clk, reset, full, parallel_out, serial_in);
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ ready <= 0;
+ end else begin
+ if (full == 1) begin
+ data_out <= parallel_out;
+ end
+ if (full == 1 || read == 1) begin
+ ready <= full;
+ end
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/ser/xmt.v
===================================================================
--- trunk/fpga/src/ser/xmt.v (nonexistent)
+++ trunk/fpga/src/ser/xmt.v (revision 27)
@@ -0,0 +1,44 @@
+module xmt(clk, reset, load, empty, parallel_in, serial_out);
+ input clk;
+ input reset;
+ input load;
+ output reg empty;
+ input [7:0] parallel_in;
+ output serial_out;
+
+ reg [3:0] state;
+ reg [8:0] shift;
+ reg [10:0] count;
+
+ assign serial_out = shift[0];
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ state <= 4'h0;
+ shift <= 9'b111111111;
+ empty <= 1;
+ end else begin
+ if (state == 4'h0) begin
+ if (load == 1) begin
+ state <= 4'h1;
+ shift <= { parallel_in, 1'b0 };
+ count <= 1302;
+ empty <= 0;
+ end
+ end else
+ if (state == 4'hb) begin
+ state <= 4'h0;
+ empty <= 1;
+ end else begin
+ if (count == 0) begin
+ state <= state + 1;
+ shift[8:0] <= { 1'b1, shift[8:1] };
+ count <= 1302;
+ end else begin
+ count <= count - 1;
+ end
+ end
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/ser/ser.v
===================================================================
--- trunk/fpga/src/ser/ser.v (nonexistent)
+++ trunk/fpga/src/ser/ser.v (revision 27)
@@ -0,0 +1,75 @@
+module ser(clk, reset,
+ en, wr, addr,
+ data_in, data_out,
+ wt, irq_r, irq_t,
+ rxd, txd);
+ input clk;
+ input reset;
+ input en;
+ input wr;
+ input [3:2] addr;
+ input [7:0] data_in;
+ output reg [7:0] data_out;
+ output wt;
+ output irq_r;
+ output irq_t;
+ input rxd;
+ output txd;
+
+ wire wr_rcv_ctrl;
+ wire rd_rcv_data;
+ wire wr_xmt_ctrl;
+ wire wr_xmt_data;
+
+ wire rcv_ready;
+ reg rcv_ien;
+ wire [7:0] rcv_data;
+ wire xmt_ready;
+ reg xmt_ien;
+
+ assign wr_rcv_ctrl = (en == 1 && wr == 1 && addr == 2'b00) ? 1 : 0;
+ assign rd_rcv_data = (en == 1 && wr == 0 && addr == 2'b01) ? 1 : 0;
+ assign wr_xmt_ctrl = (en == 1 && wr == 1 && addr == 2'b10) ? 1 : 0;
+ assign wr_xmt_data = (en == 1 && wr == 1 && addr == 2'b11) ? 1 : 0;
+
+ rcvbuf rcvbuf1(clk, reset, rd_rcv_data, rcv_ready, rcv_data, rxd);
+ xmtbuf xmtbuf1(clk, reset, wr_xmt_data, xmt_ready, data_in, txd);
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ rcv_ien <= 0;
+ xmt_ien <= 0;
+ end else begin
+ if (wr_rcv_ctrl) begin
+ rcv_ien <= data_in[1];
+ end
+ if (wr_xmt_ctrl) begin
+ xmt_ien <= data_in[1];
+ end
+ end
+ end
+
+ always @(*) begin
+ case (addr[3:2])
+ 2'b00:
+ // rcv ctrl
+ data_out = { 6'b000000, rcv_ien, rcv_ready };
+ 2'b01:
+ // rcv data
+ data_out = rcv_data;
+ 2'b10:
+ // xmt ctrl
+ data_out = { 6'b000000, xmt_ien, xmt_ready };
+ 2'b11:
+ // xmt data (cannot be read)
+ data_out = 8'hxx;
+ default:
+ data_out = 8'hxx;
+ endcase
+ end
+
+ assign wt = 1'b0;
+ assign irq_r = rcv_ien & rcv_ready;
+ assign irq_t = xmt_ien & xmt_ready;
+
+endmodule
Index: trunk/fpga/src/ser/rcv.v
===================================================================
--- trunk/fpga/src/ser/rcv.v (nonexistent)
+++ trunk/fpga/src/ser/rcv.v (revision 27)
@@ -0,0 +1,48 @@
+module rcv(clk, reset, full, parallel_out, serial_in);
+ input clk;
+ input reset;
+ output reg full;
+ output [7:0] parallel_out;
+ input serial_in;
+
+ reg serial_p;
+ reg serial_s;
+ reg [3:0] state;
+ reg [8:0] shift;
+ reg [10:0] count;
+
+ assign parallel_out[7:0] = shift[7:0];
+
+ always @(posedge clk) begin
+ serial_p <= serial_in;
+ serial_s <= serial_p;
+ end
+
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ state <= 4'h0;
+ full <= 0;
+ end else begin
+ if (state == 4'h0) begin
+ full <= 0;
+ if (serial_s == 0) begin
+ state <= 4'h1;
+ count <= 651;
+ end
+ end else
+ if (state == 4'hb) begin
+ state <= 4'h0;
+ full <= 1;
+ end else begin
+ if (count == 0) begin
+ state <= state + 1;
+ shift[8:0] <= { serial_s, shift[8:1] };
+ count <= 1302;
+ end else begin
+ count <= count - 1;
+ end
+ end
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/clk_reset/clk_reset.v
===================================================================
--- trunk/fpga/src/clk_reset/clk_reset.v (nonexistent)
+++ trunk/fpga/src/clk_reset/clk_reset.v (revision 27)
@@ -0,0 +1,87 @@
+module clk_reset(clk_in, reset_inout_n,
+ sdram_clk, sdram_fb,
+ clk, clk_ok, reset);
+ input clk_in;
+ inout reset_inout_n;
+ output sdram_clk;
+ input sdram_fb;
+ output clk;
+ output clk_ok;
+ output reset;
+
+ wire clk_in_buf;
+ wire int_clk;
+ wire int_locked;
+ wire ext_rst_n;
+ wire ext_fb;
+ wire ext_locked;
+
+ reg reset_p_n;
+ reg reset_s_n;
+ reg [23:0] reset_counter;
+ wire reset_counting;
+
+//--------------------------------------------------------------
+
+ IBUFG clk_in_buffer(.I(clk_in), .O(clk_in_buf));
+
+ DCM int_dcm (
+ .CLKIN(clk_in_buf),
+ .CLKFB(clk),
+ .RST(1'b0),
+ .CLK0(int_clk),
+ .LOCKED(int_locked)
+ );
+
+ BUFG int_clk_buffer(.I(int_clk), .O(clk));
+
+//--------------------------------------------------------------
+
+ SRL16 ext_dll_rst_gen(
+ .CLK(clk_in_buf),
+ .D(int_locked),
+ .Q(ext_rst_n),
+ .A0(1'b1),
+ .A1(1'b1),
+ .A2(1'b1),
+ .A3(1'b1)
+ );
+
+ defparam ext_dll_rst_gen.INIT = 16'h0000;
+
+//--------------------------------------------------------------
+
+ IBUFG ext_fb_buffer(.I(sdram_fb), .O(ext_fb));
+
+ DCM ext_dcm (
+ .CLKIN(clk_in_buf),
+ .CLKFB(ext_fb),
+ .RST(~ext_rst_n),
+ .CLK0(sdram_clk),
+ .LOCKED(ext_locked)
+ );
+
+ assign clk_ok = int_locked & ext_locked;
+
+//--------------------------------------------------------------
+
+ assign reset_counting = (reset_counter == 24'hFFFFFF) ? 0 : 1;
+ assign reset_inout_n = (reset_counter[23] == 0) ? 1'b0 : 1'bz;
+
+ always @(posedge clk_in_buf) begin
+ reset_p_n <= reset_inout_n;
+ reset_s_n <= reset_p_n;
+ if (reset_counting == 1) begin
+ reset_counter <= reset_counter + 1;
+ end else begin
+ if (int_locked == 0 ||
+ ext_locked == 0 ||
+ reset_s_n == 0) begin
+ reset_counter <= 24'h000000;
+ end
+ end
+ end
+
+ assign reset = reset_counting;
+
+endmodule
Index: trunk/fpga/src/rom/rom.v
===================================================================
--- trunk/fpga/src/rom/rom.v (nonexistent)
+++ trunk/fpga/src/rom/rom.v (revision 27)
@@ -0,0 +1,108 @@
+module rom(clk, reset,
+ en, wr, size, addr,
+ data_out, wt,
+ ce_n, oe_n, we_n, rst_n, byte_n, a, d);
+ // internal interface signals
+ input clk;
+ input reset;
+ input en;
+ input wr;
+ input [1:0] size;
+ input [20:0] addr;
+ output reg [31:0] data_out;
+ output reg wt;
+ // flash interface signals
+ output ce_n;
+ output oe_n;
+ output we_n;
+ output rst_n;
+ output byte_n;
+ output [19:0] a;
+ input [15:0] d;
+
+ reg [3:0] state;
+ reg a0;
+
+ // the following control signals are all
+ // either constantly asserted or deasserted
+ assign ce_n = 0;
+ assign oe_n = 0;
+ assign we_n = 1;
+ assign rst_n = 1;
+ assign byte_n = 1;
+
+ // the flash ram is organized in 16-bit halfwords
+ // address line a0 is controlled by the state machine
+ // this is necessary for word accesses
+ assign a[19:1] = addr[20:2];
+ assign a[0] = a0;
+
+ // the state machine
+ always @(posedge clk) begin
+ if (reset == 1) begin
+ state <= 0;
+ wt <= 1;
+ end else begin
+ if (state == 0) begin
+ // wait for start of access
+ if (en == 1 && wr == 0) begin
+ state <= 1;
+ if (size[1] == 1) begin
+ // word access
+ a0 <= 0;
+ end else begin
+ // halfword or byte access
+ a0 <= addr[1];
+ end
+ end
+ end else
+ if (state == 6) begin
+ if (size[1] == 1) begin
+ // word access
+ // latch upper halfword
+ data_out[31:24] <= d[7:0];
+ data_out[23:16] <= d[15:8];
+ state <= 7;
+ a0 <= 1;
+ end else begin
+ // halfword or byte access
+ data_out[31:16] <= 16'h0000;
+ if (size[0] == 1) begin
+ // halfword access
+ data_out[15:8] <= d[7:0];
+ data_out[7:0] <= d[15:8];
+ end else begin
+ // byte access
+ data_out[15:8] <= 8'h00;
+ if (addr[0] == 0) begin
+ // even address
+ data_out[7:0] <= d[7:0];
+ end else begin
+ // odd address
+ data_out[7:0] <= d[15:8];
+ end
+ end
+ state <= 13;
+ wt <= 0;
+ end
+ end else
+ if (state == 12) begin
+ // word access (state is only reached in this case)
+ // latch lower halfword
+ data_out[15:8] <= d[7:0];
+ data_out[7:0] <= d[15:8];
+ state <= 13;
+ wt <= 0;
+ end else
+ if (state == 13) begin
+ // end of access
+ wt <= 1;
+ state <= 0;
+ end else begin
+ // wait for flash access time to pass
+ state <= state + 1;
+ end
+ end
+ end
+
+endmodule
Index: trunk/fpga/src/busctrl/busctrl.v
===================================================================
--- trunk/fpga/src/busctrl/busctrl.v (nonexistent)
+++ trunk/fpga/src/busctrl/busctrl.v (revision 27)
@@ -0,0 +1,165 @@
+module busctrl(cpu_en, cpu_wr, cpu_size, cpu_addr, cpu_data_out, cpu_data_in, cpu_wt,
+ ram_en, ram_wr, ram_size, ram_addr, ram_data_in, ram_data_out, ram_wt,
+ rom_en, rom_wr, rom_size, rom_addr, rom_data_out, rom_wt,
+ tmr_en, tmr_wr, tmr_addr2, tmr_data_in, tmr_data_out, tmr_wt,
+ dsp_en, dsp_wr, dsp_addr, dsp_data_in, dsp_data_out, dsp_wt,
+ kbd_en, kbd_wr, kbd_addr2, kbd_data_in, kbd_data_out, kbd_wt,
+ ser0_en, ser0_wr, ser0_addr, ser0_data_in, ser0_data_out, ser0_wt,
+ ser1_en, ser1_wr, ser1_addr, ser1_data_in, ser1_data_out, ser1_wt,
+ dsk_en, dsk_wr, dsk_addr, dsk_data_in, dsk_data_out, dsk_wt);
+ // cpu
+ input cpu_en;
+ input cpu_wr;
+ input [1:0] cpu_size;
+ input [31:0] cpu_addr;
+ input [31:0] cpu_data_out;
+ output [31:0] cpu_data_in;
+ output cpu_wt;
+ // ram
+ output ram_en;
+ output ram_wr;
+ output [1:0] ram_size;
+ output [24:0] ram_addr;
+ output [31:0] ram_data_in;
+ input [31:0] ram_data_out;
+ input ram_wt;
+ // rom
+ output rom_en;
+ output rom_wr;
+ output [1:0] rom_size;
+ output [20:0] rom_addr;
+ input [31:0] rom_data_out;
+ input rom_wt;
+ // tmr
+ output tmr_en;
+ output tmr_wr;
+ output tmr_addr2;
+ output [31:0] tmr_data_in;
+ input [31:0] tmr_data_out;
+ input tmr_wt;
+ // dsp
+ output dsp_en;
+ output dsp_wr;
+ output [13:2] dsp_addr;
+ output [15:0] dsp_data_in;
+ input [15:0] dsp_data_out;
+ input dsp_wt;
+ // kbd
+ output kbd_en;
+ output kbd_wr;
+ output kbd_addr2;
+ output [7:0] kbd_data_in;
+ input [7:0] kbd_data_out;
+ input kbd_wt;
+ // ser0
+ output ser0_en;
+ output ser0_wr;
+ output [3:2] ser0_addr;
+ output [7:0] ser0_data_in;
+ input [7:0] ser0_data_out;
+ input ser0_wt;
+ // ser1
+ output ser1_en;
+ output ser1_wr;
+ output [3:2] ser1_addr;
+ output [7:0] ser1_data_in;
+ input [7:0] ser1_data_out;
+ input ser1_wt;
+ // dsk
+ output dsk_en;
+ output dsk_wr;
+ output [19:2] dsk_addr;
+ output [31:0] dsk_data_in;
+ input [31:0] dsk_data_out;
+ input dsk_wt;
+
+ wire i_o_en;
+
+ // decoder
+ assign ram_en =
+ (cpu_en == 1 && cpu_addr[31:29] == 3'b000
+ && cpu_addr[28:25] == 4'b0000) ? 1 : 0;
+ assign rom_en =
+ (cpu_en == 1 && cpu_addr[31:28] == 4'b0010
+ && cpu_addr[27:21] == 7'b0000000) ? 1 : 0;
+ assign i_o_en =
+ (cpu_en == 1 && cpu_addr[31:28] == 4'b0011) ? 1 : 0;
+ assign tmr_en =
+ (i_o_en == 1 && cpu_addr[27:20] == 8'h00) ? 1 : 0;
+ assign dsp_en =
+ (i_o_en == 1 && cpu_addr[27:20] == 8'h01) ? 1 : 0;
+ assign kbd_en =
+ (i_o_en == 1 && cpu_addr[27:20] == 8'h02) ? 1 : 0;
+ assign ser0_en =
+ (i_o_en == 1 && cpu_addr[27:20] == 8'h03
+ && cpu_addr[ 5: 4] == 2'b00) ? 1 : 0;
+ assign ser1_en =
+ (i_o_en == 1 && cpu_addr[27:20] == 8'h03
+ && cpu_addr[ 5: 4] == 2'b01) ? 1 : 0;
+ assign dsk_en =
+ (i_o_en == 1 && cpu_addr[27:20] == 8'h04) ? 1 : 0;
+
+ // to cpu
+ assign cpu_wt =
+ (ram_en == 1) ? ram_wt :
+ (rom_en == 1) ? rom_wt :
+ (tmr_en == 1) ? tmr_wt :
+ (dsp_en == 1) ? dsp_wt :
+ (kbd_en == 1) ? kbd_wt :
+ (ser0_en == 1) ? ser0_wt :
+ (ser1_en == 1) ? ser1_wt :
+ (dsk_en == 1) ? dsk_wt :
+ 1;
+ assign cpu_data_in[31:0] =
+ (ram_en == 1) ? ram_data_out[31:0] :
+ (rom_en == 1) ? rom_data_out[31:0] :
+ (tmr_en == 1) ? tmr_data_out[31:0] :
+ (dsp_en == 1) ? { 16'h0000, dsp_data_out[15:0] } :
+ (kbd_en == 1) ? { 24'h000000, kbd_data_out[7:0] } :
+ (ser0_en == 1) ? { 24'h000000, ser0_data_out[7:0] } :
+ (ser1_en == 1) ? { 24'h000000, ser1_data_out[7:0] } :
+ (dsk_en == 1) ? dsk_data_out[31:0] :
+ 32'h00000000;
+
+ // to ram
+ assign ram_wr = cpu_wr;
+ assign ram_size[1:0] = cpu_size[1:0];
+ assign ram_addr[24:0] = cpu_addr[24:0];
+ assign ram_data_in[31:0] = cpu_data_out[31:0];
+
+ // to rom
+ assign rom_wr = cpu_wr;
+ assign rom_size[1:0] = cpu_size[1:0];
+ assign rom_addr[20:0] = cpu_addr[20:0];
+
+ // to tmr
+ assign tmr_wr = cpu_wr;
+ assign tmr_addr2 = cpu_addr[2];
+ assign tmr_data_in[31:0] = cpu_data_out[31:0];
+
+ // to dsp
+ assign dsp_wr = cpu_wr;
+ assign dsp_addr[13:2] = cpu_addr[13:2];
+ assign dsp_data_in[15:0] = cpu_data_out[15:0];
+
+ // to kbd
+ assign kbd_wr = cpu_wr;
+ assign kbd_addr2 = cpu_addr[2];
+ assign kbd_data_in[7:0] = cpu_data_out[7:0];
+
+ // to ser0
+ assign ser0_wr = cpu_wr;
+ assign ser0_addr[3:2] = cpu_addr[3:2];
+ assign ser0_data_in[7:0] = cpu_data_out[7:0];
+
+ // to ser1
+ assign ser1_wr = cpu_wr;
+ assign ser1_addr[3:2] = cpu_addr[3:2];
+ assign ser1_data_in[7:0] = cpu_data_out[7:0];
+
+ // to dsk
+ assign dsk_wr = cpu_wr;
+ assign dsk_addr[19:2] = cpu_addr[19:2];
+ assign dsk_data_in[31:0] = cpu_data_out[31:0];
+
+endmodule
Index: trunk/fpga/xsa-xst-3/eco32.ucf
===================================================================
--- trunk/fpga/xsa-xst-3/eco32.ucf (nonexistent)
+++ trunk/fpga/xsa-xst-3/eco32.ucf (revision 27)
@@ -0,0 +1,141 @@
+#PACE: Start of Constraints generated by PACE
+
+#PACE: Start of PACE I/O Pin Assignments
+NET "ata_cs0_n" LOC = "g15" ;
+NET "ata_cs1_n" LOC = "g14" ;
+NET "ata_dmack_n" LOC = "k1" ;
+NET "ata_dmarq" LOC = "l4" ;
+NET "ata_intrq" LOC = "h15" ;
+NET "ata_iordy" LOC = "l2" ;
+NET "b<0>" LOC = "c9" ;
+NET "b<1>" LOC = "e7" ;
+NET "b<2>" LOC = "d5" ;
+NET "clk_in" LOC = "p8" ;
+NET "ether_cs_n" LOC = "g13" ;
+NET "flash_a<0>" LOC = "n5" ;
+NET "flash_a<10>" LOC = "r16" ;
+NET "flash_a<11>" LOC = "p14" ;
+NET "flash_a<12>" LOC = "p13" ;
+NET "flash_a<13>" LOC = "n12" ;
+NET "flash_a<14>" LOC = "t14" ;
+NET "flash_a<15>" LOC = "r13" ;
+NET "flash_a<16>" LOC = "n10" ;
+NET "flash_a<17>" LOC = "m14" ;
+NET "flash_a<18>" LOC = "k3" ;
+NET "flash_a<19>" LOC = "k4" ;
+NET "flash_a<1>" LOC = "k14" ;
+NET "flash_a<2>" LOC = "k13" ;
+NET "flash_a<3>" LOC = "k12" ;
+NET "flash_a<4>" LOC = "l14" ;
+NET "flash_a<5>" LOC = "m16" ;
+NET "flash_a<6>" LOC = "l13" ;
+NET "flash_a<7>" LOC = "n16" ;
+NET "flash_a<8>" LOC = "n14" ;
+NET "flash_a<9>" LOC = "p15" ;
+NET "flash_byte_n" LOC = "t8" ;
+NET "flash_ce_n" LOC = "r4" ;
+NET "flash_d<0>" LOC = "m11" ;
+NET "flash_d<10>" LOC = "t5" ;
+NET "flash_d<11>" LOC = "p6" ;
+NET "flash_d<12>" LOC = "m7" ;
+NET "flash_d<13>" LOC = "r6" ;
+NET "flash_d<14>" LOC = "n7" ;
+NET "flash_d<15>" LOC = "p7" ;
+NET "flash_d<1>" LOC = "n11" ;
+NET "flash_d<2>" LOC = "p10" ;
+NET "flash_d<3>" LOC = "r10" ;
+NET "flash_d<4>" LOC = "t7" ;
+NET "flash_d<5>" LOC = "r7" ;
+NET "flash_d<6>" LOC = "n6" ;
+NET "flash_d<7>" LOC = "m6" ;
+NET "flash_d<8>" LOC = "t4" ;
+NET "flash_d<9>" LOC = "r5" ;
+NET "flash_oe_n" LOC = "p5" ;
+NET "flash_rst_n" LOC = "p16" ;
+NET "flash_we_n" LOC = "m13" ;
+NET "g<0>" LOC = "a8" ;
+NET "g<1>" LOC = "a5" ;
+NET "g<2>" LOC = "c3" ;
+NET "hsync" LOC = "b7" ;
+NET "pbus_a<0>" LOC = "l5" ;
+NET "pbus_a<1>" LOC = "n2" ;
+NET "pbus_a<2>" LOC = "m3" ;
+NET "pbus_a<3>" LOC = "n1" ;
+NET "pbus_a<4>" LOC = "t13" ;
+NET "pbus_d<0>" LOC = "p12" ;
+NET "pbus_d<10>" LOC = "f3" ;
+NET "pbus_d<11>" LOC = "f2" ;
+NET "pbus_d<12>" LOC = "g4" ;
+NET "pbus_d<13>" LOC = "g3" ;
+NET "pbus_d<14>" LOC = "g1" ;
+NET "pbus_d<15>" LOC = "h4" ;
+NET "pbus_d<1>" LOC = "j1" ;
+NET "pbus_d<2>" LOC = "h1" ;
+NET "pbus_d<3>" LOC = "h3" ;
+NET "pbus_d<4>" LOC = "g2" ;
+NET "pbus_d<5>" LOC = "k15" ;
+NET "pbus_d<6>" LOC = "k16" ;
+NET "pbus_d<7>" LOC = "f15" ;
+NET "pbus_d<8>" LOC = "e2" ;
+NET "pbus_d<9>" LOC = "e1" ;
+NET "pbus_read_n" LOC = "p2" ;
+NET "pbus_write_n" LOC = "r1" ;
+NET "ps2_clk" LOC = "b16" ;
+NET "ps2_data" LOC = "e13" ;
+NET "r<0>" LOC = "c8" ;
+NET "r<1>" LOC = "d6" ;
+NET "r<2>" LOC = "b1" ;
+NET "reset_inout_n" LOC = "d15" ;
+NET "rs232_0_rxd" LOC = "g5" ;
+NET "rs232_0_txd" LOC = "j2" ;
+NET "rs232_1_rxd" LOC = "d1" ;
+NET "rs232_1_txd" LOC = "f4" ;
+NET "sdram_a<0>" LOC = "b5" ;
+NET "sdram_a<10>" LOC = "b6" ;
+NET "sdram_a<11>" LOC = "c5" ;
+NET "sdram_a<12>" LOC = "c6" ;
+NET "sdram_a<1>" LOC = "a4" ;
+NET "sdram_a<2>" LOC = "b4" ;
+NET "sdram_a<3>" LOC = "e6" ;
+NET "sdram_a<4>" LOC = "e3" ;
+NET "sdram_a<5>" LOC = "c1" ;
+NET "sdram_a<6>" LOC = "e4" ;
+NET "sdram_a<7>" LOC = "d3" ;
+NET "sdram_a<8>" LOC = "c2" ;
+NET "sdram_a<9>" LOC = "a3" ;
+NET "sdram_ba<0>" LOC = "a7" ;
+NET "sdram_ba<1>" LOC = "c7" ;
+NET "sdram_cas_n" LOC = "a10" ;
+NET "sdram_cke" LOC = "d7" ;
+NET "sdram_clk" LOC = "e10" ;
+NET "sdram_cs_n" LOC = "b8" ;
+NET "sdram_dq<0>" LOC = "c15" ;
+NET "sdram_dq<10>" LOC = "c12" ;
+NET "sdram_dq<11>" LOC = "b14" ;
+NET "sdram_dq<12>" LOC = "d14" ;
+NET "sdram_dq<13>" LOC = "c16" ;
+NET "sdram_dq<14>" LOC = "f12" ;
+NET "sdram_dq<15>" LOC = "f13" ;
+NET "sdram_dq<1>" LOC = "d12" ;
+NET "sdram_dq<2>" LOC = "a14" ;
+NET "sdram_dq<3>" LOC = "b13" ;
+NET "sdram_dq<4>" LOC = "d11" ;
+NET "sdram_dq<5>" LOC = "a12" ;
+NET "sdram_dq<6>" LOC = "c11" ;
+NET "sdram_dq<7>" LOC = "d10" ;
+NET "sdram_dq<8>" LOC = "b11" ;
+NET "sdram_dq<9>" LOC = "b12" ;
+NET "sdram_fb" LOC = "n8" ;
+NET "sdram_ldqm" LOC = "c10" ;
+NET "sdram_ras_n" LOC = "a9" ;
+NET "sdram_udqm" LOC = "d9" ;
+NET "sdram_we_n" LOC = "b10" ;
+NET "slot1_cs_n" LOC = "e15" ;
+NET "slot2_cs_n" LOC = "d16" ;
+NET "vsync" LOC = "d8" ;
+
+#PACE: Start of PACE Area Constraints
+
+#PACE: Start of PACE Prohibit Constraints
+
+#PACE: End of Constraints generated by PACE
Index: trunk/fpga/xsa-xst-3/eco32-29.xise
===================================================================
--- trunk/fpga/xsa-xst-3/eco32-29.xise (nonexistent)
+++ trunk/fpga/xsa-xst-3/eco32-29.xise (revision 27)
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+