OpenCores
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 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.