OpenCores
URL https://opencores.org/ocsvn/openfire2/openfire2/trunk

Subversion Repositories openfire2

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/trunk/rtl/openfire_soc.v
0,0 → 1,344
/* MODULE: openfire soc
DESCRIPTION: Contains top-level SOC
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
`timescale 1ns / 1ps
`include "openfire_define.v"
 
module openfire_soc(
`ifndef SP3SK_USERIO
rst, // if no SP3SK IOs, then we need a reset signal
`endif
`ifdef SP3SK_USERIO
leds, drivers_n, segments_n, pushbuttons, switches,
`endif
`ifdef UART1_ENABLE
tx1, rx1,
`endif
`ifdef UART2_ENABLE
tx2, rx2,
`endif
`ifdef SP3SK_SRAM
ram_addr, ram_oe_n, ram_we_n,
ram1_io, ram1_ce_n, ram1_ub_n, ram1_lb_n,
ram2_io, ram2_ce_n, ram2_ub_n, ram2_lb_n,
`endif
`ifdef SP3SK_VGA
r, g, b, hsync_n, vsync_n,
`endif
`ifdef SP3SK_PROM_DATA
prom_din, prom_cclk, prom_reset_n,
`endif
// tx_ultrasonidos_p, tx_ultrasonidos_n, rx_ultrasonidos,
// spi_clk, spi_datain, spi_dataout,
// spi_cs_1, spi_cs_2, spi_cs_3, spi_cs_4,
// i2c_clk, i2c_data,
clk_50mhz
);
 
`ifndef SP3SK_USERIO
input rst; // external RST (active HIGH)
`endif
input clk_50mhz; // board clock 50 MHZ
`ifdef SP3SK_USERIO
output [7:0] leds; // onboard LEDS
output [3:0] drivers_n; // 7segments element's driver (negated)
output [7:0] segments_n; // display segment
input [3:0] pushbuttons; // 4 push-buttons
input [7:0] switches; // 8 switches
`endif
`ifdef UART1_ENABLE
input rx1; // RS232 rx
output tx1; // RS232 tx
`endif
`ifdef UART2_ENABLE
input rx2; // RS232 rx #2
output tx2; // RS232 tx #2
`endif
`ifdef SP3SK_SRAM
output [17:0] ram_addr; // SRAM ADDR (256K @)
output ram_oe_n; // OE_N shared by 2 IC
output ram_we_n; // WE_N shared by 2 IC
inout [15:0] ram1_io; // I/O data port SRAM1
output ram1_ce_n; // SRAM1 CE_N chip enable
output ram1_ub_n; // UB_N upper byte select
output ram1_lb_n; // LB_N lower byte select
inout [15:0] ram2_io; // I/O data port SRAM2
output ram2_ce_n; // SRAM2 CE_N chip enable
output ram2_ub_n; // UB_N upper byte select
output ram2_lb_n; // LB_N lower byte select
`endif
`ifdef SP3SK_VGA
output r, g, b; // VGA components (1 bit per component)
output hsync_n; // VGA hsync_n
output vsync_n; // VGA vsync_n
`endif
`ifdef SP3SK_PROM_DATA
input prom_din;
output prom_cclk;
output prom_reset_n;
`endif
//output tx_ultrasonidos_p; // application specific ports
//output tx_ultrasonidos_n;
//input rx_ultrasonidos;
//output spi_clk;
//input spi_datain;
//output spi_dataout;
//output spi_cs_1;
//output spi_cs_2;
//output spi_cs_3;
//output spi_cs_4;
//inout i2c_clk;
//inout i2c_data;
 
// -------- connections ------------
`ifdef SP3SK_USERIO
wire rst = pushbuttons[3]; // reset generated from a push button
`endif
wire [31:0] imem_data; // ports to/from CPU
wire [31:0] imem_addr;
wire [31:0] dmem_data2mem;
wire [31:0] dmem_data2cpu;
wire [31:0] dmem_addr;
wire [1:0] dmem_input_sel; // 0=byte, 1=hw, 2=word
wire [3:0] data_selector; // maps each byte in a word (msb..lsb)
wire dmem_we; // request data write
wire dmem_re; // request data read
wire imem_re; // request instruction read
wire [31:0] dmem_data_frombram; // arbitrer to/from BRAM
wire [31:0] dmem_data_tobram;
wire dmem_we_bram;
wire [31:0] imem_data_frombram;
`ifdef SP3SK_IODEVICES
wire [31:0] dmem_data_fromio; // arbitrer to/from IO-SPACE
wire [31:0] dmem_data_toio;
wire dmem_we_io;
wire dmem_re_io;
`endif
`ifdef IO_MULTICYCLE
wire io_done; // handle multicycle i/o operations
`endif
wire imem_done; // operation on imem completed
wire dmem_done; // operation on dmem completed
`ifdef SP3SK_SRAM
wire [31:0] sram_data2mem1;
wire [31:0] sram_data2cpu1;
wire sram_re1, sram_we1, sram_done1;
wire [31:0] sram_data2cpu2;
wire sram_re2, sram_done2;
wire [17:0] sram_addr3; // port #3 other uses
wire [31:0] sram_data2cpu3;
wire sram_re3, sram_done3;
`endif
 
`ifdef CLK_25MHZ // cpu clock generation
reg clk;
//synthesis translate_off
initial clk = 0;
//synthesis translate_on
always @(posedge clk_50mhz) clk <= ~clk; // 25mhz clock
`else
wire clk = clk_50mhz; // 50mhz clock
`endif
 
`ifdef ENABLE_INTERRUPTS
wire interrupt; // interrupt line
`endif
 
`ifdef ENABLE_ALIGNMENT_EXCEPTION
wire dmem_alignment_exception;
`endif
 
// --------- instantiation of the SoC ----------------
openfire_cpu CPU( // openfire CPU
.clock(clk),
.reset(rst),
`ifdef ENABLE_INTERRUPTS
.interrupt(interrupt),
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
.dmem_alignment_exception(dmem_alignment_exception),
`endif
.dmem_addr(dmem_addr),
.dmem_data_in(dmem_data2cpu),
.dmem_data_out(dmem_data2mem),
.dmem_we(dmem_we),
.dmem_re(dmem_re),
.dmem_input_sel(dmem_input_sel),
.dmem_done(dmem_done),
.imem_addr(imem_addr),
.imem_data_in(imem_data),
.imem_re(imem_re),
.imem_done(imem_done)
);
 
openfire_arbitrer ARBITRER( // bus arbitrer
`ifdef SP3SK_SRAM
.sram_data2mem(sram_data2mem1),
.sram_data2cpu(sram_data2cpu1),
.sram_dmem_re(sram_re1),
.sram_dmem_we(sram_we1),
.sram_dmem_done(sram_done1),
.sram_ins2cpu(sram_data2cpu2),
.sram_imem_re(sram_re2),
.sram_imem_done(sram_done2),
`endif
`ifdef IO_MULTICYCLE
.dmem_done_io(io_done),
`endif
`ifdef SP3SK_IODEVICES
.dmem_we_io(dmem_we_io),
.dmem_re_io(dmem_re_io),
.dmem_data_fromio(dmem_data_fromio),
.dmem_data_toio(dmem_data_toio),
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
.dmem_alignment_exception(dmem_alignment_exception),
`endif
.clock(clk),
.reset(rst),
.imem_done(imem_done),
.dmem_done(dmem_done),
.dmem_address(dmem_addr),
.dmem_data_out(dmem_data2cpu),
.dmem_data_in(dmem_data2mem),
.dmem_re(dmem_re),
.dmem_we(dmem_we),
.dmem_input_sel(dmem_input_sel),
.data_selector(data_selector),
.imem_address(imem_addr),
.imem_data(imem_data),
.imem_re(imem_re),
.dmem_data_frombram(dmem_data_frombram),
.dmem_data_tobram(dmem_data_tobram),
.dmem_we_bram(dmem_we_bram),
.imem_data_frombram(imem_data_frombram)
);
 
`ifdef SP3SK_IODEVICES
openfire_iospace IOSPACE( // i/o space manager
`ifdef SP3SK_USERIO
.leds(leds),
.drivers_n(drivers_n),
.segments_n(segments_n),
.pushbuttons(pushbuttons),
.switches(switches),
`endif
`ifdef UART1_ENABLE
.tx1(tx1),
.rx1(rx1),
`endif
`ifdef UART2_ENABLE
.tx2(tx2),
.rx2(rx2),
`endif
`ifdef SP3SK_PROM_DATA
.prom_din(prom_din),
.prom_cclk(prom_cclk),
.prom_reset_n(prom_reset_n),
`endif
`ifdef ENABLE_INTERRUPTS
.interrupt(interrupt),
`endif
`ifdef IO_MULTICYCLE
.done(io_done),
`endif
.clk(~clk),
.rst(rst),
.addr(dmem_addr[`IO_SIZE+1:2]),
.data_in(dmem_data_toio),
.data_out(dmem_data_fromio),
.read(dmem_re_io),
.write(dmem_we_io)
);
`endif
 
openfire_bootram BOOTRAM( // boot ram (block ram)
.rst(rst),
.clk(~clk),
.ins_addr( imem_addr[12:2] ),
.ins_output(imem_data_frombram),
.data_sel(data_selector),
.data_we(dmem_we_bram),
.data_addr( dmem_addr[12:2] ),
.data_input(dmem_data_tobram),
.data_output(dmem_data_frombram)
);
 
`ifdef SP3SK_SRAM // sram controller
sram_controller sram_256kx32(
.rst(rst), .clk(~clk), // controller at full speed
 
.ram_addr(ram_addr), .ram_oe_n(ram_oe_n), .ram_we_n(ram_we_n), // sp3sk sram interface
.ram1_io(ram1_io), .ram1_ce_n(ram1_ce_n), .ram1_ub_n(ram1_ub_n), .ram1_lb_n(ram1_lb_n),
.ram2_io(ram2_io), .ram2_ce_n(ram2_ce_n), .ram2_ub_n(ram2_ub_n), .ram2_lb_n(ram2_lb_n),
 
.addr1( dmem_addr[19:2] ), // dmem port (read/write) byte capable
.data2mem1(sram_data2mem1),
.data2cpu1(sram_data2cpu1),
.re1(sram_re1),
.we1(sram_we1),
.select1(data_selector),
.done1(sram_done1),
 
.addr2( imem_addr[19:2] ), // imem port (read only) word only
.data2cpu2(sram_data2cpu2),
.re2(sram_re2),
.done2(sram_done2),
 
.addr3(sram_addr3), // aux port (read only) word only
.data2cpu3(sram_data2cpu3),
.re3(sram_re3),
.done3(sram_done3)
);
`endif
 
`ifdef SP3SK_VGA // vga module
vga_controller VGA(
.reset(rst),
.cpu_clk(clk), // for the sram fetch module
.pixel_clk(clk), // should be 25MHz for 640x480 video mode
.hsync_n(hsync_n),
.vsync_n(vsync_n),
.red(r),
.green(g),
.blue(b),
.ram_pointer(sram_addr3),
.ram_data(sram_data2cpu3),
.req(sram_re3),
.rdy(sram_done3)
);
`endif
 
`include "openfire_debug.v"
endmodule
 
/trunk/rtl/bbfifo_16x8.v
0,0 → 1,394
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2004 Xilinx, Inc.
// All Rights Reserved
////////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 1.01
// \ \ Filename: bbfifo_16x8.v
// / / Date Last Modified: 08/04/2004
// /___/ /\ Date Created: 10/14/2002
// \ \ / \
// \___\/\___\
//
//Device: Xilinx
//Purpose:
// 'Bucket Brigade' FIFO
// 16 deep
// 8-bit data
//Reference:
// None
//Revision History:
// Rev 1.00 - kc - Start of design entry in VHDL, 10/14/2002.
// Rev 1.01 - sus - Converted to verilog, 08/04/2004.
// Rev 1.02 - njs - Synplicity attributes added, 09/06/2004.
// Rev 1.03 - njs - defparam values corrected, 12/01/2005.
////////////////////////////////////////////////////////////////////////////////
// Contact: e-mail picoblaze@xilinx.com
//////////////////////////////////////////////////////////////////////////////////
//
// Disclaimer:
// LIMITED WARRANTY AND DISCLAIMER. These designs are
// provided to you "as is". Xilinx and its licensors make and you
// receive no warranties or conditions, express, implied,
// statutory or otherwise, and Xilinx specifically disclaims any
// implied warranties of merchantability, non-infringement, or
// fitness for a particular purpose. Xilinx does not warrant that
// the functions contained in these designs will meet your
// requirements, or that the operation of these designs will be
// uninterrupted or error free, or that defects in the Designs
// will be corrected. Furthermore, Xilinx does not warrant or
// make any representations regarding use or the results of the
// use of the designs in terms of correctness, accuracy,
// reliability, or otherwise.
//
// LIMITATION OF LIABILITY. In no event will Xilinx or its
// licensors be liable for any loss of data, lost profits, cost
// or procurement of substitute goods or services, or for any
// special, incidental, consequential, or indirect damages
// arising from the use or operation of the designs or
// accompanying documentation, however caused and on any theory
// of liability. This limitation will apply even if Xilinx
// has been advised of the possibility of such damage. This
// limitation shall apply not-withstanding the failure of the
// essential purpose of any limited remedies herein.
//////////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1ps
 
module bbfifo_16x8
(data_in,
data_out,
reset,
write,
read,
full,
half_full,
data_present,
clk);
 
input [7:0] data_in;
output [7:0] data_out;
input reset;
input write;
input read;
output full;
output half_full;
output data_present;
input clk;
 
////////////////////////////////////////////////////////////////////////////////////
//
// Start of BBFIFO_16x8
//
//
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
//
// wires used in BBFIFO_16x8
//
////////////////////////////////////////////////////////////////////////////////////
 
wire [3:0] pointer;
wire [3:0] next_count;
wire [3:0] half_count;
wire [2:0] count_carry;
 
wire pointer_zero;
wire pointer_full;
wire decode_data_present;
wire data_present_int;
wire valid_write;
 
////////////////////////////////////////////////////////////////////////////////////
//
// Start of BBFIFO_16x8 circuit description
//
////////////////////////////////////////////////////////////////////////////////////
// SRL16E data storage
SRL16E data_srl_0
( .D(data_in[0]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[0]) );
defparam data_srl_0.INIT = 16'h0000;
 
SRL16E data_srl_1
( .D(data_in[1]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[1]) );
defparam data_srl_1.INIT = 16'h0000;
 
SRL16E data_srl_2
( .D(data_in[2]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[2]) );
defparam data_srl_2.INIT = 16'h0000;
 
SRL16E data_srl_3
( .D(data_in[3]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[3]) );
defparam data_srl_3.INIT = 16'h0000;
 
SRL16E data_srl_4
( .D(data_in[4]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[4]) );
defparam data_srl_4.INIT = 16'h0000;
 
SRL16E data_srl_5
( .D(data_in[5]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[5]) );
defparam data_srl_5.INIT = 16'h0000;
 
SRL16E data_srl_6
( .D(data_in[6]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[6]) );
defparam data_srl_6.INIT = 16'h0000;
 
SRL16E data_srl_7
( .D(data_in[7]),
.CE(valid_write),
.CLK(clk),
.A0(pointer[0]),
.A1(pointer[1]),
.A2(pointer[2]),
.A3(pointer[3]),
.Q(data_out[7]) );
defparam data_srl_7.INIT = 16'h0000;
 
// 4-bit counter to act as data pointer
// Counter is clock enabled by 'data_present'
// Counter will be reset when 'reset' is active
// Counter will increment when 'valid_write' is active
 
FDRE register_bit_0
( .D(next_count[0]),
.Q(pointer[0]),
.CE(data_present_int),
.R(reset),
.C(clk) );
 
LUT4 count_lut_0
( .I0(pointer[0]),
.I1(read),
.I2(pointer_zero),
.I3(write),
.O(half_count[0]) );
defparam count_lut_0.INIT = 16'h6606;
 
FDRE register_bit_1
( .D(next_count[1]),
.Q(pointer[1]),
.CE(data_present_int),
.R(reset),
.C(clk) );
 
LUT4 count_lut_1
( .I0(pointer[1]),
.I1(read),
.I2(pointer_zero),
.I3(write),
.O(half_count[1]) );
defparam count_lut_1.INIT = 16'h6606;
 
FDRE register_bit_2
( .D(next_count[2]),
.Q(pointer[2]),
.CE(data_present_int),
.R(reset),
.C(clk) );
 
LUT4 count_lut_2
( .I0(pointer[2]),
.I1(read),
.I2(pointer_zero),
.I3(write),
.O(half_count[2]) );
defparam count_lut_2.INIT = 16'h6606;
 
FDRE register_bit_3
( .D(next_count[3]),
.Q(pointer[3]),
.CE(data_present_int),
.R(reset),
.C(clk) );
 
LUT4 count_lut_3
( .I0(pointer[3]),
.I1(read),
.I2(pointer_zero),
.I3(write),
.O(half_count[3]) );
defparam count_lut_3.INIT = 16'h6606;
 
MUXCY count_muxcy_0
( .DI(pointer[0]),
.CI(valid_write),
.S(half_count[0]),
.O(count_carry[0]) );
XORCY count_xor_0
( .LI(half_count[0]),
.CI(valid_write),
.O(next_count[0]) );
 
MUXCY count_muxcy_1
( .DI(pointer[1]),
.CI(count_carry[0]),
.S(half_count[1]),
.O(count_carry[1]) );
XORCY count_xor_1
( .LI(half_count[1]),
.CI(count_carry[0]),
.O(next_count[1]) );
 
MUXCY count_muxcy_2
( .DI(pointer[2]),
.CI(count_carry[1]),
.S(half_count[2]),
.O(count_carry[2]) );
XORCY count_xor_2
( .LI(half_count[2]),
.CI(count_carry[1]),
.O(next_count[2]) );
 
XORCY count_xor
( .LI(half_count[3]),
.CI(count_carry[2]),
.O(next_count[3]) );
 
// Detect when pointer is zero and maximum
 
LUT4 zero_lut
( .I0(pointer[0]),
.I1(pointer[1]),
.I2(pointer[2]),
.I3(pointer[3]),
.O(pointer_zero ) );
defparam zero_lut.INIT = 16'h0001;
 
LUT4 full_lut
( .I0(pointer[0]),
.I1(pointer[1]),
.I2(pointer[2]),
.I3(pointer[3]),
.O(pointer_full ) );
defparam full_lut.INIT = 16'h8000;
 
// Data Present status
 
LUT4 dp_lut
( .I0(write),
.I1(read),
.I2(pointer_zero),
.I3(data_present_int),
.O(decode_data_present ) );
defparam dp_lut.INIT = 16'hBFA0;
 
FDR dp_flop
( .D(decode_data_present),
.Q(data_present_int),
.R(reset),
.C(clk) );
 
// Valid write wire
 
LUT3 valid_lut
( .I0(pointer_full),
.I1(write),
.I2(read),
.O(valid_write ) );
defparam valid_lut.INIT = 8'hC4;
 
// assign internal wires to outputs
 
assign full = pointer_full;
assign half_full = pointer[3];
assign data_present = data_present_int;
 
endmodule
 
 
 
////////////////////////////////////////////////////////////////////////////////////
//
// END OF FILE BBFIFO_16x8.V
//
////////////////////////////////////////////////////////////////////////////////////
 
 
/trunk/rtl/openfire_debug.v
0,0 → 1,416
/* MODULE: openfire_debug
DESCRIPTION: Contains opcode dissasembler and
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
//synthesis translate_off
 
// ------------------ opcode disassembler -----------------
// based on the kcpsm3 (picoblaze) dissasembler
 
`ifdef OPCODE_DISSASEMBLER
reg [31:0] pc_actual;
reg [31:0] instruction; // executing instruction
reg [31:0] instruction_decode;
reg [31:0] instruction_fetch; // fetched instruction
reg [15:0] prev_imm;
 
reg [1:64] op;
reg [1:32] arg1;
reg [1:32] arg2;
reg [1:80] arg3;
 
reg [1:0] rD, rA, rB_IMM;
 
initial prev_imm = 0; // initialize IMM opcode
 
always @(posedge clk)
begin
if(rst)
begin
instruction_fetch = `NoOp;
instruction_decode = `NoOp;
instruction = `NoOp;
end
else if(imem_done)
begin
instruction = instruction_decode;
instruction_decode = instruction_fetch;
instruction_fetch = CPU.FETCH.idata;
end
end
 
always @(posedge clk)
begin
if(CPU.EXECUTE.instr_complete & !CPU.EXECUTE.stall)
begin
op[1:56] = " "; // initialize dissasembled line
arg1[1:32] = " ";
arg2[1:32] = " ";
arg3[1:80] = " ";
rD = 1; // by default enable all parameters, specific
rA = 1; // opcodes will disable they
rB_IMM = 1;
pc_actual = {{(30 - `A_SPACE) {1'b0}},CPU.EXECUTE.pc_exe}; // executed PC
 
casez(`opcode) // decode opcode
`ADD : begin
op[1:24] = "add";
if(`IMM_bit) op[25:32] = "i";
if(`K_bit) op[33:40] = "k";
if(`C_bit) op[41:48] = "c";
end
`LOGIC_AND : begin
op[1:24] = "and";
if(`IMM_bit) op[25:32] = "i";
end
`LOGIC_ANDN : begin
op[1:32] = "andn";
if(`IMM_bit) op[33:40] = "i";
end
`BRANCH_CON : begin
rD = 0;
case(`branch_compare)
`CMP_equal : op[1:24] = "beq";
`CMP_not_equal : op[1:24] = "bne";
`CMP_lessthan : op[1:24] = "blt";
`CMP_lt_equal : op[1:24] = "ble";
`CMP_greaterthan : op[1:24] = "bgt";
`CMP_gt_equal : op[1:24] = "bge";
default: $display("error: invalid conditional branch");
endcase
if(`IMM_bit) op[25:32] = "i";
if(`D_bit_cond) op[33:40] = "d";
end
`BRANCH_UNCON: begin
rA = 0;
if(`A_bit & `L_bit & ~`D_bit_uncond) // bral = break
begin
op[1:32] = "brk"; // rA is 5'b01100 for brk
if(`IMM_bit) op[33:40] = "i";
end
else
begin // other unconditional branches
op[1:16] = "br";
if(`A_bit) op[17:24] = "a";
if(`IMM_bit) op[25:32] = "i";
if(`L_bit) op[33:40] = "l"; else rD = 0; // rD used if link
if(`D_bit_uncond) op[41:48] = "d";
end
end
`BARREL_SHIFT: $display("error: barrel shift not implemented");
`FSL : $display("error: fsl not implemented");
`FP_OP : $display("error: floating point not implemented");
`DIVIDE : $display("error: divide not implemented");
`IMMEDIATE : begin
rD = 0;
rA = 0;
op[1:24]="imm";
prev_imm = instruction[15:0]; // store previous immediate
end
`LOAD : begin
op[1:8] = "l";
case(`word_size)
2'b00: op[9:24] = "bu";
2'b01: op[9:24] = "hu";
2'b10: op[9:16] = "w";
default: $display("error: invalid load");
endcase
if(`IMM_bit) op[25:32] = "i";
end
`SPECIAL_REG : begin
if(`is_mfs) // mfs rD,rS (rmsr, rpc, etc..)
begin
op[1:24] = "mfs";
rA = 0;
rB_IMM = 2;
end
else if(`is_mts) // mts rS,rD (rS only msr)
begin
op[1:24] = "mts";
rD = 2;
rB_IMM = 0;
end
end
`MULTIPLY : begin
op[1:24] = "mul";
if(`IMM_bit) op[25:32] = "i";
end
`LOGIC_OR : begin
op[1:16] = "or";
if(`IMM_bit) op[17:24] = "i";
end
`PATTERN_CMP : $display("error: pattern compare not implemented");
`SUBTRACT : begin
if(`CMP_bit)
begin
op[1:24] = "cmp"; // compare
if(`U_bit) op[25:32] = "u";
end
else op[1:32] = "rsub";
if(`IMM_bit) op[33:40] = "i";
if(`K_bit) op[41:48] = "k";
if(`C_bit) op[49:56] = "c";
end
`RETURN : begin // default is return from subroutine
rD = 0;
op[1:32] = "rtsd"; // rD = 6'b10100, type B (imm value)
if(`BRK_bit) op[17:24] = "b";
else if(`INT_bit) op[17:24] = "i";
else if(`EXC_bit) op[17:24] = "e";
end
`STORE : begin
op[1:8] = "s";
case(`word_size)
2'b00: op[9:16] = "b";
2'b01: op[9:16] = "h";
2'b10: op[9:16] = "w";
default: $display("error: invalid store");
endcase
if(`IMM_bit) op[17:24] = "i";
end
`LOGIC_BIT : begin // is only type A: opcode rD,rA,rB
rB_IMM = 0;
if(`is_SEXT16) op[1:48] = "sext16";
else if(`is_SEXT8) op[1:40] = "sext8";
else if(`is_SRA) op[1:24] = "sra";
else if(`is_SRC) op[1:24] = "src";
else if(`is_SRL) op[1:24] = "srl";
else $display("error: invalid logical bit function");
end
`LOGIC_XOR : begin
op[1:24] = "xor";
if(`IMM_bit) op[25:32] = "i";
end
default : $display("error: invalid opcode");
endcase
 
if(`opcode == `IMMEDIATE) // IMM opcode only has arg3
begin
arg3[1:16] = "0x";
arg3[17:48] = hex4(prev_imm); // high 16 bits are prev_imm
end
else
begin
if(`IMM_bit)
begin
if(prev_imm == 0) prev_imm = {16 {instruction[15]}}; // sign extend immediate
arg3[1:16] = "0x";
arg3[17:48] = hex4(prev_imm); // high 16 bits are prev_imm
arg3[49:80] = hex4(instruction[15:0]); // low 16 bits are in opcode
end
else arg3[1:24] = registro(`regB_sel);
if(rD == 1) arg1[1:24] = registro(`regD_sel);
else if(rD == 2) arg1[1:32] = registro_especial(`regS_sel_msr);
arg2[1:24] = registro(`regA_sel);
end
if(rD == 0) arg1[1:32] = " "; // disable unused parameters
if(rA == 0) arg2[1:32] = " ";
if(rB_IMM == 0) arg3[1:80] = " ";
else if(rB_IMM == 2) arg3[1:32] = registro_especial(`regS_sel_msr);
if(rD && rA) arg1[25:32] = ","; // parameter separators
if(rA && rB_IMM) arg2[25:32] = ",";
if(rD && rB_IMM) arg2[25:32] = ",";
$display("%d PC[%x] OPCODE[%x] - %s", $time, pc_actual, instruction, {op, arg1, arg2, arg3} );
if(`opcode != `IMMEDIATE && prev_imm != 0) prev_imm = 0; // after the opcode that uses the IMM, prev_imm=0
end
end
 
function [1:8] hexcharacter ; // generates 4 bit hex string
input [3:0] nibble ;
begin
case (nibble)
4'b0000 : hexcharacter = "0" ;
4'b0001 : hexcharacter = "1" ;
4'b0010 : hexcharacter = "2" ;
4'b0011 : hexcharacter = "3" ;
4'b0100 : hexcharacter = "4" ;
4'b0101 : hexcharacter = "5" ;
4'b0110 : hexcharacter = "6" ;
4'b0111 : hexcharacter = "7" ;
4'b1000 : hexcharacter = "8" ;
4'b1001 : hexcharacter = "9" ;
4'b1010 : hexcharacter = "A" ;
4'b1011 : hexcharacter = "B" ;
4'b1100 : hexcharacter = "C" ;
4'b1101 : hexcharacter = "D" ;
4'b1110 : hexcharacter = "E" ;
4'b1111 : hexcharacter = "F" ;
endcase
end
endfunction
 
function [15:0] hex2; // generates 8 bit hex string
input [7:0] num;
begin
hex2[15:8] = hexcharacter(num[7:4]);
hex2[7:0] = hexcharacter(num[3:0]);
end
endfunction
 
function [31:0] hex4; // generates 16 bit hex string
input [15:0] num;
begin
hex4[31:16] = hex2(num[15:8]);
hex4[15:0] = hex2(num[7:0]);
end
endfunction
 
function [1:32] registro_especial;
input [4:0] regn;
begin
case (regn)
`rS_PC : registro_especial = "rpc ";
`rS_MSR : registro_especial = "rmsr";
default :
begin
$display("dissasembler: error: special register %x not implemented", regn);
registro_especial = "???";
end
endcase
end
endfunction
 
function [1:24] registro; // converts 5 bits to the register representation rXX
input [4:0] regn;
begin
case (regn)
0 : registro = "r0 ";
1 : registro = "r1 ";
2 : registro = "r2 ";
3 : registro = "r3 ";
4 : registro = "r4 ";
5 : registro = "r5 ";
6 : registro = "r6 ";
7 : registro = "r7 ";
8 : registro = "r8 ";
9 : registro = "r9 ";
10: registro = "r10";
11: registro = "r11";
12: registro = "r12";
13: registro = "r13";
14: registro = "r14";
15: registro = "r15";
16: registro = "r16";
17: registro = "r17";
18: registro = "r18";
19: registro = "r19";
20: registro = "r20";
21: registro = "r21";
22: registro = "r22";
23: registro = "r23";
24: registro = "r24";
25: registro = "r25";
26: registro = "r26";
27: registro = "r27";
28: registro = "r28";
29: registro = "r29";
30: registro = "r30";
31: registro = "r31";
endcase
end
endfunction
`endif
 
// -------------- memory/register dumps -------------------
// from Stephen Douglas Craven testbench
 
`ifdef DEBUG_SIMPLE_MEMORY_DUMP
// BREAKPOINT stops simulation and displays register contents.
// Set to unreachable address to disable.
`define BREAKPOINT 32'hc0
 
// Define clock counter for debugging
integer i;
 
reg [31:0] counter;
assign clock = clk;
assign reset = rst;
 
initial begin
counter = 32'b0;
for (i = 0; i >= 0; i = i + 1)
@(posedge clock) if (~reset) counter <= counter + 1;
end
 
// Debug Statements
always@(posedge clock)
begin
if( CPU.EXECUTE.instr_complete & !CPU.EXECUTE.stall )
begin
if(CPU.branch_taken) // Branch instructions
begin
$display("*** PC=%x: BRANCH=%x", {{(30 - `A_SPACE) {1'b0}},CPU.EXECUTE.pc_exe},
{{(30 - `A_SPACE) {1'b0}},CPU.pc_branch});
end
if (CPU.REGFILE.write_en) // Register File writes
begin
if(CPU.dmem_re)
$display("*** PC=%x: r%d=%x (leido de DMEM=0x%x)", {{(30 - `A_SPACE) {1'b0}},CPU.EXECUTE.pc_exe},
CPU.REGFILE.regD_addr, {CPU.REGFILE.input_data}, CPU.dmem_addr );
else
$display("*** PC=%x: r%d=%x", {{(30 - `A_SPACE) {1'b0}},CPU.EXECUTE.pc_exe}, CPU.REGFILE.regD_addr,
{CPU.REGFILE.input_data});
end
 
if (dmem_we) // Memory writes
begin
$display("*** PC=%x: addr=%x write=%x", {{(30 - `A_SPACE) {1'b0}},CPU.EXECUTE.pc_exe},
CPU.dmem_addr, dmem_data2mem);
end
if (dmem_re & !CPU.REGFILE.write_en) // Memory read
begin
$display("*** PC=%x: addr=%x read=%x", {{(30 - `A_SPACE) {1'b0}},CPU.EXECUTE.pc_exe},
CPU.dmem_addr, dmem_data2cpu);
end
end
 
end
 
// Stop at Breakpoint
//always@(posedge clock)
//begin
// if(CPU.DECODE.pc_exe == `BREAKPOINT)
// begin
// Uncomment to display register file contents at breakpoint
/* $display(" PC is %x", CPU.EXECUTE.pc_exe);
$display(" Clock Counter is %d", counter);
for(j = 0; j < 8; j = j + 1)
$display(" %d: %x %d %x %d: %x %d %x", j, CPU.REGFILE.RF_BANK0.MEM[j], j + 8,
CPU.REGFILE.RF_BANK0.MEM[j + 8],j+16, CPU.REGFILE.RF_BANK0.MEM[j+16],j+24,
CPU.REGFILE.RF_BANK0.MEM[j+24]);
*/
// $finish;
// end
//end
`endif
 
//synthesis translate_on
/trunk/rtl/openfire_cpu.v
0,0 → 1,278
/* MODULE: openfire_cpu
 
DESCRIPTION: This is the top module for the openfire processor, instantiating
the fetch, decode, execute, pipeline_ctrl, and register file modules.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug
 
Revision 0.4 27/03/2007 Antonio J. Anton
Improved (interrupts, exceptions, msr)
Ripup of memory signals
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
 
`include "openfire_define.v"
 
module openfire_cpu (
clock, reset,
`ifdef ENABLE_INTERRUPTS
interrupt,
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
dmem_alignment_exception,
`endif
dmem_addr, dmem_data_in, dmem_data_out, // ins/data ports
dmem_we, dmem_re, dmem_input_sel, dmem_done,
imem_addr, imem_data_in, imem_re, imem_done
);
 
input clock;
input reset;
input [31:0] dmem_data_in;
input [31:0] imem_data_in;
input dmem_done;
input imem_done;
`ifdef ENABLE_INTERRUPTS
input interrupt;
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
input dmem_alignment_exception;
`endif
 
output [31:0] dmem_data_out;
output [31:0] dmem_addr;
output [31:0] imem_addr;
output imem_re;
output dmem_we;
output dmem_re;
output [1:0] dmem_input_sel; //0=byte, 1=hw, 2=word
 
wire branch_taken;
wire [`A_SPACE+1:0] pc_branch;
wire [`A_SPACE+1:0] pc_decode;
wire [`A_SPACE+1:0] pc_exe_rf;
wire [31:0] instruction;
wire [4:0] regA_addr;
wire [4:0] regB_addr;
wire [4:0] regD_addr;
wire [31:0] immediate;
 
wire [2:0] alu_inputA_sel;
wire [1:0] alu_inputB_sel;
wire [1:0] alu_inputC_sel;
wire [3:0] alu_fns_sel;
wire [2:0] comparator_fns_sel;
wire we_alu_branch;
wire we_load;
wire we_store;
wire we_regfile;
wire [3:0] regfile_input_sel;
wire delay_bit;
wire [31:0] result;
 
wire [31:0] regA;
wire [31:0] regB;
wire [31:0] regD;
wire update_carry;
wire stall_exe;
wire stall_decode;
wire stall_fetch;
wire instr_complete;
wire flush;
wire branch_instr;
 
`ifdef ENABLE_MSR_BIP
wire update_msr_bip;
wire value_msr_bip;
`endif
`ifdef ENABLE_INTERRUPTS
wire int_ip;
wire int_dc;
wire set_msr_ie;
`endif
`ifdef ENABLE_EXCEPTIONS
wire reset_msr_eip;
wire insert_exception;
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
wire opcode_exception;
`endif
`ifdef ENABLE_MSR_OPCODES
wire rS_update;
`endif
 
openfire_fetch FETCH (
.stall(stall_fetch),
.clock(clock),
.reset(reset),
.branch_taken(branch_taken),
.pc_branch(pc_branch),
.idata(imem_data_in),
.imem_addr(imem_addr),
.imem_re(imem_re),
.pc_decode(pc_decode),
.instruction(instruction)
);
 
openfire_decode DECODE (
`ifdef ENABLE_MSR_BIP
.update_msr_bip(update_msr_bip),
.value_msr_bip(value_msr_bip),
`endif
`ifdef ENABLE_INTERRUPTS
.int_ip(int_ip),
.int_dc(int_dc),
.set_msr_ie(set_msr_ie),
`endif
`ifdef ENABLE_EXCEPTIONS
.reset_msr_eip(reset_msr_eip),
.insert_exception(insert_exception),
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
.opcode_exception(opcode_exception),
`endif
`ifdef ENABLE_MSR_OPCODES
.rS_update(rs_update),
`endif
.clock(clock),
.stall(stall_decode),
.reset(reset),
.pc_decode(pc_decode),
.instruction(instruction),
.regA_addr(regA_addr),
.regB_addr(regB_addr),
.regD_addr(regD_addr),
.immediate(immediate),
.pc_exe(pc_exe_rf),
.alu_inputA_sel(alu_inputA_sel),
.alu_inputB_sel(alu_inputB_sel),
.alu_inputC_sel(alu_inputC_sel),
.alu_fns_sel(alu_fns_sel),
.comparator_fns_sel(comparator_fns_sel),
.branch_instr(branch_instr),
.we_alu_branch(we_alu_branch),
.we_load(we_load),
.we_store(we_store),
.regfile_input_sel(regfile_input_sel),
.dmem_input_sel(dmem_input_sel),
.flush(flush),
.delay_bit(delay_bit),
.update_carry(update_carry)
);
 
openfire_execute EXECUTE (
`ifdef ENABLE_MSR_BIP
.update_msr_bip(update_msr_bip),
.value_msr_bip(value_msr_bip),
`endif
`ifdef ENABLE_INTERRUPTS
.interrupt(interrupt),
.int_ip(int_ip),
.int_dc(int_dc),
.set_msr_ie(set_msr_ie),
`endif
`ifdef ENABLE_EXCEPTIONS
.reset_msr_eip(reset_msr_eip),
.insert_exception(insert_exception),
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
.opcode_exception(opcode_exception),
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
.dmem_alignment_exception(dmem_alignment_exception),
`endif
`ifdef ENABLE_MSR_OPCODES
.rS_update(rs_update),
`endif
.clock(clock),
.reset(reset),
.stall(stall_exe),
.immediate(immediate),
.pc_exe(pc_exe_rf),
.alu_inputA_sel(alu_inputA_sel),
.alu_inputB_sel(alu_inputB_sel),
.alu_inputC_sel(alu_inputC_sel),
.alu_fns_sel(alu_fns_sel),
.comparator_fns_sel(comparator_fns_sel),
.we_load(we_load),
.we_store(we_store),
.update_carry(update_carry),
.regA(regA),
.regB(regB),
.regD(regD),
.alu_result(result),
.pc_branch(pc_branch),
.branch_instr(branch_instr),
.branch_taken(branch_taken),
.instr_complete(instr_complete),
.dmem_addr(dmem_addr),
.dmem_data_out(dmem_data_out),
.dmem_done(dmem_done),
.we_regfile(we_regfile),
.dmem_we(dmem_we),
.dmem_re(dmem_re)
);
openfire_regfile REGFILE (
.reset(reset),
.clock(clock),
.regA_addr(regA_addr),
.regB_addr(regB_addr),
.regD_addr(regD_addr),
.result(result),
.pc_regfile(pc_exe_rf),
.dmem_data(dmem_data_in),
.regfile_input_sel(regfile_input_sel),
.we_regfile(we_regfile),
.we_alu_branch(we_alu_branch),
.regA(regA),
.regB(regB),
.regD(regD),
.enable(~stall_exe)
);
 
openfire_pipeline_ctrl PIPELINE (
.clock(clock),
.reset(reset),
.flush(flush),
.imem_done(imem_done),
.imem_re(imem_re),
.branch_taken(branch_taken),
.instr_complete(instr_complete),
.delay_bit(delay_bit),
.stall_fetch(stall_fetch),
.stall_decode(stall_decode),
.stall_exe(stall_exe)
);
endmodule
/trunk/rtl/openfire_fetch.v
0,0 → 1,106
/* MODULE: openfire_fetch
 
DESCRIPTION: The fetch module interfaces with the instruction memory and
fetches the next instruction.
 
TO DO:
- Add prefetch buffer
- Add LMB interface
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug
 
Revision 0.4 27/03/2007 Antonio J Anton
Instruction port wait states
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
 
`include "openfire_define.v"
 
module openfire_fetch(
stall, clock, reset, // top level
branch_taken, pc_branch, idata, // inputs
instruction, imem_addr, pc_decode, imem_re // outputs
);
// From top level -- all active high unless otherwise noted
input stall;
input reset;
input clock;
 
// From EXECUTE module
input branch_taken; // strobe for latching in new pc
// PCs are A_SPACE + 1 because lower 2 bits are always zero
// A_SPACE is addr space in words ... 2^A_SPACE * 4 = # Bytes
input [`A_SPACE+1:0] pc_branch; // PC of branch
 
// From Instr Mem
input [31:0] idata;
 
output [31:0] imem_addr;
output imem_re;
output [`A_SPACE+1:0] pc_decode;
output [31:0] instruction;
 
reg [`A_SPACE+1:0] pc_fetch; // PCs only need to contain addressable instr mem
reg [`A_SPACE+1:0] pc_decode; // delayed PC for DECODE
reg [31:0] instruction;
reg imem_re;
 
assign imem_addr[31:`A_SPACE+2] = 0; // pad unused bits with zeros,
assign imem_addr[`A_SPACE+1:0] = pc_fetch;
 
always@(posedge clock)
begin
if (reset)
begin
pc_fetch <= 0;
pc_decode <= 0;
imem_re <= 1;
instruction <= `NoOp; // Execute NoOp on reset
end
else
begin // update PC to branch or increment pc (if stall --> pc on hold)
if(!stall)
begin
pc_fetch <= branch_taken ? pc_branch : pc_fetch + 4;
pc_decode <= pc_fetch;
instruction <= idata;
`ifdef DEBUG_FETCH
$display("FETCH : pc_fetch=%x, pc_decode=%x, instruction=%x", pc_fetch, pc_decode, instruction);
`endif
end
imem_re <= !stall;
end
end
 
endmodule
/trunk/rtl/openfire_pipeline_ctrl.v
0,0 → 1,133
/* MODULE: openfire_pipeline_ctrl
 
DESCRIPTION: Pipeline controller to stall various modules. FETCH and DECODE
are stalled on multicycle instructions (currently only loads & stores & MULs).
DECODE and EXECUTE cycles are stalled on branchs. See below for timing.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 27/03/2007 Antonio J Anton
Handling of instruction memory stall
data memory stall is handled by the multicycle instruction not completed
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
`include "openfire_define.v"
 
module openfire_pipeline_ctrl(
clock, reset,
branch_taken, instr_complete, delay_bit,
stall_fetch, stall_decode, stall_exe, flush,
imem_done, imem_re
);
// From top level
input clock;
input reset;
input imem_done;
input imem_re;
 
// From DECODE/EXECUTE
input delay_bit;
input branch_taken;
input instr_complete;
 
output stall_fetch;
output stall_decode;
output stall_exe;
output flush; // flush DECODE instruction
 
reg [1:0] branch_cnt;
wire stall = (~imem_done & imem_re); // stall if fetch is not completed
 
assign stall_fetch = ~instr_complete | stall;
assign stall_decode = ~instr_complete | branch_cnt[1] | stall ;
assign stall_exe = branch_cnt[0] | stall;
assign flush = branch_taken & ~delay_bit;
 
always@(posedge clock)
begin
if (reset)
branch_cnt <= 0;
else if (~stall)
begin
if (branch_taken)
branch_cnt <= 2;
else if (instr_complete & |branch_cnt)
branch_cnt <= branch_cnt - 1;
end
end
 
endmodule
 
/* TIMING DIAGRAM
Branch with Delay (F = Fetch, D = Decode, E = Execute)
|--------|--------|--------|--------|--------|--------|
____ ____ ____ ____ ____ ____
clock | |___| |___| |___| |___| |___| |___
 
F - BRD D - BRD E - BRD
F - ADD D - ADD E - ADD
F - AND S - AND S - AND
F - XOR D - XOR E - XOR
________
branch_taken ___________________| |_____________________
_______
branch_cnt ___________________________| |________________
_______
stall_decode _________________________| |________________
________________________________________________
instr_complete
________
delay_bit __________________| |_________________________
___
flush _____________________________| |____________________
 
 
Branch without Delay (S = Stall)
|--------|--------|--------|--------|--------|--------|
____ ____ ____ ____ ____ ____
clock | |___| |___| |___| |___| |___| |___
 
F - BRA D - BRA E - BRA
F - ADD D - ADD S - ADD
F - AND S - AND S - AND
F - XOR D - XOR E - XOR
________
branch_taken ___________________| |_____________________
_______
branch_cnt ___________________________| |________________
_______
stall_decode _________________________| |________________
________________________________________________
instr_complete
*/
/trunk/rtl/sim_sram256kx16.v
0,0 → 1,91
/* MODULE: sram 256k x 16
DESCRIPTION: Contains simulation model for the 256K x 16 bit SRAM
in spartan 3 starter kit
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
/* sram256Kx16.v -- external async 256Kx16 SRAM Verilog model (simulation only) */
`timescale 1ns/100ps
`include "openfire_define.v"
 
module SRAM256KX16(ce_n, we_n, oe_n, ub_n, lb_n, addr, io);
 
parameter MAX_RAM = `MAX_SIMULATION_SRAM; // max. memoria simulada
parameter DELAY = 12; // retraso de acceso (lectura/escritura) a memoria
 
input ce_n; // active low chip enable
input we_n; // active low write enable
input oe_n; // active low output enable
input ub_n; // byte alto activo (negado)
input lb_n; // byte bajo activo (negado)
input [17:0] addr; // address (18 bits=256k)
inout [15:0] io; // tri-state data I/O
 
reg [7:0] memh [0:MAX_RAM - 1]; // no simulamos toda la memoria
reg [7:0] meml [0:MAX_RAM - 1];
 
integer n; // contador para memoria
initial begin
$display("Inicializando %d bytes de RAM...", MAX_RAM);
for(n = 0; n < MAX_RAM; n = n + 1) // inicializar la memoria
begin
memh[n] = n / 256;
meml[n] = n % 256;
end
$display("RAM inicializada");
end
 
// lectura
wire [7:0] #DELAY lectura_meml = meml[addr % MAX_RAM];
wire [7:0] #DELAY lectura_memh = memh[addr % MAX_RAM];
 
// tristate buffers
assign io[7:0] = (~oe_n & we_n & ~ce_n & ~lb_n) ? lectura_meml : 8'bz;
assign io[15:8] = (~oe_n & we_n & ~ce_n & ~ub_n) ? lectura_memh : 8'bz;
 
// escritura
always @(we_n or ce_n or lb_n or ub_n)
begin
#1 // glitch filter
if(~we_n & ~ce_n & ~lb_n)
begin
meml[addr % MAX_RAM] = io[7:0];
$display(" write LOW: meml[%d(%d)]=%d", addr, addr % MAX_RAM, meml[addr % MAX_RAM]);
end
if(~we_n & ~ce_n & ~ub_n)
begin
memh[addr % MAX_RAM] = io[15:8];
$display(" write HIGH: memh[%d(%d)]=%d", addr, addr % MAX_RAM, memh[addr % MAX_RAM]);
end
end
 
endmodule
 
/trunk/rtl/openfire_define.v
0,0 → 1,275
/* MODULE: openfire_define
DESCRIPTION: Contains define statements used for readability.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
 
New tags added for Core/SOC/Peripherals
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
 
`timescale 1ns/100ps
 
/************* USER MODIFIED SOC OPTIONS ****************/
`define CLK_25MHZ // system clock
`define IO_SIZE 4 // up to 16 IO addresses
 
// IO memory address (use <<2 at program level)
`define ADDR_SP3_IO 0 // 7SEG + LEDS + SWITCHES + PUSHBUTTONS
`define ADDR_UARTS 1 // uart1/2 status register
`define ADDR_UART1 2 // uart 1 tx/rx
`define ADDR_UART2 3 // uart 2 tx/rx
`define ADDR_PROM 4 // prom control/status/data
`define ADDR_TIMER1 5 // control / set / current
`define ADDR_INT 6 // interrupt enable
 
`define BAUD_COUNT 13 // 26=115200@50mhz, 324=9600@50mhz, 13=115200@25mhz
`define PROM_SYNC_PATTERN 32'h8F9FAFBF // bit pattern to detect start of file
 
`define SP3SK_IODEVICES // enables peripherals on SP3SK
`ifdef SP3SK_IODEVICES
`define SP3SK_USERIO // enable GPIO in SP3SK board
`define UART1_ENABLE // enable UART #1
//`define UART2_ENABLE // enable UART #2
`define SP3SK_PROM_DATA // enable user data at the end of FPGA PROM
`define TIMER1_GENERATOR // enable TIMER generator (31 bit + 1 restart/stop bit)
//`define IO_MULTICYCLE // enable multicycle i/o operations
`endif
`define SP3SK_SRAM // enable external 1Mx32 SRAM in SP3SK
`define SP3SK_VGA // enable VGA in SP3SK
 
`define LOCATION_BRAM 2'b00 // boot ram 0x0000_0000->0x0000_1FFF (8 Kbytes)
`define LOCATION_SRAM 2'b01 // external SRAM 0x0400_0000->0x040F_FFFF (1 Mbyte)
`define LOCATION_BRAM_WRAP 2'b11 // temporary wrap end address space with bootram
`define LOCATION_IOSPACE 2'b10 // 0x08xx_xx<00yy><zz00> yyzz=i/o address
`define LOCATION_VRAM 18'h3_8800 // video ram starts at 0x040E_2000 (end of SRAM)
 
`define SRAM_BASE_ADDRESS { {32 - `A_SPACE{0}, `LOCATION_SRAM, {`A_SPACE-2{0}} }
`define IO_BASE_ADDRESS { {32 - `A_SPACE{0}, `LOCATION_IOSPACE, {`A_SPACE-2{0}} }
`define VIDEO_BASE_ADDRESS { {32 - `A_SPACE{0}, `LOCATION_SRAM, `LOCATION_VRAM }
 
/***********************************
* User-modified Processor Options *
***********************************/
// enable opcode dissasembler in simulador
`define OPCODE_DISSASEMBLER
`define DEBUG_SIMPLE_MEMORY_DUMP
//`define DEBUG_FETCH
//`define DEBUG_DECODE
//`define DEBUG_EXECUTE
`define DEBUG_FILE_SRAM "..\\sw\\sample2\\sample.rom" // ROM file to be loaded at SRAM base
`define MAX_SIMULATION_SRAM 4096 // in 32 bit words
 
`define ENABLE_INTERRUPTS // enable interrupt handling & MSR[IE] bit
//`define ENABLE_MSR_BIP // enables MSR[BIP] processing
`define ENABLE_MSR_OPCODES // opcodes to manage MS registers (mfs, msrclr, msrset, mts)
 
//`define ENABLE_EXCEPTIONS // enable exception handling & MSR[EIP] bit
`ifdef ENABLE_EXCEPTIONS
//`define ENABLE_ALIGNMENT_EXCEPTION // generates exception on memory read/write unalignment
//`define ENABLE_OPCODE_EXCEPTION // generates exception on invalid opcode
`endif
//`define FSL_LINK
 
// Optional CMPU instruction requires a 32-bit comparator
// To enable CMPU support, leave only one of the following two options uncommented
// To disable CMPU support (for faster, smaller core) comment out both options
//`define FAST_CMP // use fast, but larger comparator for CMPU instr
`define CMP // include comparator for CMPU instr
 
// Specify address space size
// If using a unified memory (data and instr in same memory) both memory sizes must be the same
`define IM_SIZE 28 // width of instruction memory space; 12 => 2^12 words = 16kB
`define DM_SIZE 28 // width of data memory space; 12 => 2^12 words = 16kB
 
// Specify addressible space -- easiest just to set to max of IM_SIZE and DM_SIZE
`define A_SPACE 28 // width of addressible space, used for PC (must be =< D_WIDTH)
 
// Optional HW multiplier uses 3 Xilinx Block MULTS for 32-bit multiply
`define MUL // include HW multiplier
//`define DIV // include HW divider **TODO**
//`define BS // include HW barrel shift **TODO**
 
// End User-modified Processor Options
// Sets define statements for datapath -- DO NOT TOUCH ANYTHING BELOW THIS LINE (UNLESS ADDING INSTRUCTIONS)
`define NoOp 32'h8000_0000 // NoOp instruction
`define IntOp 32'hB9CC_0010 // Interrupt Opcode is: brali r14,0x10
//`define ExcptOp 32'h // Exception Opcode is: brali r17,0x20
//`define BreakOp 32'h // Break Opcode is: brali r16,0x18
 
`define REG_RET_FROM_INTERRUPT 14 // return address from interrupt in r14
`define ADDRESS_INTERRUPT_VECTOR 32'h10 // interrupt vector is at 0x10
`define REG_RET_FROM_BREAK 16 // return address from break in r16
`define ADDRESS_BREAK_VECTOR 32'h18 // break vector is at 0x18
`define REG_RET_FROM_EXCEPTION 17 // return address from exception in r17
`define ADDRESS_EXCEPTION_VECTOR 32'h20 // exception vector is at 0x20
 
// Instruction Fields
`define opcode instruction[31:26]
`define regD_sel instruction[25:21]
`define regA_sel instruction[20:16]
`define regB_sel instruction[15:11]
`define imm_value instruction[15:0]
`define branch_compare instruction[23:21]
`define word_size instruction[27:26]
`define fsl_get_put instruction[15]
//`define regS_sel_mfs instruction[13:0]
//`define regS_sel_mts instruction[2:0]
`define regS_sel_msr instruction[3:0]
 
// Special opcode bits
`define CMP_bit instruction[0] // differentiate CMP/CMPU instr from SUBSTRACT
`define C_bit instruction[27] // Use Carry bit
`define K_bit instruction[28] // if 1, do not update Carry bit in MSR
`define D_bit_uncond instruction[20] // Delay bit for unconditional branchs
`define D_bit_cond instruction[25] // Delay bit for conditional branchs
`define A_bit instruction[19] // Absolute addressing for branch
`define L_bit instruction[18] // Link bit, stores PC in rD for branchs
`define U_bit instruction[1] // Unsigned bit for Compare instructions
`define IMM_bit instruction[29] // IMMediate
`define uncond_branch (({instruction[31], instruction[30], instruction[28], instruction[27], instruction[26]} == 5'b10110 ) | ({instruction[31], instruction[30], instruction[28], instruction[27], instruction[26]} == 5'b10101 ))
`define cond_branch ({instruction[31], instruction[30], instruction[28], instruction[27], instruction[26]} == 5'b10111 )
`define FSL_nblock instruction[14]
`define FSL_control instruction[13]
`define BRK_bit instruction[22] // break bit for returns
`define INT_bit instruction[21] // interrupt bit
`define EXC_bit instruction[23] // exception bit
`define is_SEXT16 (instruction[6:0] == 7'b1100001) // functions for LOGICAL_BIT opcode
`define is_SEXT8 (instruction[6:0] == 7'b1100000)
`define is_SRA (instruction[6:0] == 7'b0000001)
`define is_SRC (instruction[6:0] == 7'b0100001)
`define is_SRL (instruction[6:0] == 7'b1000001)
`define is_mfs (instruction[15:14] == 3'b10)
`define msr_clrset instruction[16] //1=clr, 0=set
`define is_mts (instruction[15:14] == 2'b11)
 
// Instructions
`define ADD 6'b00???0 // 00ikc0 add[i][k][c]
`define LOGIC_AND 6'b10?001 // 10i001 and[i]
`define LOGIC_ANDN 6'b10?011 // 10i011 andn[i]
`define BRANCH_CON 6'b10?111 // 10i111 d b<cond>[i][d]
`define BRANCH_UNCON 6'b10?110 // 10i110 <rD> dal br[a][i][l][d] Break is actually BRAL
`define BREAK 6'b10?110 // brk=bral
`define BARREL_SHIFT 6'b01?001 // 01i001 <rD><rA><rB> st bs<l|r><l|a>[i] s=1/0=left/right, t=1/0=arithmetic/logical
`define COMPARE 6'b000101 // same as SUBSTRACT with opcode[0]=1
`define FSL 6'b011011 // 011011 <rd> 00000 <g|p>nc....<fslN 3bits> n=0 block, c=control [n][c]get/[n][c]put
`define FP_OP 6'b010110 // floating point instructions
`define DIVIDE 6'b01?010 // 01i010 <rd> <rA> <rB> bit[30]=1=unsigned idiv[u]
`define IMMEDIATE 6'b101100 // 101100 imm
`define LOAD 6'b11?0?? // 11i0wh wh=00: lbu[i], wh=01: lhu[i], wh=10: lw[i]
`define SPECIAL_REG 6'b100101 // **todo**
`define MULTIPLY 6'b01?000 // 01i000 mul[i]
`define LOGIC_OR 6'b10?000 // 10i000 or[i]
`define PATTERN_CMP 6'b100000 // **todo**
`define SUBTRACT 6'b00???1 // 00ikc1 rsub[i][k][c]
`define RETURN 6'b101101 // 101101 10ebi <rA> rt<e|b|i|s>d (ebi=0 --> s)
`define STORE 6'b11?1?? // 11i1wh wh=00: sb[i], wh=01: sh[i], wh=10: sl[i]
`define LOGIC_BIT 6'b100100 // 100100 and 7 lower bits sext16,sext8,sra,src,srl,wdc, wic
`define LOGIC_XOR 6'b10?010 // 10i010 xor[i]
 
// ALU Functions
`define ALU_add 4'd0
`define ALU_compare_uns 4'd1 // CMPU (unsigned Compare)
`define ALU_logic_or 4'd2
`define ALU_logic_and 4'd3
`define ALU_logic_xor 4'd4
`define ALU_sex8 4'd5
`define ALU_sex16 4'd6
`define ALU_shiftR_arth 4'd7
`define ALU_shiftR_log 4'd8
`define ALU_shiftR_c 4'd9
`define ALU_compare 4'd10 // CMP
`define ALU_multiply 4'd11
`define ALU_divide 4'd12 // **TODO**
`define ALU_barrel 4'd13 // **TODO**
 
// ALU inputs
`define aluA_ra 3'd0 // size increased to acommodate further inputs
`define aluA_ra_bar 3'd1 // from special registers
`define aluA_pc 3'd2
`define aluA_zero 3'd3
`define aluA_msr 3'd4
 
`define aluB_rb 2'd0
`define aluB_imm 2'd1
`define aluB_rb_bar 2'd2
`define aluB_imm_bar 2'd3
 
`define aluC_zero 2'd0
`define aluC_one 2'd1
`define aluC_carry 2'd2
 
// Comparator Functions
`define CMP_equal 3'd0
`define CMP_not_equal 3'd1
`define CMP_lessthan 3'd2
`define CMP_lt_equal 3'd3
`define CMP_greaterthan 3'd4
`define CMP_gt_equal 3'd5
`define CMP_one 3'd6
`define CMP_dual_inputs 3'd7 // compare regA and regB for CMPU instr
 
// RegFile Input Select (width increased)
`define RF_dmem_byte 4'd0 // same as `word_size
`define RF_dmem_halfword 4'd1 // same as `word_size
`define RF_dmem_wholeword 4'd2 // same as `word_size
`define RF_alu_result 4'd3
`define RF_pc 4'd4
`define RF_zero 4'd5
`define RF_fsl 4'd6
`define RF_msr 4'd7
`define RF_ear 4'd8 //todo
`define RF_esr 4'd9 //todo
`define RF_btr 4'd10 //todo
 
// DMEM Input Select
`define DM_byte 2'd0
`define DM_halfword 2'd1
`define DM_wholeword 2'd2
 
// MSR bits
`define MSR_BL_Ena 0 // bus lock enable
`define MSR_IE 1 // interrupt enable
`define MSR_C 2 // carry
`define MSR_BIP 3 // break in progress
`define MSR_FSL_Err 4 // FSL error
`define MSR_IC_Ena 5 // Instruction Cache
`define MSR_DZ 6 // Division by Zero
`define MSR_DC_Ena 7 // Data Cache
`define MSR_E_Ena 8 // Exception enable
`define MSR_EIP 9 // Exception in progress
`define MSR_PVR 10 // Procesor Version Register exists
 
// MSR registers
`define rS_PC 4'h0
`define rS_MSR 4'h1
`define rS_EAR 4'h3
`define rS_ESR 4'h5
`define rS_BTR 4'hB
/trunk/rtl/openfire_primitives.v
0,0 → 1,335
/* MODULE: openfire_primitives
 
DESCRIPTION: Contains all submodules called by the design.
 
CONTENTS:
openfire_compare comparator for conditional branchs & CMPU instr
openfire_alu
openfire_rf_sram registerfile
 
TO DO:
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed Register File zeroing function for simulation
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE */
 
`include "openfire_define.v"
 
/**********************************
* Comparator for Branches & CMPU *
**********************************/
module openfire_compare (
in0, in1, fns, // inputs
out); // outputs
 
input [31:0] in0;
input [31:0] in1;
input [2:0] fns;
output out;
 
reg out;
 
wire cmp_out;
 
`ifdef FAST_CMP
wire cmp_dual_out;
 
// A single comparator could be used, but timing is tight.
// A single comparator can reach 100 MHz in a 2vp-7 part, but not in a -6 speed grade.
assign cmp_dual_out = (in0 > in1);
assign cmp_out = (in0[30:0] > 0);
 
always@(in0 or in1 or cmp_out or fns or cmp_dual_out)
begin
 
// Verilog treats all signals as unsigned
case(fns)
`CMP_equal: out <= (in0 == 0);
`CMP_not_equal: out <= (in0 != 0);
`CMP_lessthan: out <= (in0[31] == 1); // negative number
`CMP_lt_equal: out <= (in0 == 0) | (in0[31] == 1);
`CMP_greaterthan: out <= cmp_out & (in0[31] == 0);
`CMP_gt_equal: out <= (cmp_out | (in0[30:0] == 0)) & (in0[31] == 0);
`CMP_one: out <= 1'b1; // used for unconditional branchs
`CMP_dual_inputs: out <= cmp_dual_out; // used only for CMPU instruction
default:
begin
out <= 1'b0;
$display("ERROR! Comparator set to illegal function!");
end
endcase
end // always@
`else
`ifdef CMP
// Force tools to synthesize only a single 32-bit comparator... cannot reach 100 MHz in a 2vp speed grade 6 part
reg [31:0] cmp_in_a;
reg [31:0] cmp_in_b;
 
assign cmp_out = (cmp_in_a > cmp_in_b);
 
always@(in0 or in1 or cmp_out or fns)
begin
cmp_in_a <= {1'b0, in0[30:0]};
cmp_in_b <= 0;
// Verilog treats all signals as unsigned
case(fns)
`CMP_equal: out <= (in0 == 0);
`CMP_not_equal: out <= (in0 != 0);
`CMP_lessthan: out <= (in0[31] == 1); // negative number
`CMP_lt_equal: out <= (in0 == 0) | (in0[31] == 1);
`CMP_greaterthan: out <= cmp_out & (in0[31] == 0);
`CMP_gt_equal: out <= (cmp_out | (in0[30:0] == 0)) & (in0[30] == 0);
`CMP_one: out <= 1'b1; // used for unconditional branchs
`CMP_dual_inputs:
begin // used only for CMPU instruction
cmp_in_a <= in0;
cmp_in_b <= in1;
out <= cmp_out;
end
default:
begin
out <= 1'b0;
$display("ERROR! Comparator set to illegal function!");
end
endcase
end // always@
`else // Do not allow CMPU instruction
 
reg [30:0] cmp_in_a;
 
assign cmp_out = (cmp_in_a > 0);
 
always@(in0, in1, cmp_out, fns)
begin
cmp_in_a <= in0[30:0];
// Verilog treats all signals as unsigned
case(fns)
`CMP_equal: out <= (in0 == 0);
`CMP_not_equal: out <= (in0 != 0);
`CMP_lessthan: out <= (in0[31] == 1); // negative number
`CMP_lt_equal: out <= (in0 == 0) | (in0[31] == 1);
`CMP_greaterthan: out <= cmp_out & (in0[31] == 0);
`CMP_gt_equal: out <= (cmp_out | (in0[30:0] == 0)) & (in0[31] == 0);
`CMP_one: out <= 1'b1; // used for unconditional branchs
default:
begin
out <= 1'b0;
$display("ERROR! Comparator set to illegal function!");
end
endcase
end // always@
`endif
`endif
 
endmodule
 
/**************
* Custom ALU *
**************/
module openfire_alu (
a, b, c_in, fns, clock, reset, stall, // inputs
alu_result, c_out, dmem_addr, // output
alu_multicycle_instr, alu_multicycle_instr_complete);
input [31:0] a;
input [31:0] b;
input c_in;
input [3:0] fns;
input clock;
input reset;
input stall;
 
output [31:0] alu_result;
output [31:0] dmem_addr;
output c_out;
output alu_multicycle_instr;
output alu_multicycle_instr_complete;
 
reg [31:0] alu_result;
reg [31:0] adder_out;
reg c_out;
reg alu_multicycle_instr;
reg [2:0] mul_counter;
 
reg [31:0] mul_result;
reg [31:0] mul_tmp1;
reg [31:0] a_in;
reg [31:0] b_in;
 
`ifdef MUL
// Force tools to infer pipelined Mult - allows use of code on devices other than Xilinx FPGAs
// Mult takes 5 execute cycles to complete at 32-bits
assign alu_multicycle_instr_complete = (mul_counter == 3'b011);
 
always@(posedge clock)
begin
if(reset)
begin
a_in <= 0;
b_in <= 0;
mul_tmp1 <= 0;
mul_result <= 0;
mul_counter <= 0;
end
else if (~stall)
begin // infer pipelined multiplier
a_in <= a;
b_in <= b;
mul_tmp1 <= a_in * b_in;
mul_result <= mul_tmp1;
if (mul_counter == 3)
mul_counter <= 0;
else if(alu_multicycle_instr)
mul_counter <= mul_counter + 1;
end
end
`endif
 
// dmem_addr comes straight from adder to by-pass ALU output MUX for timing
assign dmem_addr = adder_out;
 
// ALU result selection
`ifdef MUL
always@(a or b or c_in or fns or mul_result)
`else
always@(a or b or c_in or fns)
`endif
begin
{c_out, adder_out} <= a + b + c_in;
alu_multicycle_instr <= 0;
case(fns)
//`ALU_add: {c_out, alu_result} <= a + b + c_in;
`ALU_logic_or:
begin
alu_result <= a | b;
c_out <= 0;
end
`ALU_logic_and:
begin
alu_result <= a & b;
c_out <= 0;
end
`ALU_logic_xor:
begin
alu_result <= a ^ b;
c_out <= 0;
end
`ALU_sex8:
begin
alu_result <= {{(24){a[7]}}, a[7:0]};
c_out <= 0;
end
`ALU_sex16:
begin
alu_result <= {{(16){a[15]}}, a[15:0]};
c_out <= 0;
end
`ALU_shiftR_arth:
begin
alu_result <= {a[31], a[31:1]};
c_out <= a[0];
end
`ALU_shiftR_log:
begin
alu_result <= {1'b0, a[31:1]};
c_out <= a[0];
end
`ALU_shiftR_c:
begin
alu_result <= {c_in, a[31:1]};
c_out <= a[0];
end
`ALU_compare: {c_out, alu_result} <= a + b + c_in;
`ALU_compare_uns: {c_out, alu_result} <= a + b + c_in; // comparator determines MSB
`ifdef MUL
`ALU_multiply:
begin
alu_multicycle_instr <= 1;
alu_result <= mul_result;
c_out <= 0;
end
`endif
default: //`ALU_add -- moved to default for speed considerations
begin
{c_out, alu_result} <= a + b + c_in;
if(fns != `ALU_add) $display("ERROR! ALU set to illegal or unimplemented function!");
end
endcase
end // end always@
 
endmodule
 
/*********************************************
* Register File SRAM *
* Created from 2, 2-bank SRAMs *
* Async Reads, Sync Writes *
* Targets dual-port distributed Select RAM *
*********************************************/
module openfire_rf_sram(
clock,
read_addr, write_addr, data_in, we, // inputs
read_data_out, write_data_out); // outputs
 
parameter addr_width = 5; // 32 registers
 
input clock;
input [addr_width-1:0] read_addr;
input [addr_width-1:0] write_addr;
input [31:0] data_in;
input we;
 
output [31:0] read_data_out;
output [31:0] write_data_out;
 
reg [31:0] MEM [(1 << addr_width) - 1:0];
 
//synthesis translate_off
integer i;
initial
begin
for(i=0; i < ( 1 << addr_width); i=i+1)
MEM[i] <= 0;
end
//synthesis translate_on
 
always@(posedge clock)
begin
if (we)
MEM[write_addr] <= data_in;
end
 
assign read_data_out = MEM[read_addr];
assign write_data_out = MEM[write_addr];
 
endmodule
 
/trunk/rtl/vga_controlador.v
0,0 → 1,202
/* MODULE: openfire vga
DESCRIPTION: Contains vga controller (displays pictures from RAM)
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
`timescale 1ns / 1ps
`include "openfire_define.v"
 
//***************************************************************************
// VGA timming by Jason Stewart
// http://www.cs.unc.edu/~stewart/comp290-ghw/vga.html
//
// Filename: vga_controller.v
//
// Module for a simple vga controller. A "horizontal counter" counts pixels
// in a line, including the sync pulse, front porch, back porch, etc. Then,
// a "pulse generator" looks at the output of the counter and outputs a
// pulse of a given length starting at a given count. These are used to
// generate the sync pulse and the active video signal. Parameters for
// the counter and pulse generators appear below.
//
// The logic for vertical is similar. The main difference is that the
// vertical counter has a clock enable, which is used to make the vert
// counter count lines instead of pixels. Specifically, the hsync from
// the horizontal stage (which occurs once per line) creates a 1-cycle
// pulse for the vert counter clock enable, and thus the vert counter
// increments on every hsync.
//
// In general, you can play around with the start counts for the sync pulse
// and active signal. This basically increases/decreases the front and back
// porches, thereby moving the frame up/down or left/right on the screen.
//***************************************************************************
module vga_controller(cpu_clk, pixel_clk, reset,
hsync_n, vsync_n, red, green, blue,
ram_pointer, ram_data, req, rdy);
 
// The default parameters are for 800x600 @ 72 Hz (assuming a 50 MHz clock).
/* parameter N1 = 11; // number of counter bits HORIZONTAL
parameter HCOUNT = 1040; // total pixel count
parameter HS_START = 40; // start of hsync pulse
parameter HS_LEN = 120; // length of hsync pulse
parameter HA_START = 224; // start of active video
parameter HA_LEN = 800; // length of active video
 
parameter N2 = 10; // number of counter bits VERTICAL
parameter VCOUNT = 666; // total line count
parameter VS_START = 24; // start of vsync pulse
parameter VS_LEN = 6; // length of vsync pulse
parameter VA_START = 64; // start of active video
parameter VA_LEN = 600; // length of active video */
 
// For 640x480 @ 60 Hz, use the following (assuming a 25 MHz clock):
parameter N1 = 10;
parameter HCOUNT = 800;
parameter HS_START = 8;
parameter HS_LEN = 96;
parameter HA_START = 127;
parameter HA_LEN = 640;
parameter N2 = 10;
parameter VCOUNT = 525;
parameter VS_START = 2;
parameter VS_LEN = 2;
parameter VA_START = 24;
parameter VA_LEN = 480;
 
input cpu_clk; // clock de la cpu
input pixel_clk; // pixel clock
input reset;
 
output red; // color
output green;
output blue;
 
output [17:0] ram_pointer; // SRAM pointer (32 bit aligned)
input [31:0] ram_data; // data from SRAM
output req; // read request
input rdy; // SRAM data available
wire hsync, vsync; // --- sync signals are negated ----
wire hsync_n = ~hsync;
wire vsync_n = ~vsync;
 
wire htc, vtc, vce; // --------- Sync pulse stuff ----------
wire hactive, vactive;
wire [N1-1:0] hcnt;
wire [N2-1:0] vcnt;
 
// horizontal
counter_tc #(N1,HCOUNT) H_CNT(pixel_clk, reset, hcnt, htc);
pulse_gen #(N1,HS_START,HS_LEN) H_SYNC(pixel_clk, reset, hcnt, hsync);
pulse_gen #(N1,HA_START,HA_LEN) H_ACTIVE(pixel_clk, reset, hcnt, hactive);
 
// vertical
pulse_high_low V_CNT_CE(pixel_clk, reset, hsync, vce);
counter_tc_ce #(N2,VCOUNT) V_CNT(pixel_clk, reset, vce, vcnt, vtc);
pulse_gen #(N2,VS_START,VS_LEN) V_SYNC(pixel_clk, reset, vcnt, vsync);
pulse_gen #(N2,VA_START,VA_LEN) V_ACTIVE(pixel_clk, reset, vcnt, vactive);
 
// -------- memory and video parameters ------------
reg [17:0] ram_pointer; // memory pointer
reg req; // indica si hay que leer desde memoria
 
wire red; // output RGB signals (1 bpp)
wire green;
wire blue;
 
reg [9:0] pixels_red; // WORD = x RGB RGB RGB RGB RGB x RGB RGB RGB RGB RGB
reg [9:0] pixels_green; // 1 098 765 432 109 876 5 432 109 876 543 210
reg [9:0] pixels_blue; // 3 2 1
reg [3:0] contador_pixels; // pixel counter
reg leer; // video asks SRAM reader next word
reg leido; // SRAM reader notifies video the data is available
 
assign red = (hactive && vactive) && pixels_red[9]; // current pixel
assign green = (hactive && vactive) && pixels_green[9];
assign blue = (hactive && vactive) && pixels_blue[9];
// --------- retrieve 1 word (30 pixels) each time from SRAM ---------
always @(posedge cpu_clk)
begin
if(reset || !vactive) // reset or vertical retrace -> restart
begin
ram_pointer <= `LOCATION_VRAM; // video memory at the end of the SRAM (upper 120 Kbytes)
req <= 0;
leido <= 0;
end
else
begin
if(!leido && leer && !req) // request data
begin
req <= 1;
end
else if(!leido && leer && req && rdy)// data avaiable (registered at controller level)
begin
req <= 0;
leido <= 1;
end
else if(leido && !leer) // waiting next read
begin
leido <= 0;
ram_pointer <= ram_pointer + 1;
end
end
end
 
// ------- pintamos los pixels (al pixel clock) --------
wire first_pixel = (contador_pixels == 0);
wire threshold_pixel = (contador_pixels == 2);
wire last_pixel = (contador_pixels == 9);
 
always @(posedge pixel_clk)
begin
if(reset) // tras un reset -> pedir el 1er word a SRAM
begin
leer <= 1; // on startup request next data
contador_pixels <= 0;
pixels_red <= 10'b0;
pixels_green <= 10'b0;
pixels_blue <= 10'b0;
end
else if(hactive && vactive) // we are in visible area
begin
pixels_red <= first_pixel ? { ram_data[30], ram_data[27], ram_data[24], ram_data[21], ram_data[18], ram_data[14], ram_data[11], ram_data[8], ram_data[5], ram_data[2] } : { pixels_red[8:0], 1'bX };
pixels_green <= first_pixel ? { ram_data[29], ram_data[26], ram_data[23], ram_data[20], ram_data[17], ram_data[13], ram_data[10], ram_data[7], ram_data[4], ram_data[1] } : { pixels_green[8:0], 1'bX };
pixels_blue <= first_pixel ? { ram_data[28], ram_data[25], ram_data[22], ram_data[19], ram_data[16], ram_data[12], ram_data[9], ram_data[6], ram_data[3], ram_data[0] } : { pixels_blue[8:0], 1'bX };
if(threshold_pixel) leer <= 1; // fetch next word before current is processed
else if(leido) leer <= 0; // if already done, release flag
contador_pixels <= last_pixel ? 0 : contador_pixels + 1; // pixel counter
end
end
 
endmodule
 
/trunk/rtl/sp3dk_simulator.v
0,0 → 1,185
/* MODULE: openfire simulator
DESCRIPTION: Contains top-level simulator of the Openfire SOC
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
`timescale 1ns / 1ps
`include "openfire_define.v"
 
module sp3dk_simulator();
 
reg clk;
reg rst;
 
`ifdef SP3SK_USERIO
reg [7:0] switches;
reg [3:0] pushbuttons;
wire [7:0] leds;
wire [3:0] drivers_n;
wire [7:0] segments_n;
`endif
`ifdef UART1_ENABLE
wire tx1;
reg rx1;
`endif
`ifdef UART2_ENABLE
wire tx2;
reg rx2;
`endif
`ifdef SP3SK_PROM_DATA
reg prom_din;
wire prom_cclk;
wire prom_reset_n;
`endif
`ifdef SP3SK_SRAM
wire [17:0] ram_addr; // SRAM ADDR (256K @)
wire ram_oe_n; // OE_N shared by 2 IC
wire ram_we_n; // WE_N shared by 2 IC
wire [15:0] ram1_io; // I/O data port SRAM1
wire ram1_ce_n; // SRAM1 CE_N chip enable
wire ram1_ub_n; // UB_N upper byte select
wire ram1_lb_n; // LB_N lower byte select
wire [15:0] ram2_io; // I/O data port SRAM2
wire ram2_ce_n; // SRAM2 CE_N chip enable
wire ram2_ub_n; // UB_N upper byte select
wire ram2_lb_n; // LB_N lower byte select`endif
`endif
`ifdef SP3SK_VGA
wire r, g, b; // VGA components (1 bit per component)
wire hsync_n; // VGA hsync_n
wire vsync_n; // VGA vsync_n
`endif
// --- simulation statments ---
// Toggle clock every time unit
always #20 clk = ~clk;
 
`define TIMEOUT 1000000
initial begin
`ifdef SP3SK_USERIO
pushbuttons <= 0;
switches <= 0;
`endif
clk = 1;
rst = 1; // reset the processor (active high)
 
`ifdef UART1_ENABLE
rx1 = 1;
`endif
`ifdef UART2_ENABLE
rx2 = 1;
`endif
`ifdef SP3SK_PROM_DATA
prom_din = 1;
`endif
 
#70 rst = 0;
#`TIMEOUT;
//$finish; // finish after TIMEOUT
end
 
// ---------- device under test ----------
openfire_soc DUT(
`ifndef SP3SK_USERIO
.rst( rst ),
`endif
`ifdef SP3SK_USERIO
.leds( leds ),
.drivers_n( drivers_n ),
.segments_n( segments_n ),
.pushbuttons( {rst, pushbuttons[2:0]} ), // 3rd push button is the RESET
.switches( switches ),
`endif
`ifdef SP3SK_SRAM
.ram_addr(ram_addr), .ram_oe_n(ram_oe_n), .ram_we_n(ram_we_n),
.ram1_io(ram1_io), .ram1_ce_n(ram1_ce_n), .ram1_ub_n(ram1_ub_n), .ram1_lb_n(ram1_lb_n),
.ram2_io(ram2_io), .ram2_ce_n(ram2_ce_n), .ram2_ub_n(ram2_ub_n), .ram2_lb_n(ram2_lb_n),
`endif
`ifdef UART1_ENABLE
.tx1(tx1), .rx1(rx1),
`endif
`ifdef UART2_ENABLE
.tx2(tx2), .rx2(rx2),
`endif
`ifdef SP3SK_PROM_DATA
.prom_din(prom_din), .prom_cclk(prom_cclk), .prom_reset_n(prom_reset_n),
`endif
`ifdef SP3SK_VGA
.r(r), .g(g), .b(b),
.hsync_n(hsync_n), .vsync_n(vsync_n),
`endif
.clk_50mhz( clk )
);
 
`ifdef SP3SK_SRAM // used as a whole 256Kx32
SRAM256KX16 sram1( // 256K x 16 #1
.ce_n(ram1_ce_n), .we_n(ram_we_n), .oe_n(ram_oe_n),
.ub_n(ram1_ub_n), .lb_n(ram1_lb_n), .addr(ram_addr),
.io(ram1_io)
);
SRAM256KX16 sram2( // 256K x 16 #2
.ce_n(ram2_ce_n), .we_n(ram_we_n), .oe_n(ram_oe_n),
.ub_n(ram2_ub_n), .lb_n(ram2_lb_n), .addr(ram_addr),
.io(ram2_io)
);
 
// ---- load program/data in external SRAM -----------
`ifdef DEBUG_FILE_SRAM
reg [31:0] addr;
reg [31:0] memory[`MAX_SIMULATION_SRAM]; // temporary load here
reg [31:0] word;
 
initial begin
#1 // wait SRAM initialization
$display("Loading ROM file..."); // file should be rows of 32 bit hex dump (in ascii)
$readmemh(`DEBUG_FILE_SRAM, memory);
$display("File loaded");
 
$display("Populating SRAM...");
addr = 0;
word = memory[0];
while( addr < `MAX_SIMULATION_SRAM && word !== 32'bX ) // populate only until
begin // the end of valid data
word = memory[addr];
sram1.memh[addr] = word[31:24];
sram1.meml[addr] = word[23:16];
sram2.memh[addr] = word[15:8];
sram2.meml[addr] = word[7:0];
// $display(" SRAM[%x]=%x", addr, word);
addr = addr + 1;
end
$display("SRAM Populated with %d bytes", addr * 4);
end
`endif
 
`endif
 
endmodule
/trunk/rtl/sp3_devboard.ucf
0,0 → 1,124
#PACE: Start of Constraints generated by PACE
 
#PACE: Start of PACE I/O Pin Assignments
NET "b" LOC = "R11" ;
NET "clk_50mhz" LOC = "T9" ;
NET "drivers_n<0>" LOC = "D14" ;
NET "drivers_n<1>" LOC = "G14" ;
NET "drivers_n<2>" LOC = "F14" ;
NET "drivers_n<3>" LOC = "E13" ;
NET "g" LOC = "T12" ;
NET "hsync_n" LOC = "R9" ;
#NET "i2c_clk" LOC = "D6" ;
#NET "i2c_data" LOC = "C6" ;
NET "leds<0>" LOC = "K12" ;
NET "leds<1>" LOC = "P14" ;
NET "leds<2>" LOC = "L12" ;
NET "leds<3>" LOC = "N14" ;
NET "leds<4>" LOC = "P13" ;
NET "leds<5>" LOC = "N12" ;
NET "leds<6>" LOC = "P12" ;
NET "leds<7>" LOC = "P11" ;
NET "prom_cclk" LOC = "A14" ;
NET "prom_din" LOC = "M11" ;
NET "prom_reset_n" LOC = "N9" ;
NET "pushbuttons<0>" LOC = "M13" ;
NET "pushbuttons<1>" LOC = "M14" ;
NET "pushbuttons<2>" LOC = "L13" ;
NET "pushbuttons<3>" LOC = "L14" ;
NET "r" LOC = "R12" ;
NET "ram1_ce_n" LOC = "P7" ;
NET "ram1_io<0>" LOC = "N7" ;
NET "ram1_io<10>" LOC = "F2" ;
NET "ram1_io<11>" LOC = "H1" ;
NET "ram1_io<12>" LOC = "J2" ;
NET "ram1_io<13>" LOC = "L2" ;
NET "ram1_io<14>" LOC = "P1" ;
NET "ram1_io<15>" LOC = "R1" ;
NET "ram1_io<1>" LOC = "T8" ;
NET "ram1_io<2>" LOC = "R6" ;
NET "ram1_io<3>" LOC = "T5" ;
NET "ram1_io<4>" LOC = "R5" ;
NET "ram1_io<5>" LOC = "C2" ;
NET "ram1_io<6>" LOC = "C1" ;
NET "ram1_io<7>" LOC = "B1" ;
NET "ram1_io<8>" LOC = "D3" ;
NET "ram1_io<9>" LOC = "P8" ;
NET "ram1_lb_n" LOC = "P6" ;
NET "ram1_ub_n" LOC = "T4" ;
NET "ram2_ce_n" LOC = "N5" ;
NET "ram2_io<0>" LOC = "P2" ;
NET "ram2_io<10>" LOC = "G1" ;
NET "ram2_io<11>" LOC = "F5" ;
NET "ram2_io<12>" LOC = "C3" ;
NET "ram2_io<13>" LOC = "K2" ;
NET "ram2_io<14>" LOC = "M1" ;
NET "ram2_io<15>" LOC = "N1" ;
NET "ram2_io<1>" LOC = "N2" ;
NET "ram2_io<2>" LOC = "M2" ;
NET "ram2_io<3>" LOC = "K1" ;
NET "ram2_io<4>" LOC = "J1" ;
NET "ram2_io<5>" LOC = "G2" ;
NET "ram2_io<6>" LOC = "E1" ;
NET "ram2_io<7>" LOC = "D1" ;
NET "ram2_io<8>" LOC = "D2" ;
NET "ram2_io<9>" LOC = "E2" ;
NET "ram2_lb_n" LOC = "P5" ;
NET "ram2_ub_n" LOC = "R4" ;
NET "ram_addr<0>" LOC = "L5" ;
NET "ram_addr<10>" LOC = "G5" ;
NET "ram_addr<11>" LOC = "H3" ;
NET "ram_addr<12>" LOC = "H4" ;
NET "ram_addr<13>" LOC = "J4" ;
NET "ram_addr<14>" LOC = "J3" ;
NET "ram_addr<15>" LOC = "K3" ;
NET "ram_addr<16>" LOC = "K5" ;
NET "ram_addr<17>" LOC = "L3" ;
NET "ram_addr<1>" LOC = "N3" ;
NET "ram_addr<2>" LOC = "M4" ;
NET "ram_addr<3>" LOC = "M3" ;
NET "ram_addr<4>" LOC = "L4" ;
NET "ram_addr<5>" LOC = "G4" ;
NET "ram_addr<6>" LOC = "F3" ;
NET "ram_addr<7>" LOC = "F4" ;
NET "ram_addr<8>" LOC = "E3" ;
NET "ram_addr<9>" LOC = "E4" ;
NET "ram_oe_n" LOC = "K4" ;
NET "ram_we_n" LOC = "G3" ;
NET "rx1" LOC = "T13" ;
#NET "rx2" LOC = "N10" ;
#NET "rx_ultrasonidos" LOC = "C5" ;
NET "segments_n<0>" LOC = "P16" ;
NET "segments_n<1>" LOC = "N16" ;
NET "segments_n<2>" LOC = "F13" ;
NET "segments_n<3>" LOC = "R16" ;
NET "segments_n<4>" LOC = "P15" ;
NET "segments_n<5>" LOC = "N15" ;
NET "segments_n<6>" LOC = "G13" ;
NET "segments_n<7>" LOC = "E14" ;
#NET "spi_clk" LOC = "E7" ;
#NET "spi_cs_1" LOC = "C8" ;
#NET "spi_cs_2" LOC = "D8" ;
#NET "spi_cs_3" LOC = "C9" ;
#NET "spi_cs_4" LOC = "D10" ;
#NET "spi_datain" LOC = "C7" ;
#NET "spi_dataout" LOC = "D7" ;
NET "switches<0>" LOC = "F12" ;
NET "switches<1>" LOC = "G12" ;
NET "switches<2>" LOC = "H14" ;
NET "switches<3>" LOC = "H13" ;
NET "switches<4>" LOC = "J14" ;
NET "switches<5>" LOC = "J13" ;
NET "switches<6>" LOC = "K14" ;
NET "switches<7>" LOC = "K13" ;
NET "tx1" LOC = "R13" ;
#NET "tx2" LOC = "T14" ;
#NET "tx_ultrasonidos_n" LOC = "D5" ;
#NET "tx_ultrasonidos_p" LOC = "E6" ;
NET "vsync_n" LOC = "T10" ;
 
#PACE: Start of PACE Area Constraints
 
#PACE: Start of PACE Prohibit Constraints
 
#PACE: End of Constraints generated by PACE
/trunk/rtl/uart_rx.v
0,0 → 1,136
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2004 Xilinx, Inc.
// All Rights Reserved
////////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 1.01
// \ \ Filename: uart_rx.v
// / / Date Last Modified: 08/04/2004
// /___/ /\ Date Created: 10/16/2002
// \ \ / \
// \___\/\___\
//
//Device: Xilinx
//Purpose:
// UART Receiver with integral 16 byte FIFO buffer
// 8 bit, no parity, 1 stop bit
//Reference:
// None
//Revision History:
// Rev 1.00 - kc - Start of design entry in VHDL, 10/16/2002.
// Rev 1.01 - sus - Converted to verilog, 08/04/2004.
////////////////////////////////////////////////////////////////////////////////
// Contact: e-mail picoblaze@xilinx.com
//////////////////////////////////////////////////////////////////////////////////
//
// Disclaimer:
// LIMITED WARRANTY AND DISCLAIMER. These designs are
// provided to you "as is". Xilinx and its licensors make and you
// receive no warranties or conditions, express, implied,
// statutory or otherwise, and Xilinx specifically disclaims any
// implied warranties of merchantability, non-infringement, or
// fitness for a particular purpose. Xilinx does not warrant that
// the functions contained in these designs will meet your
// requirements, or that the operation of these designs will be
// uninterrupted or error free, or that defects in the Designs
// will be corrected. Furthermore, Xilinx does not warrant or
// make any representations regarding use or the results of the
// use of the designs in terms of correctness, accuracy,
// reliability, or otherwise.
//
// LIMITATION OF LIABILITY. In no event will Xilinx or its
// licensors be liable for any loss of data, lost profits, cost
// or procurement of substitute goods or services, or for any
// special, incidental, consequential, or indirect damages
// arising from the use or operation of the designs or
// accompanying documentation, however caused and on any theory
// of liability. This limitation will apply even if Xilinx
// has been advised of the possibility of such damage. This
// limitation shall apply not-withstanding the failure of the
// essential purpose of any limited remedies herein.
//////////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1ps
module uart_rx
( serial_in,
data_out,
read_buffer,
reset_buffer,
en_16_x_baud,
buffer_data_present,
buffer_full,
buffer_half_full,
clk);
 
input serial_in;
output[7:0] data_out;
input read_buffer;
input reset_buffer;
input en_16_x_baud;
output buffer_data_present;
output buffer_full;
output buffer_half_full;
input clk;
 
wire serial_in;
wire [7:0] data_out;
wire read_buffer;
wire reset_buffer;
wire en_16_x_baud;
wire buffer_data_present;
wire buffer_full;
wire buffer_half_full;
wire clk;
 
 
//----------------------------------------------------------------------------------
//
// Start of Main UART_RX
//
//
//----------------------------------------------------------------------------------
//
// Signals used in UART_RX
//
//----------------------------------------------------------------------------------
//
wire [7:0] uart_data_out;
wire fifo_write;
//
//----------------------------------------------------------------------------------
//
// Start of UART_RX circuit description
//
//----------------------------------------------------------------------------------
//
 
// 8 to 1 multiplexer to convert parallel data to serial
kcuart_rx kcuart
( .serial_in(serial_in),
.data_out(uart_data_out),
.data_strobe(fifo_write),
.en_16_x_baud(en_16_x_baud),
.clk(clk));
 
bbfifo_16x8 buf_0
( .data_in(uart_data_out),
.data_out(data_out),
.reset(reset_buffer),
.write(fifo_write),
.read(read_buffer),
.full(buffer_full),
.half_full(buffer_half_full),
.data_present(buffer_data_present),
.clk(clk));
 
endmodule
 
//----------------------------------------------------------------------------------
//
// END OF FILE uart_rx.v
//
//----------------------------------------------------------------------------------
 
/trunk/rtl/openfire_template_bootram.v
0,0 → 1,154
/* MODULE: openfire bootram
DESCRIPTION: Contains BRAM instanties loaded with the boot program
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
`timescale 1ns / 1ps
 
// bootram is an internal 2048 x 32 bit dualport ram inside
// FPGA to let CPU boot without external resources
// this RAM is shared by program and data
 
module openfire_bootram(
rst, clk, ins_addr, ins_output,
data_we, data_addr, data_input, data_output,
data_sel
);
 
input rst; // reset sincrono
input clk; // reloj
input [10:0] ins_addr; // 11 bit INS-ADDR
output [31:0] ins_output; // 32 bit INSTRUCTION
input data_we; // activa escritura DATA
input [10:0] data_addr; // 11 bit DATA-ADDR
input [31:0] data_input; // 32 bit DATA-IN
output [31:0] data_output; // 32 bit DATA-OUT
input [3:0] data_sel; // byte selector
 
// ------------ block ram instances -------------
RAMB16_S9_S9 MEM3(
.DOA(ins_output[31:24]), // Port A ins_output
.DOB(data_output[31:24]), // Port B data_output
.DOPA( ), // Port A 1-bit Parity Output NO
.DOPB( ), // Port B 1-bit Parity Output NO
.ADDRA(ins_addr[10:0]), // Port A 11-bit Address Input
.ADDRB(data_addr[10:0]), // Port B 11-bit Address Input
.CLKA(clk), // Port A Clock
.CLKB(clk), // Port B Clock
.DIA(8'b0), // Port A 8-bit Data Input NO
.DIB(data_input[31:24]), // Port B 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.DIPB(1'b0), // Port-B 1-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRA(rst), // Port A Synchronous Set/Reset Input
.SSRB(rst), // Port B Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input NO
.WEB(data_we & data_sel[3]) // Port B Write Enable Input
);
 
RAMB16_S9_S9 MEM2(
.DOA(ins_output[23:16]), // Port A ins_output
.DOB(data_output[23:16]), // Port B data_output
.DOPA( ), // Port A 1-bit Parity Output NO
.DOPB( ), // Port B 1-bit Parity Output NO
.ADDRA(ins_addr[10:0]), // Port A 11-bit Address Input
.ADDRB(data_addr[10:0]), // Port B 11-bit Address Input
.CLKA(clk), // Port A Clock
.CLKB(clk), // Port B Clock
.DIA(8'b0), // Port A 8-bit Data Input NO
.DIB(data_input[23:16]), // Port B 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.DIPB(1'b0), // Port-B 1-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRA(rst), // Port A Synchronous Set/Reset Input
.SSRB(rst), // Port B Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input NO
.WEB(data_we & data_sel[2]) // Port B Write Enable Input
);
 
RAMB16_S9_S9 MEM1(
.DOA(ins_output[15:8]), // Port A ins_output
.DOB(data_output[15:8]), // Port B data_output
.DOPA( ), // Port A 1-bit Parity Output NO
.DOPB( ), // Port B 1-bit Parity Output NO
.ADDRA(ins_addr[10:0]), // Port A 11-bit Address Input
.ADDRB(data_addr[10:0]), // Port B 11-bit Address Input
.CLKA(clk), // Port A Clock
.CLKB(clk), // Port B Clock
.DIA(8'b0), // Port A 8-bit Data Input NO
.DIB(data_input[15:8]), // Port B 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.DIPB(1'b0), // Port-B 1-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRA(rst), // Port A Synchronous Set/Reset Input
.SSRB(rst), // Port B Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input NO
.WEB(data_we & data_sel[1]) // Port B Write Enable Input
);
 
RAMB16_S9_S9 MEM0(
.DOA(ins_output[7:0]), // Port A ins_output
.DOB(data_output[7:0]), // Port B data_output
.DOPA( ), // Port A 1-bit Parity Output NO
.DOPB( ), // Port B 1-bit Parity Output NO
.ADDRA(ins_addr[10:0]), // Port A 11-bit Address Input
.ADDRB(data_addr[10:0]), // Port B 11-bit Address Input
.CLKA(clk), // Port A Clock
.CLKB(clk), // Port B Clock
.DIA(8'b0), // Port A 8-bit Data Input NO
.DIB(data_input[7:0]), // Port B 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.DIPB(1'b0), // Port-B 1-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRA(rst), // Port A Synchronous Set/Reset Input
.SSRB(rst), // Port B Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input NO
.WEB(data_we & data_sel[0]) // Port B Write Enable Input
);
 
// ---------------- memory content -----------------
// this macro is replaced by a series of
// defparam MEMx.INIT_yy = 256'h{hexadecimal bytes};
// as per BIN file provided to bin2bram
//
// also de MEMx.INIT_A/B and MEMx.SRVAL_A/B are initialized
// with the 1st DWORD in the BIN file to be available at startup/reset
// $DUMP_INIT_RAM
 
// blockram configuration and parity bits are left empty
// so default values are used
 
endmodule
/trunk/rtl/vga_parts.v
0,0 → 1,132
`timescale 1ns / 1ps
 
// by Jason Stewart
// http://www.cs.unc.edu/~stewart/comp290-ghw/vga.html
 
//********************************************************
// Filename: counter_tc.v
//
// Parameterized counter module with sync reset
// and terminal count.
//********************************************************
module counter_tc(clk, reset, q, tc);
parameter N = 8; // number of bits
parameter TCNT = 256; // desired terminal count
 
input clk, reset;
output tc;
reg tc;
output [N-1:0] q;
reg [N-1:0] q;
 
// check for one less than what you want ...
wire tc_tmp;
assign tc_tmp = (q==TCNT-2);
 
// ... then register (causes 1-cycle delay)
always @(posedge clk)
if (reset) tc <= 0;
else tc <= tc_tmp;
 
// counter
always @(posedge clk)
if (reset) q <= 0;
else
begin
if (tc) q <= 0;
else q <= q + 1;
end
endmodule
 
//********************************************************
// Filename: counter_tc_ce.v
//
// Parameterized counter module with sync reset,
// clock enable, and terminal count.
//********************************************************
module counter_tc_ce(clk, reset, enable, q, tc);
parameter N = 8; // number of bits
parameter TCNT = 256; // desired terminal count
 
input clk, reset, enable;
output tc;
reg tc;
output [N-1:0] q;
reg [N-1:0] q;
 
// check for one less than what you want ...
wire tc_tmp;
assign tc_tmp = (q==TCNT-2);
 
// ... then register (causes 1-cycle delay)
always @(posedge clk)
if (reset) tc <= 0;
else tc <= tc_tmp;
 
// counter
always @(posedge clk)
if (reset) q <= 0;
else if (enable)
begin
if (tc) q <= 0;
else q <= q + 1;
end
endmodule
 
//********************************************************
// Filename: pulse_gen.v
//
// Parameterized pulse_gen module with sync reset.
// The output is registered.
//
// Basically, just a comparator that outputs a one
// when the count falls between two values and a
// zero otherwise. START + LENGTH should fall within
// the counter range (plus one). That is, this module
// doesn't deal with counter rollover.
//********************************************************
module pulse_gen(clk,reset,count,pulse);
parameter N = 8; // number of counter bits
parameter START = 0; // start count
parameter LENGTH = 1; // pulse length (number of cycles)
 
input clk, reset;
input [N-1:0] count;
output pulse;
reg pulse;
 
always @(posedge clk)
if (reset) pulse <= 0;
else
begin
if ((count>=START)&&(count<START+LENGTH)) pulse <= 1;
else pulse <= 0;
end
endmodule
 
//********************************************************
// Filename: pulse_high_low.v
//
// Outputs a 1-cycle pulse when din transitions from
// high to low. Sync reset. Output is registered.
//********************************************************
module pulse_high_low(clk,reset,din,pulse);
input clk, reset, din;
output pulse;
reg pulse;
reg din_reg;
 
// 1-cycle delay reg
always @(posedge clk)
if (reset) din_reg <= 0;
else din_reg <= din;
 
// check for old value high, current value low
always @(posedge clk)
if (reset) pulse <= 0;
else
begin
if (~din && din_reg) pulse <= 1;
else pulse <= 0;
end
endmodule
/trunk/rtl/uart_tx.v
0,0 → 1,135
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2004 Xilinx, Inc.
// All Rights Reserved
////////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 1.01
// \ \ Filename: uart_tx.v
// / / Date Last Modified: 08/04/2004
// /___/ /\ Date Created: 10/14/2002
// \ \ / \
// \___\/\___\
//
//Device: Xilinx
//Purpose:
// UART Transmitter with integral 16 byte FIFO buffer
// 8 bit, no parity, 1 stop bit
//Reference:
// None
//Revision History:
// Rev 1.00 - kc - Start of design entry in VHDL, 10/14/2002.
// Rev 1.01 - sus - Converted to verilog, 08/04/2004.
////////////////////////////////////////////////////////////////////////////////
// Contact: e-mail picoblaze@xilinx.com
//////////////////////////////////////////////////////////////////////////////////
//
// Disclaimer:
// LIMITED WARRANTY AND DISCLAIMER. These designs are
// provided to you "as is". Xilinx and its licensors make and you
// receive no warranties or conditions, express, implied,
// statutory or otherwise, and Xilinx specifically disclaims any
// implied warranties of merchantability, non-infringement, or
// fitness for a particular purpose. Xilinx does not warrant that
// the functions contained in these designs will meet your
// requirements, or that the operation of these designs will be
// uninterrupted or error free, or that defects in the Designs
// will be corrected. Furthermore, Xilinx does not warrant or
// make any representations regarding use or the results of the
// use of the designs in terms of correctness, accuracy,
// reliability, or otherwise.
//
// LIMITATION OF LIABILITY. In no event will Xilinx or its
// licensors be liable for any loss of data, lost profits, cost
// or procurement of substitute goods or services, or for any
// special, incidental, consequential, or indirect damages
// arising from the use or operation of the designs or
// accompanying documentation, however caused and on any theory
// of liability. This limitation will apply even if Xilinx
// has been advised of the possibility of such damage. This
// limitation shall apply not-withstanding the failure of the
// essential purpose of any limited remedies herein.
//////////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1ps
 
module uart_tx
( data_in,
write_buffer,
reset_buffer,
en_16_x_baud,
serial_out,
buffer_full,
buffer_half_full,
clk);
 
input[7:0] data_in;
input write_buffer;
input reset_buffer;
input en_16_x_baud;
output serial_out;
output buffer_full;
output buffer_half_full;
input clk;
 
wire [7:0] data_in;
wire write_buffer;
wire reset_buffer;
wire en_16_x_baud;
wire serial_out;
wire buffer_full;
wire buffer_half_full;
wire clk;
 
//----------------------------------------------------------------------------------
//
// Start of UART_TX
//
//
//----------------------------------------------------------------------------------
//
// Signals used in UART_TX
//
//----------------------------------------------------------------------------------
//
wire [7:0] fifo_data_out;
wire fifo_data_present;
wire fifo_read;
//
//----------------------------------------------------------------------------------
//
// Start of UART_TX circuit description
//
//----------------------------------------------------------------------------------
//
 
// 8 to 1 multiplexer to convert parallel data to serial
kcuart_tx kcuart
( .data_in(fifo_data_out),
.send_character(fifo_data_present),
.en_16_x_baud(en_16_x_baud),
.serial_out(serial_out),
.Tx_complete(fifo_read),
.clk(clk));
 
bbfifo_16x8 buf_0
( .data_in(data_in),
.data_out(fifo_data_out),
.reset(reset_buffer),
.write(write_buffer),
.read(fifo_read),
.full(buffer_full),
.half_full(buffer_half_full),
.data_present(fifo_data_present),
.clk(clk));
 
endmodule
 
//----------------------------------------------------------------------------------
//
// END OF FILE UART_TX.V
//
//----------------------------------------------------------------------------------
 
 
/trunk/rtl/openfire_execute.v
0,0 → 1,386
/* MODULE: openfire_execute
 
DESCRIPTION: The execute module instantiates the alu and comparator and
updates the Machine Status Register (MSR). This module produces a status
signal, instr_complete, when the currently executing instruction is finished.
 
TO DO:
- Add interrupt handling
- Add exception handling
- Complete MSR
- Add all other special registers: EAR, ESR, ESS
- Add OPB interface
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug and CMP bug for case when both rA and rB are negative.
 
Revision 0.4 27/03/2007 Antonio J. Anton
Memory handshaking protocol
Removed memory read/write alignment code
Interrupt handling
Exception handling
MSR register handling
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
`include "openfire_define.v"
 
module openfire_execute (
`ifdef ENABLE_MSR_BIP
update_msr_bip, value_msr_bip,
`endif
`ifdef ENABLE_INTERRUPTS
interrupt, int_ip, int_dc, set_msr_ie,
`endif
`ifdef ENABLE_MSR_OPCODES
rS_update,
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
opcode_exception,
`endif
`ifdef ENABLE_EXCEPTIONS
reset_msr_eip,
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
dmem_alignment_exception,
`endif
clock, reset, stall, // top level
immediate, pc_exe, alu_inputA_sel, alu_inputB_sel, // inputs
alu_inputC_sel, alu_fns_sel, comparator_fns_sel,
we_load, we_store, regA,
regB, regD, update_carry, branch_instr,
alu_result, pc_branch, branch_taken, // outputs
we_regfile, dmem_addr,
dmem_data_out, instr_complete, dmem_done,
dmem_we, dmem_re
);
// From top level -- all active high unless otherwise noted
input stall;
input reset;
input clock;
 
// From DECODE module
input [31:0] immediate;
input [`A_SPACE+1:0] pc_exe; // pc for use by EXECUTE
input [2:0] alu_inputA_sel;
input [1:0] alu_inputB_sel;
input [1:0] alu_inputC_sel;
input [3:0] alu_fns_sel;
input [2:0] comparator_fns_sel;
input we_load; // write_en for regfile on Load
input we_store; // we on DMEM on Store
input update_carry;
input branch_instr;
input dmem_done;
output dmem_re;
output dmem_we;
`ifdef ENABLE_MSR_BIP
input update_msr_bip;
input value_msr_bip;
`endif
`ifdef ENABLE_INTERRUPTS
input interrupt;
output int_ip;
input int_dc;
input set_msr_ie;
`endif
`ifdef ENABLE_MSR_OPCODES
input rS_update;
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
input opcode_exception;
`endif
`ifdef ENABLE_EXCEPTIONS
input reset_msr_eip;
output insert_exception;
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
input dmem_alignment_exception;
`endif
 
// From REGFILE
input [31:0] regA;
input [31:0] regB;
input [31:0] regD;
 
output [31:0] alu_result;
output [`A_SPACE+1:0] pc_branch;
output branch_taken;
output we_regfile; // we for load and alu
output [31:0] dmem_addr;
output [31:0] dmem_data_out;
output instr_complete; // status of execution, active high
 
// register all outputs EXCEPT:
// - branch_taken and pc_branch -- registered in FETCH
// - alu_result -- REGFILE registers
// - dmem_addr -- DMEM registers
// - instr_complete -- needed before rise of clock by PIPLINE_CTRL
assign dmem_data_out = regD;
 
// internal registers
reg [31:0] MSR; // **TODO** Working: C, BIP, IE
reg [31:0] alu_a_input;
reg [31:0] alu_b_input;
reg alu_c_input;
reg MSB_signed_compare;
 
wire alu_multicycle_instr;
wire alu_multicycle_instr_complete;
wire multicycle_instr;
wire multicycle_instr_complete;
wire c_out;
wire compare_out;
wire [31:0] alu_out_internal;
wire [31:0] extended_pc; // PC with leading zeros addded
 
`ifdef ENABLE_EXCEPTIONS
reg insert_exception; // to ask DECODE to insert "brali r17,0x20"
wire exception = // 1 if any exception happened
`ifdef ENABLE_ALIGNMENT_EXCEPTION
dmem_alignment_exception |
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
opcode_exception |
`endif
0;
`endif
 
`ifdef ENABLE_INTERRUPTS
// this code is to signal an interrupt when interrupts are enabled (MSR[IE]=1)
reg int_requested;
always @(interrupt or MSR[`MSR_IE]) // if interrupt == 1, then raise a request for
begin // clear the request based on clear_interrupt
if(interrupt && MSR[`MSR_IE]) int_requested <= 1;
else if(!MSR[`MSR_IE]) int_requested <= 0;
end
 
reg int_ip; // interrupt in progress
wire can_interrupt = // cpu can be interrupted if...
`ifdef ENABLE_EXCEPTION
~MSR[`MSR_EIP] & // no Exception in Progress
`endif
`ifdef ENABLE_MSR_BIP
~MSR[`MSR_BIP] & ( // no Break in Progress
`endif
~int_ip | set_msr_ie // not interrupt in progress
`ifdef ENABLE_MSR_BIP // and interrupts are enabled
)
`endif
;
`endif
 
assign branch_taken = branch_instr ? compare_out : 0;
assign pc_branch = alu_out_internal[`A_SPACE+1:0]; // ALU calculates next instr address
 
// instr_complete is always high EXCEPT for optional MUL (alu_multicycle_instr)
// all other instructions currently implemented are single-cycle execution except
// load / store that are multicycle (controlled by dmem_done)
// also re/we enable are only valid if EXECUTE is not stalled
assign dmem_we = we_store & ~stall;
assign dmem_re = we_load & ~stall;
 
assign memory_instr = we_load | we_store;
assign memory_instr_complete = memory_instr & dmem_done;
 
assign multicycle_instr = memory_instr | alu_multicycle_instr;
assign multicycle_instr_complete = memory_instr_complete | alu_multicycle_instr_complete;
 
assign instr_complete = ~multicycle_instr | multicycle_instr_complete;
assign we_regfile = (we_load & dmem_done) | alu_multicycle_instr_complete;
 
// for CMP/CMPU
// use comparator output for CMPU
// use ALU output for CMP -- signed comparison result is a function of input signs and output sign
assign alu_result[31] = (alu_fns_sel == `ALU_compare_uns) ? compare_out :
(alu_fns_sel == `ALU_compare) ? MSB_signed_compare :
alu_out_internal[31];
assign alu_result[30:0] = alu_out_internal[30:0];
 
always@(regA[31] or regB[31] or alu_out_internal[31])
begin
case ({regB[31], regA[31]}) // look at signs of input numbers
2'b00: MSB_signed_compare <= alu_out_internal[31]; // both inputs positive
2'b01: MSB_signed_compare <= 0; // A is negative, B is positive => B is greater
2'b10: MSB_signed_compare <= 1; // B is negative, A is positive => A is greater
2'b11: MSB_signed_compare <= alu_out_internal[31]; // both inputs negative
endcase
end
 
// extend PC to datapath width to store in Reg File
assign extended_pc[31:`A_SPACE+2] = 0;
assign extended_pc[`A_SPACE+1:0] = pc_exe;
 
// Stateful logic to handle multi-cycle instructions
always@(posedge clock)
begin
if(reset)
begin
MSR[`MSR_C] <= 0; // Carry
`ifdef ENABLE_INTERRUPTS
int_ip <= 0;
MSR[`MSR_IE] <= 1; // Interrupt Enable
`endif
`ifdef ENABLE_EXCEPTIONS
insert_exception <= 0;
MSR[`MSR_E_Ena] <= 1; // Enable Exceptions
MSR[`MSR_EIP] <= 0; // Exception in Progress
`endif
`ifdef ENABLE_MSR_BIP
MSR[`MSR_BIP`] <= 0; // Break In Progress
`endif
end
else if (~stall)
begin
// Update MSR[BIP] due to BREAK / RTBD
`ifdef ENABLE_MSR_BIP
if(update_msr_bip) MSR[`MSR_BIP] <= value_msr_bip;
`endif
`ifdef ENABLE_INTERRUPTS
if(int_requested & can_interrupt) // interrupt requested and cpu can be interrupted?
begin
MSR[`MSR_IE] <= 0; // disable further interrupts
int_ip <= 1; // ask DECODE to insert "brali r14,0x10" asap
end
else if(int_ip & int_dc) // if DECODE completed the instruction insert
int_ip <= 0; // finish interrupt in progress
if(set_msr_ie) MSR[`MSR_IE] <= 1; // decode asks to enable interrupts again
`endif
`ifdef ENABLE_EXCEPTIONS
/* TODO: exceptions handling ---
r17 <- PC
PC <- 0x20
MSR[EE] <- 0
MSR[EIP] <- 1
ESR[DS] <- exception in delay slot
ESR[EC] <- exception specific value
ESR[ESS] <- exception specific value
EAR <- exception specific value
FSR <- exception specific value
*/
if(reset_msr_eip) // return from an exception handler
begin
MSR[`MSR_EIP] <= 0; // disable EIP flag due to rted opcode
MSR[`MSR_E_Ena] <= 1; // enable exceptions agains
// ESR <- 0 // reset exception cause
end
`endif
`ifdef ENABLE_MSR_OPCODES
if(rS_update) MSR <= regA; // mts instruction
`endif
// Update Carry Bit in Status Register
if ((alu_fns_sel == `ALU_add) & update_carry)
MSR[`MSR_C] <= c_out;
if ((alu_fns_sel == `ALU_shiftR_arth) | (alu_fns_sel == `ALU_shiftR_log) |
(alu_fns_sel == `ALU_shiftR_c))
MSR[`MSR_C] <= regA[0];
`ifdef DEBUG_EXECUTE
$display("EXECUTE: pc_exe=%x", pc_exe);
`endif
end // end elseif (~stall)
end // always@
 
/**************************
* Module input selectors *
**************************/
always@(
`ifdef ENABLE_MSR_OPCODES
MSR or
`endif
alu_inputA_sel or extended_pc or regA
)
begin
case(alu_inputA_sel)
`aluA_ra: alu_a_input <= regA;
`aluA_ra_bar: alu_a_input <= ~regA;
`aluA_pc: alu_a_input <= extended_pc;
`aluA_zero: alu_a_input <= 0;
`ifdef ENABLE_MSR_OPCODES
`aluA_msr: alu_a_input <= MSR; // msr instruction feed to regfile via ALU
`endif
endcase
end // always @ ALU_input_A
 
always@(alu_inputB_sel or immediate or regB)
begin
case(alu_inputB_sel)
`aluB_rb: alu_b_input <= regB;
`aluB_imm: alu_b_input <= immediate;
`aluB_rb_bar: alu_b_input <= ~regB;
`aluB_imm_bar: alu_b_input <= ~immediate;
endcase
end // always @ ALU_input_B
 
always@(alu_inputC_sel or MSR)
begin
case(alu_inputC_sel)
`aluC_zero: alu_c_input <= 1'b0;
`aluC_one: alu_c_input <= 1'b1;
`aluC_carry: alu_c_input <= MSR[`MSR_C];
default:
begin // for simulation
$display("ERROR! Illegal ALU Input Selection! PC %x", pc_exe);
alu_c_input <= 1'b0;
end
endcase
end // always @ ALU_input_C
 
// Instantiate ALU and comparator
openfire_alu ALU0 (
.clock(clock),
.reset(reset),
.stall(stall),
.a(alu_a_input),
.b(alu_b_input),
.c_in(alu_c_input),
.fns(alu_fns_sel),
.alu_result(alu_out_internal),
.c_out(c_out),
.alu_multicycle_instr(alu_multicycle_instr),
.dmem_addr(dmem_addr),
.alu_multicycle_instr_complete(alu_multicycle_instr_complete)
);
// comparator used only for branches (and optional CMPU instruction)
// DECODE unit forces COMPARE output high for unconditional branchs by selecting a 1 output
// with comparator_fns_sel
openfire_compare CMP0 (
.in0(regA),
.in1(regB),
.out(compare_out),
.fns(comparator_fns_sel)
);
 
endmodule
/trunk/rtl/prom_reader_shift_cmp_serial.v
0,0 → 1,143
// MODULE : shift_compare_serial.v
// AUTHOR : Stephan Neuhold
// VERSION : v1.00
//
// REVISION HISTORY:
// -----------------
// No revisions
//
// FUNCTION DESCRIPTION:
// ---------------------
// This module provides the shifting in of data
// and comparing that data to the synchronisation
// pattern. Once the synchronisation pattern has
// been found, the last eight bits of data
// shifted in are presented.
//
// The shift register and comparator are
// automatically scaled to the correct length
// using the "length" generic.
 
`timescale 1 ns / 1 ns
 
module shift_compare_serial( clock,
reset,
enable,
din,
b,
eq,
din_shifted);
 
parameter length = 5;
parameter frequency = 50;
input clock;
input reset;
input enable;
input din;
input [(2**length) - 1:0] b;
output eq;
output reg [7:0] din_shifted;
reg [(2**length) - 1:0] b_swapped;
wire [(2**length):0] r;
wire [(2**length) - 1:0] q;
wire [(2**length) - 1:0] a;
wire GND;
integer i;
integer j;
 
//***************************************************
//* This process swaps the bits in the data byte.
//* This is done to present the data in the format
//* that it is entered in the PROM file.
//***************************************************
always @ (a)
for (i = 0; i < 8; i = i + 1)
begin
din_shifted[i] <= a[((2**length) - 1) - i];
end
 
//*******************************************************
//* This process swaps the bits of every byte of the
//* synchronisation pattern. This is done so that
//* data read in from the PROM can be directly
//* compared. Data from the PROM is read with all
//* bits of every byte swapped.
//* e.g.
//* If the data in the PROM is 28h then this is read in
//* the following way:
//* 00010100
//*******************************************************
always @ (b)
for (i = 0; i < 2**length / 8; i = i + 1)
begin
for (j = 0; j < 8; j = j + 1)
begin
b_swapped[(8 * i) + j] <= b[7 + (8 * i) - j];
end
end
 
 
//***********************************************
//* This is the first FF of the shift register.
//* It needs to be seperated from the rest
//* since it has a different input.
//***********************************************
assign GND = 1'b0;
assign r[0] = 1'b1;
 
FDRE Data_Shifter_0_Serial(
.C(clock),
.D(din),
.CE(enable),
.R(reset),
.Q(a[0])
);
 
//***************************************************
//* This loop generates as many registers needed
//* based on the length of the synchronisation
//* word.
//***************************************************
genvar x;
generate
for (x = 1; x < 2**length; x = x + 1)
begin: Shifter_Serial
FDRE Data_Shifter_Serial(
.C(clock),
.D(a[x - 1]),
.CE(enable),
.R(reset),
.Q(a[x])
);
end
endgenerate
 
//***********************************************
//* This loop generates as many LUTs and MUXCYs
//* as needed based on the length of the
//* synchronisation word.
//***********************************************
genvar y;
generate
for (y = 0; y < 2**length; y = y + 1)
begin: Comparator_Serial
my_LUT2 Comparator_LUTs_Serial(
.I0(a[y]),
.I1(b_swapped[y]),
.O(q[y])
);
MUXCY Comparator_MUXs_Serial(
.DI(GND),
.CI(r[y]),
.S(q[y]),
.O(r[y + 1])
);
end
endgenerate
 
assign eq = r[(2**length)];
 
endmodule
/trunk/rtl/prom_reader_clock_mgmt.v
0,0 → 1,82
// MODULE : clock_management.v
// AUTHOR : Stephan Neuhold
// VERSION : v1.00
//
// REVISION HISTORY:
// -----------------
// No revisions
//
// FUNCTION DESCRIPTION:
// ---------------------
// This module generates an enable signal for
// the shift register and comparator. It also
// generates the clock signal that is connected
// to the PROM.
// The enable and clock signals are generated
// based on the "frequency" generic entered for
// the system clock.
// The clock signal is only generated at the
// appropriate times. All other states the clock
// signal is kept at a logic high. The PROMs
// address counter only increments on a rising
// edge of this clock.
 
`timescale 1 ns / 1 ns
 
module clock_management( clock,
enable,
read_enable,
cclk);
input clock;
input enable;
output reg read_enable;
output cclk;
parameter length = 5;
parameter frequency = 50;
wire [3:0] SRL_length = (frequency / 20) - 1;
defparam Divider0.INIT = 16'h0001;
 
reg cclk_int = 1'b1;
wire enable_cclk;
 
//***************************************************
//* The length of the SRL16 is based on the system
//* clock frequency entered. This frequency is then
//* "divided" down to approximately 10MHz.
//***************************************************
SRL16 Divider0(
.CLK(clock),
.D(enable_cclk),
.A0(SRL_length[0]),
.A1(SRL_length[1]),
.A2(SRL_length[2]),
.A3(SRL_length[3]),
.Q(enable_cclk)
);
//***************************************************
//* This process generates the enable signal for
//* the shift register and the comparator. It also
//* generates the clock signal used to increment
//* the PROMs address counter.
//***************************************************
always @ (posedge clock)
begin
if (enable)
begin
if (enable_cclk)
cclk_int <= ~cclk_int;
if (enable_cclk & cclk_int)
read_enable <= 1'b1;
else
read_enable <= 1'b0;
end
else
cclk_int <= 1'b1;
end
 
assign cclk = cclk_int;
 
endmodule
/trunk/rtl/prom_reader.v
0,0 → 1,191
// MODULE : PROM_reader_serial.v
// AUTHOR : Stephan Neuhold
// VERSION : v1.00
//
// FUNCTION DESCRIPTION:
// ---------------------
// This module provides the control state machine
// for reading data from the PROM. This includes
// searching for synchronisation patterns, retrieving
// data, resetting the PROMs address counter.
 
// Signal format and FSM modified to be adapted OpenFIRE SOC
 
`timescale 1 ns / 1 ns
`include "openfire_define.v"
 
module PROM_reader_serial( clock, // cpu clock
reset, // reset signal (syncronous)
read, // request a byte from PROM (once synced)
next_sync, // seek next file in PROM
din, // din/d0 from PROM
sync_pattern, // sync pattern that determines start of file
cclk, // PROM clock
sync, // notify we are in sync (at a file)
data_ready, // notify dout data is ready
reset_prom_n, // PROM reset
dout); // PROM data
 
parameter length = 5;
parameter frequency = 50;
input clock;
input reset;
input read;
input next_sync;
input din;
input [(2**length) - 1:0] sync_pattern;
output cclk;
output sync;
output reg data_ready;
output reg reset_prom_n;
output reg [7:0] dout;
reg [3:0] current_state;
reg [length:0] count;
reg sync_int;
reg cclk_on;
wire [7:0] data;
 
parameter [3:0] Look4Sync = 4'b0001,
Wait4Active = 4'b0010,
GetData = 4'b0100,
PresentData = 4'b1000;
 
assign sync = sync_int;
 
//Clock generation and clock enable generation
clock_management #(length, frequency) Clock_Manager(
.clock(clock),
.enable(cclk_on),
.read_enable(din_read_enable),
.cclk(cclk)
);
//Shift and compare operation
shift_compare_serial #(length, frequency) Shift_And_Compare(
.clock(clock),
.reset(reset),
.enable(din_read_enable),
.din(din),
.b(sync_pattern),
.eq(sync_found),
.din_shifted(data)
);
 
//State machine
always @ (posedge clock)
begin
if (reset) // syncronous reset
begin
current_state <= Look4Sync; // we are looking for the sync pattern
dout <= 0;
count <= 0;
sync_int <= 1'b0;
data_ready <= 1'b0;
reset_prom_n <= 1'b0; // reset the prom
cclk_on <= 1'b1; // activate cclk
end
else
begin
case (current_state)
//*************************************************************
//* This state clocks in one bit of data at a time from the
//* PROM. With every new bit clocked in a comparison is done
//* to check whether it matches the synchronisation pattern.
//* If the pattern is found then a further bits are read
//* from the PROM to provide the first byte of data appearing
//* after the synchronisation pattern.
//*************************************************************
Look4Sync:
begin
count <= 0;
data_ready <= 1'b0;
sync_int <= sync_found;
reset_prom_n<= 1'b1; // end of prom reset
if (sync_found)
begin
if(~next_sync) current_state <= Wait4Active; // wait until next_sync
cclk_on <= 1'b0; // when synced, stop prom clock
end
end
//*********************************************************
//* At this point the state machine waits for user input.
//* If the user pulses the "read" signal then 8 bits of
//* are retrieved from the PROM. If the user wants to
//* look for another synchronisation pattern and pulses
//* the "next_sync" signal, then the state machine goes
//* into the "Look4Sync" state.
//*********************************************************
Wait4Active:
begin
count <= 0;
data_ready <= 1'b0;
if (read) // request a byte from prom
begin
current_state <= GetData;
cclk_on <= 1'b1;
end
if (next_sync) // request seek next file
begin
current_state <= Look4Sync;
cclk_on <= 1'b1;
end
end
//*********************************************************
//* This state gets the data from the PROM. If the
//* synchronisation pattern has just been found then
//* enough data is retrieved to present the first
//* 8 bits after the pattern. This is dependant on the
//* synchronisation pattern length.
//* If the synchronisation pattern has already been found
//* previously then only the next 8 bits of data are
//* retrieved.
//*********************************************************
GetData:
begin
if (din_read_enable) // if we can read a bit from prom...
begin
count <= count + 1;
if (sync_int)
begin
if (count == (2**length - 1))
begin
current_state <= PresentData;
sync_int <= 1'b0;
cclk_on <= 1'b0;
end
end
else
begin
if (count == 7)
begin
current_state <= PresentData;
sync_int <= 1'b0;
cclk_on <= 1'b0;
end
end
end
end
//*******************************************************
//* This state tells the user that 8 bits of data have
//* been retrieved and is presented on the "dout" port.
//* The "Wait4Active" state is then entered to wait for
//* another user request.
//*******************************************************
PresentData:
begin
dout <= data;
data_ready <= 1'b1;
if(~read) current_state <= Wait4Active; // wait until cpu releases read bit
end
default:
begin
end
endcase
end
end
 
endmodule
/trunk/rtl/openfire_arbitrer.v
0,0 → 1,288
/* MODULE: openfire arbitrer
DESCRIPTION: Contains data/instruction memory decoder and arbitrer for
several peripherals
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/`timescale 1ns / 1ps
`include "openfire_define.v"
 
module openfire_arbitrer(
`ifdef SP3SK_SRAM
sram_data2mem, sram_data2cpu,
sram_dmem_re, sram_dmem_we, sram_dmem_done,
sram_ins2cpu, sram_imem_re, sram_imem_done,
`endif
`ifdef IO_MULTICYCLE
dmem_done_io,
`endif
`ifdef ENABLE_ALIGNMENT_EXCEPTION
dmem_alignment_exception,
`endif
`ifdef SP3SK_IODEVICES
dmem_data_fromio, dmem_data_toio, dmem_we_io, dmem_re_io,
`endif
clock, reset, imem_done, dmem_done,
dmem_address, dmem_data_out, dmem_data_in, dmem_re, dmem_we,
dmem_input_sel, data_selector,
imem_address, imem_data, imem_re,
dmem_data_frombram, dmem_data_tobram, dmem_we_bram,
imem_data_frombram
);
 
input clock; // clock signal
input reset; // reset signal
output imem_done; // imem operation done
output dmem_done; // dmem operation done
 
input [31:0] dmem_address; // dmem address from cpu
output [31:0] dmem_data_out; // data-out to cpu (from arbitrer multiplexer)
input [31:0] dmem_data_in; // data-in from cpu to selected device
input dmem_re; // cpu read enable signal
input dmem_we; // cpu write enable signal
input [1:0] dmem_input_sel; // 0=byte, 1=hw, 2=word
output [3:0] data_selector; // each byte of the word (msb..lsb)
`ifdef ENABLE_ALIGNMENT_EXCEPTION
output dmem_alignment_exception; // exception on hw/word alignment
`endif
 
input [31:0] imem_address; // imem address from cpu
output [31:0] imem_data; // instruction to cpu
input imem_re; // instruction read enable
 
input [31:0] dmem_data_frombram; // data from bram
output [31:0] dmem_data_tobram; // data to bram
output dmem_we_bram; // write enable bram
input [31:0] imem_data_frombram; // instruction from bram
 
`ifdef SP3SK_IODEVICES
input [31:0] dmem_data_fromio; // data from iospace
output [31:0] dmem_data_toio; // data to iospace
output dmem_we_io; // write enable iospace
output dmem_re_io; // read from iospace
`endif
 
`ifdef SP3SK_SRAM // interface to external memory controller
output [31:0] sram_data2mem;
input [31:0] sram_data2cpu;
output sram_dmem_re;
output sram_dmem_we;
input sram_dmem_done;
input [31:0] sram_ins2cpu;
output sram_imem_re;
input sram_imem_done;
`endif
`ifdef IO_MULTICYCLE
input dmem_done_io;
`endif
 
// ---- read/write enable byte decoder and data selector -----
// this code generates de byte enable for a 32 bit word (4 bytes)
// based on dmem_address and dmem_input_sel (byte, hw or word)
// *** also generates unalignment exception
// *** also generates the memory to cpu data depending on the width
// of the request and the address
// *** also aligns the data from the cpu to the correct byte in the
// 32 bit word to be stored on memory
 
wire data_operation = dmem_re | dmem_we;
reg [3:0] data_selector;
`ifdef ENABLE_ALIGNMENT_EXCEPTION
reg dmem_alignment;
assign dmem_alignment_exception = dmem_alignment & data_operation;
`endif
 
wire [31:0] dmem_data2cpu; // bytes readed from device
reg [31:0] dmem_data_out;
reg [31:0] dmem_data2mem; // data 2 memory
 
always @(dmem_input_sel or dmem_address[1:0] or dmem_data2cpu or dmem_data_in)
begin
`ifdef ENABLE_ALIGNMENT_EXCEPTION
dmem_alignment <= 0; // default value
`endif
data_selector <= 4'b0000; // default no data selected
dmem_data_out <= 32'b0;
dmem_data2mem <= 32'bX;
case(dmem_address[1:0])
2'b00: case(dmem_input_sel)
`DM_byte : begin
data_selector <= 4'b1000;
dmem_data_out <= { dmem_data2cpu[31:24], 24'b0 };
dmem_data2mem <= { dmem_data_in[7:0], 24'bX };
end
`DM_halfword : begin
data_selector <= 4'b1100;
dmem_data_out <= { dmem_data2cpu[31:16], 16'b0 };
dmem_data2mem <= { dmem_data_in[15:0], 16'bX };
end
`DM_wholeword : begin
data_selector <= 4'b1111;
dmem_data_out <= dmem_data2cpu;
dmem_data2mem <= dmem_data_in;
end
`ifdef ENABLE_ALIGNMENT_EXCEPTION
default: dmem_alignment <= 1;
`endif
endcase
2'b01: case(dmem_input_sel)
`DM_byte : begin
data_selector <= 4'b0100;
dmem_data_out <= { dmem_data2cpu[23:16], 24'b0 };
dmem_data2mem <= { 8'bX, dmem_data_in[7:0], 16'bX };
end
`ifdef ENABLE_ALIGNMENT_EXCEPTION
default: dmem_alignment <= 1;
`endif
endcase
2'b10: case(dmem_input_sel)
`DM_byte : begin
data_selector <= 4'b0010;
dmem_data_out <= {dmem_data2cpu[15:8], 24'b0 };
dmem_data2mem <= { 16'bX, dmem_data_in[7:0], 8'bX };
end
`DM_halfword : begin
data_selector <= 4'b0011;
dmem_data_out <= {dmem_data2cpu[15:0], 16'b0 };
dmem_data2mem <= { 16'bX, dmem_data_in[15:0] };
end
`ifdef ENABLE_ALIGNMENT_EXCEPTION
default: dmem_alignment <= 1;
`endif
endcase
2'b11: case(dmem_input_sel)
`DM_byte : begin
data_selector <= 4'b0001;
dmem_data_out <= { dmem_data2cpu[7:0], 24'b0 };
dmem_data2mem <= { 24'b0, dmem_data_in[7:0] };
end
`ifdef ENABLE_ALIGNMENT_EXCEPTION
default: dmem_alignment <= 1;
`endif
endcase
endcase
`ifdef ENABLE_ALIGNMENT_EXCEPTION
//synthesis translate_off
if(dmem_alignment_exception) $display("ERROR!! Alignment exception");
//synthesis translate_on
`endif
end
 
// ---- data memory port chip select ----
// this logic generates the chip select based on the data address present
 
wire select_data_bram = (dmem_address[`DM_SIZE-1:`DM_SIZE-2] == `LOCATION_BRAM ||
dmem_address[`DM_SIZE-1:`DM_SIZE-2] == `LOCATION_BRAM_WRAP); // temporal!!!
`ifdef SP3SK_IODEVICES
wire select_data_io = dmem_address[`DM_SIZE-1:`DM_SIZE-2] == `LOCATION_IOSPACE;
`endif
`ifdef SP3SK_SRAM
wire select_data_sram = dmem_address[`DM_SIZE-1:`DM_SIZE-2] == `LOCATION_SRAM;
`endif
 
// ---- instruction memory port chip select ----
 
wire select_ins_bram = imem_address[`DM_SIZE-1:`DM_SIZE-2] == `LOCATION_BRAM;
`ifdef SP3SK_SRAM
wire select_ins_sram = imem_address[`DM_SIZE-1:`DM_SIZE-2] == `LOCATION_SRAM;
`endif
 
// ---- operation completed on data port ----
`ifndef IO_MULTICYCLE
wire dmem_done_io = 1; // no multicycle i/o
`endif
 
assign dmem_done = data_operation & ( select_data_bram // data BRAM
`ifdef SP3SK_SRAM
| (select_data_sram & sram_dmem_done) // data SRAM
`endif
`ifdef SP3SK_IODEVICES
| (select_data_io & dmem_done_io) // data IO
`endif
);
 
// ---- operation completed on instruction port ----
assign imem_done = /*imem_re &*/ (select_ins_bram // instruction BRAM
`ifdef SP3SK_SRAM
| (select_ins_sram & sram_imem_done) // instruction SRAM
`endif
);
 
// ---- data port operation enable ----
// data read BRAM always enabled
assign dmem_we_bram = dmem_we & select_data_bram; // write enable to bram
`ifdef SP3SK_IODEVICES
assign dmem_we_io = dmem_we & select_data_io;
assign dmem_re_io = dmem_re & select_data_io;
`endif
`ifdef SP3SK_SRAM
assign sram_dmem_re = dmem_re & select_data_sram; // read/write enable to sram
assign sram_dmem_we = dmem_we & select_data_sram;
`endif
 
// ---- instruction port operation enable ----
// instruction read BRAM always
`ifdef SP3SK_SRAM
wire sram_imem_re = select_ins_sram & imem_re;
`endif
 
// ----- instruction from memory to cpu multiplexer ----
`ifndef SP3SK_SRAM
assign imem_data = imem_data_frombram; // only BRAM
`else
assign imem_data = select_ins_bram ? imem_data_frombram : sram_ins2cpu; // ins2cpu mux
`endif
 
// ----- data from memory to cpu multiplexer ----
`ifndef SP3SK_SRAM
`ifndef SP3SK_IODEVICES
assign dmem_data2cpu = dmem_data_frombram; // only BRAM
`else
assign dmem_data2cpu = select_data_io ? dmem_data_fromio : dmem_data_frombram; // BRAM + IO
`endif
`else
`ifndef SP3SK_IODEVICES
assign dmem_data2cpu = select_data_sram ? sram_data2cpu : dmem_data_frombram; // BRAM + SRAM
`else
assign dmem_data2cpu = select_data_sram ? sram_data2cpu :
select_data_io ? dmem_data_fromio :
dmem_data_frombram;
`endif
`endif
 
// ---- data from cpu to all devices ----
assign dmem_data_tobram = dmem_data2mem; // data from cpu to all devices
`ifdef SP3SK_IODEVICES
assign dmem_data_toio = dmem_data2mem;
`endif
`ifdef SP3SK_SRAM
assign sram_data2mem = dmem_data2mem;
`endif
 
endmodule
/trunk/rtl/kcuart_rx.v
0,0 → 1,556
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2004 Xilinx, Inc.
// All Rights Reserved
////////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 1.01
// \ \ Filename: kcuart_rx.v
// / / Date Last Modified: 08/04/2004
// /___/ /\ Date Created: 10/16/2002
// \ \ / \
// \___\/\___\
//
//Device: Xilinx
//Purpose:
// Constant (K) Compact UART Receiver
//Reference:
// None
//Revision History:
// Rev 1.00 - kc - Start of design entry in VHDL, 10/16/2002.
// Rev 1.01 - sus - Converted to verilog, 08/04/2004.
// Rev 1.02 - njs - Synplicity attributes added, 09/06/2004.
// Rev 1.03 - njs - defparam values corrected, 12/01/2005.
//////////////////////////////////////////////////////////////////////////////////
// Contact: e-mail picoblaze@xilinx.com
//////////////////////////////////////////////////////////////////////////////////
//
// Disclaimer:
// LIMITED WARRANTY AND DISCLAIMER. These designs are
// provided to you "as is". Xilinx and its licensors make and you
// receive no warranties or conditions, express, implied,
// statutory or otherwise, and Xilinx specifically disclaims any
// implied warranties of merchantability, non-infringement, or
// fitness for a particular purpose. Xilinx does not warrant that
// the functions contained in these designs will meet your
// requirements, or that the operation of these designs will be
// uninterrupted or error free, or that defects in the Designs
// will be corrected. Furthermore, Xilinx does not warrant or
// make any representations regarding use or the results of the
// use of the designs in terms of correctness, accuracy,
// reliability, or otherwise.
//
// LIMITATION OF LIABILITY. In no event will Xilinx or its
// licensors be liable for any loss of data, lost profits, cost
// or procurement of substitute goods or services, or for any
// special, incidental, consequential, or indirect damages
// arising from the use or operation of the designs or
// accompanying documentation, however caused and on any theory
// of liability. This limitation will apply even if Xilinx
// has been advised of the possibility of such damage. This
// limitation shall apply not-withstanding the failure of the
// essential purpose of any limited remedies herein.
//////////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1ps
 
module kcuart_rx
(serial_in,
data_out,
data_strobe,
en_16_x_baud,
clk);
 
input serial_in;
output [7:0] data_out;
output data_strobe;
input en_16_x_baud;
input clk;
 
////////////////////////////////////////////////////////////////////////////////////
//
// Start of KCUART_RX
//
//
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
//
// wires used in KCUART_RX
//
////////////////////////////////////////////////////////////////////////////////////
//
wire sync_serial ;
wire stop_bit ;
wire [7:0] data_int ;
wire [7:0] data_delay ;
wire start_delay ;
wire start_bit ;
wire edge_delay ;
wire start_edge ;
wire decode_valid_char ;
wire valid_char ;
wire decode_purge ;
wire purge ;
wire [8:0] valid_srl_delay ;
wire [8:0] valid_reg_delay ;
wire decode_data_strobe ;
 
////////////////////////////////////////////////////////////////////////////////////
//
// Start of KCUART_RX circuit description
//
////////////////////////////////////////////////////////////////////////////////////
//
 
// Synchronise input serial data to system clock
 
FD sync_reg
( .D(serial_in),
.Q(sync_serial),
.C(clk) );
 
FD stop_reg
( .D(sync_serial),
.Q(stop_bit),
.C(clk) );
 
 
// Data delays to capture data at 16 time baud rate
// Each SRL16E is followed by a flip-flop for best timing
 
SRL16E delay15_srl_0
( .D(data_int[1]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[0] ));
defparam delay15_srl_0.INIT = 16'h0000;
 
SRL16E delay15_srl_1
( .D(data_int[2]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[1] ));
defparam delay15_srl_1.INIT = 16'h0000;
 
SRL16E delay15_srl_2
( .D(data_int[3]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[2] ));
defparam delay15_srl_2.INIT = 16'h0000;
 
SRL16E delay15_srl_3
( .D(data_int[4]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[3] ));
defparam delay15_srl_3.INIT = 16'h0000;
 
SRL16E delay15_srl_4
( .D(data_int[5]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[4] ));
defparam delay15_srl_4.INIT = 16'h0000;
 
SRL16E delay15_srl_5
( .D(data_int[6]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[5] ));
defparam delay15_srl_5.INIT = 16'h0000;
 
SRL16E delay15_srl_6
( .D(data_int[7]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[6] ));
defparam delay15_srl_6.INIT = 16'h0000;
SRL16E delay15_srl_7
( .D(stop_bit),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(data_delay[7]) );
defparam delay15_srl_7.INIT = 16'h0000;
 
FDE data_reg_0
( .D(data_delay[0]),
.Q(data_int[0]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE data_reg_1
( .D(data_delay[1]),
.Q(data_int[1]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE data_reg_2
( .D(data_delay[2]),
.Q(data_int[2]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE data_reg_3
( .D(data_delay[3]),
.Q(data_int[3]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE data_reg_4
( .D(data_delay[4]),
.Q(data_int[4]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE data_reg_5
( .D(data_delay[5]),
.Q(data_int[5]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE data_reg_6
( .D(data_delay[6]),
.Q(data_int[6]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE data_reg_7
( .D(data_delay[7]),
.Q(data_int[7]),
.CE(en_16_x_baud),
.C(clk) );
 
// Assign internal wires to outputs
assign data_out = data_int;
// Data delays to capture start bit at 16 time baud rate
 
SRL16E start_srl
( .D(data_int[0]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(start_delay ) );
defparam start_srl.INIT = 16'h0000;
 
FDE start_reg
( .D(start_delay),
.Q(start_bit),
.CE(en_16_x_baud),
.C(clk) );
 
// Data delays to capture start bit leading edge at 16 time baud rate
// Delay ensures data is captured at mid-bit position
 
SRL16E edge_srl
( .D(start_bit),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b0),
.A2(1'b1),
.A3(1'b0),
.Q(edge_delay ) );
defparam edge_srl.INIT = 16'h0000;
 
FDE edge_reg
( .D(edge_delay),
.Q(start_edge),
.CE(en_16_x_baud),
.C(clk) );
 
// Detect a valid character
 
LUT4 valid_lut
( .I0(purge),
.I1(stop_bit),
.I2(start_edge),
.I3(edge_delay),
.O(decode_valid_char ) );
defparam valid_lut.INIT = 16'h0040;
 
FDE valid_reg
( .D(decode_valid_char),
.Q(valid_char),
.CE(en_16_x_baud),
.C(clk) );
 
// Purge of data status
 
LUT3 purge_lut
( .I0(valid_reg_delay[8]),
.I1(valid_char),
.I2(purge),
.O(decode_purge ) );
defparam purge_lut.INIT = 8'h54;
 
FDE purge_reg
( .D(decode_purge),
.Q(purge),
.CE(en_16_x_baud),
.C(clk) );
 
// Delay of valid_char pulse of length equivalent to the time taken
// to purge data shift register of all data which has been used.
// Requires 9x16 + 8 delays which is achieved by packing of SRL16E with
// 16 delays and utilising the dedicated flip flop in each of 8 stages.
 
SRL16E valid_delay15_srl_0
( .D(valid_char),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b0),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[0] ) );
defparam valid_delay15_srl_0.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_1
( .D(valid_reg_delay[0]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[1] ) );
defparam valid_delay16_srl_1.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_2
( .D(valid_reg_delay[1]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[2] ) );
defparam valid_delay16_srl_2.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_3
( .D(valid_reg_delay[2]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[3] ) );
defparam valid_delay16_srl_3.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_4
( .D(valid_reg_delay[3]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[4] ) );
defparam valid_delay16_srl_4.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_5
( .D(valid_reg_delay[4]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[5] ) );
defparam valid_delay16_srl_5.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_6
( .D(valid_reg_delay[5]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[6] ) );
defparam valid_delay16_srl_6.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_7
( .D(valid_reg_delay[6]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[7] ) );
defparam valid_delay16_srl_7.INIT = 16'h0000;
 
SRL16E valid_delay16_srl_8
( .D(valid_reg_delay[7]),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b1),
.A2(1'b1),
.A3(1'b1),
.Q(valid_srl_delay[8] ) );
defparam valid_delay16_srl_8.INIT = 16'h0000;
 
FDE valid_data_reg_0
( .D(valid_srl_delay[0]),
.Q(valid_reg_delay[0]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE valid_data_reg_1
( .D(valid_srl_delay[1]),
.Q(valid_reg_delay[1]),
.CE(en_16_x_baud),
.C(clk) );
FDE valid_data_reg_2
( .D(valid_srl_delay[2]),
.Q(valid_reg_delay[2]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE valid_data_reg_3
( .D(valid_srl_delay[3]),
.Q(valid_reg_delay[3]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE valid_data_reg_4
( .D(valid_srl_delay[4]),
.Q(valid_reg_delay[4]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE valid_data_reg_5
( .D(valid_srl_delay[5]),
.Q(valid_reg_delay[5]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE valid_data_reg_6
( .D(valid_srl_delay[6]),
.Q(valid_reg_delay[6]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE valid_data_reg_7
( .D(valid_srl_delay[7]),
.Q(valid_reg_delay[7]),
.CE(en_16_x_baud),
.C(clk) );
 
FDE valid_data_reg_8
( .D(valid_srl_delay[8]),
.Q(valid_reg_delay[8]),
.CE(en_16_x_baud),
.C(clk) );
 
// Form data strobe
 
LUT2 strobe_lut
( .I0(valid_char),
.I1(en_16_x_baud),
.O(decode_data_strobe ) );
defparam strobe_lut.INIT = 4'h8;
 
FD strobe_reg
( .D(decode_data_strobe),
.Q(data_strobe),
.C(clk) );
 
endmodule
 
////////////////////////////////////////////////////////////////////////////////////
//
// END OF FILE KCUART_RX.V
//
////////////////////////////////////////////////////////////////////////////////////
 
 
/trunk/rtl/sram_wrapper.v
0,0 → 1,197
/* MODULE: openfire sram controller
DESCRIPTION: Controls multiple access to SRAM
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
`timescale 1ns / 1ps
`include "openfire_define.v"
 
module sram_controller(
rst, clk,
 
ram_addr, ram_oe_n, ram_we_n, // external 2x 256Kx16 sram modules in SP3 Starter Kit
ram1_io, ram1_ce_n, ram1_ub_n, ram1_lb_n,
ram2_io, ram2_ce_n, ram2_ub_n, ram2_lb_n,
 
addr1, data2mem1, data2cpu1, re1, we1, done1, select1,
addr2, data2cpu2, re2, done2,
addr3, data2cpu3, re3, done3
);
 
input rst;
input clk;
 
output [17:0] ram_addr; // SRAM ADDR (256K @)
output ram_oe_n; // OE_N shared by 2 IC
output ram_we_n; // WE_N shared by 2 IC
inout [15:0] ram1_io; // I/O data port SRAM1
output ram1_ce_n; // SRAM1 CE_N chip enable
output ram1_ub_n; // UB_N upper byte select
output ram1_lb_n; // LB_N lower byte select
inout [15:0] ram2_io; // I/O data port SRAM2
output ram2_ce_n; // SRAM2 CE_N chip enable
output ram2_ub_n; // UB_N upper byte select
output ram2_lb_n; // LB_N lower byte select
 
input [17:0] addr1; // port #1 lines
input [31:0] data2mem1;
output [31:0] data2cpu1;
input re1;
input we1;
output done1;
input [3:0] select1;
 
input [17:0] addr2; // port #2 lines
output [31:0] data2cpu2;
input re2;
output done2;
 
input [17:0] addr3; // port #3 lines
output [31:0] data2cpu3;
input re3;
output done3;
 
// ----- state machine for arbitrated access ----------
 
wire p1 = re1 | we1; // operation requested on each port
wire p2 = re2;
wire p3 = re3;
 
reg op_done1; // operation completed on each port
reg op_done2;
reg op_done3;
 
reg [31:0] data2cpu1; // register data output to cpu
reg [31:0] data2cpu2;
reg [31:0] data2cpu3;
 
reg [17:0] addr2_cached; // cache imem address
 
assign done1 = op_done1;
assign done2 = (addr2 == addr2_cached) & op_done2;
assign done3 = op_done3;
 
//synthesis translate_off
initial begin
data2cpu1 <= 0;
data2cpu2 <= 0;
data2cpu3 <= 0;
end
//synthesis translate_on
 
parameter [3:0] Idle = 4'b0001, // different states
Port1 = 4'b0010,
Port2 = 4'b0100,
Port3 = 4'b1000;
 
reg [3:0] state; // store different states
wire [3:0] bytesel; // byte select for the current operation
 
assign bytesel = (state == Port1) ? select1 : 4'b1111; // byteselect to the physical ram
 
always @(posedge clk)
begin
if(rst) // reinitialite FSM
begin
state <= Idle;
op_done1 <= 0;
op_done2 <= 0;
op_done3 <= 0;
end
else
begin
case(state) // process FSM
Idle : begin // IDLE
op_done1 <= 0; // if any request -> fall associate done
op_done2 <= 0;
op_done3 <= 0;
if(p2) state <= Port2; // PORT2 in progress
else if(p1) state <= Port1; // PORT1 in progress
else if(p3) state <= Port3; // PORT3 in progress
end
 
Port1 : begin // PORT1 completed
data2cpu1 <= { ram1_io, ram2_io };
op_done1 <= 1;
op_done2 <= 0;
op_done3 <= 0;
if(p2) state <= Port2;
else if(p3) state <= Port3;
else state <= Idle;
end
 
Port2 : begin // PORT2 completed
data2cpu2 <= { ram1_io, ram2_io };
addr2_cached <= addr2;
op_done1 <= 0;
op_done2 <= 1;
op_done3 <= 0;
if(p3) state <= Port3;
else if(p1) state <= Port1;
else state <= Idle;
end
 
Port3 : begin // PORT3 completed
data2cpu3 <= { ram1_io, ram2_io };
op_done1 <= 0;
op_done2 <= 0;
op_done3 <= 1;
if(p1) state <= Port1;
else if(p2) state <= Port2;
else state <= Idle;
end
endcase
end // else
end // always
 
// --------- physical sram interface -----------
 
assign ram_oe_n = ~1; // oe always active (check: power consumption?)
assign ram_we_n = ~(state == Port1 & we1);
 
assign ram1_ce_n = 0; // chip select enabled
assign ram1_ub_n = ~bytesel[3]; // upper/lower byte enabled
assign ram1_lb_n = ~bytesel[2];
 
assign ram2_ce_n = 0; // chip select enabled
assign ram2_ub_n = ~bytesel[1]; // upper/lower byte enabled
assign ram2_lb_n = ~bytesel[0];
 
assign ram_addr = (state == Port3) ? addr3 : // address bus
(state == Port2) ? addr2 :
addr1;
 
wire [31:0] data2mem = data2mem1; // only port #1 can write to memory
 
assign ram1_io = ~ram_we_n ? data2mem[31:16] : 16'bZ; // write port (tristate)
assign ram2_io = ~ram_we_n ? data2mem[15:0] : 16'bZ;
 
endmodule
/trunk/rtl/openfire_regfile.v
0,0 → 1,140
/* MODULE: openfire_regfile
 
DESCRIPTION: This module instantiates two, dual-port aynchronous memories. In
Xilinx parts this synthesizes to Select (LUT-based) RAM. To handle half-word
and byte loads, MUXes and a feedback loop are used such that only the desired
portions of the previous word are modified.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3 27/03/2007 Antonio J Anton
Removed memory load unalignment handling (moved to arbitrer)
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
`include "openfire_define.v"
 
module openfire_regfile (
reset, clock,
regA_addr, regB_addr, regD_addr, result, pc_regfile,
dmem_data, regfile_input_sel, we_regfile,
we_alu_branch,
regA, regB, regD, enable
);
 
// From top level
input reset;
input clock;
 
// From DECODE
input [4:0] regA_addr;
input [4:0] regB_addr;
input [4:0] regD_addr;
input [3:0] regfile_input_sel;
input we_alu_branch;
 
// From EXECUTE
input [31:0] result;
input [`A_SPACE+1:0] pc_regfile;
input we_regfile;
input enable;
 
// From DMEM
input [31:0] dmem_data;
 
output [31:0] regA;
output [31:0] regB;
output [31:0] regD;
 
reg [31:0] input_data;
 
wire write_en;
wire [31:0] extended_pc;
 
// Write to registers on we_alu_branch OR we_load
// UNLESS r0 is the target. r0 MUST always be zero. (|regD_addr) isolates R0
// Allow write on reset to load r0 with zero.
assign write_en = reset ? 1'b1 : (we_alu_branch | we_regfile) & (|regD_addr) & enable;
 
// extended PC to datapath width
assign extended_pc[31:`A_SPACE+2] = 0;
assign extended_pc[`A_SPACE+1:0] = pc_regfile;
 
// Input select into REGFILE
always@(
`ifdef FSL_LINK
// todo
`endif
dmem_data or extended_pc or result or regfile_input_sel or write_en or clock
)
begin
case(regfile_input_sel)
`RF_dmem_byte: input_data <= dmem_data[31:24]; // update byte
`RF_dmem_halfword: input_data <= dmem_data[31:16]; // update halfword
`RF_dmem_wholeword: input_data <= dmem_data; // update word
`RF_alu_result: input_data <= result;
`RF_pc: input_data <= extended_pc;
`ifdef FSL_LINK
`RF_fsl: //todo
`endif
default:
begin
input_data <= 0;
//synthesis translate_off
if(write_en & ~clock & (regfile_input_sel != `RF_zero)) $display("ERROR! REGFILE input selector set to illegal value %d at PC %x", regfile_input_sel, pc_regfile);
//synthesis translate_on
end
endcase
end
 
// We need a 3-port register file -- create from 2, 2-port SRAMs
// Tie write ports together
openfire_rf_sram RF_BANK0 (
.clock(clock),
.read_addr(regA_addr),
.write_addr(regD_addr),
.data_in(input_data),
.we(write_en),
.read_data_out(regA),
.write_data_out(regD)
);
 
openfire_rf_sram RF_BANK1 (
.clock(clock),
.read_addr(regB_addr),
.write_addr(regD_addr),
.data_in(input_data),
.we(write_en),
.read_data_out(regB),
.write_data_out( )
);
endmodule
/trunk/rtl/kcuart_tx.v
0,0 → 1,414
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2004 Xilinx, Inc.
// All Rights Reserved
////////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Version: 1.03
// \ \ Filename: kcuart_tx.v
// / / Date Last Modified: November 2, 2004
// /___/ /\ Date Created: October 14, 2002
// \ \ / \
// \___\/\___\
//
//Device: Xilinx
//Purpose:
// Constant (K) Compact UART Transmitter
//Reference:
// None
//Revision History:
// Rev 1.00 - kc - Start of design entry in VHDL, October 14, 2002
// Rev 1.01 - sus - Converted to verilog, August 4, 2004
// Rev 1.02 - njs - Synplicity attributes added, September 6, 2004
// Rev 1.03 - njs - Fixed simulation attributes from string to hex,
// November 2, 2004
//////////////////////////////////////////////////////////////////////////////////
// Contact: e-mail picoblaze@xilinx.com
//////////////////////////////////////////////////////////////////////////////////
//
// Disclaimer:
// LIMITED WARRANTY AND DISCLAIMER. These designs are
// provided to you "as is". Xilinx and its licensors make and you
// receive no warranties or conditions, express, implied,
// statutory or otherwise, and Xilinx specifically disclaims any
// implied warranties of merchantability, non-infringement, or
// fitness for a particular purpose. Xilinx does not warrant that
// the functions contained in these designs will meet your
// requirements, or that the operation of these designs will be
// uninterrupted or error free, or that defects in the Designs
// will be corrected. Furthermore, Xilinx does not warrant or
// make any representations regarding use or the results of the
// use of the designs in terms of correctness, accuracy,
// reliability, or otherwise.
//
// LIMITATION OF LIABILITY. In no event will Xilinx or its
// licensors be liable for any loss of data, lost profits, cost
// or procurement of substitute goods or services, or for any
// special, incidental, consequential, or indirect damages
// arising from the use or operation of the designs or
// accompanying documentation, however caused and on any theory
// of liability. This limitation will apply even if Xilinx
// has been advised of the possibility of such damage. This
// limitation shall apply not-withstanding the failure of the
// essential purpose of any limited remedies herein.
//////////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1ps
 
module kcuart_tx
(data_in,
send_character,
en_16_x_baud,
serial_out,
Tx_complete,
clk);
 
input [7:0] data_in;
input send_character;
input en_16_x_baud;
output serial_out;
output Tx_complete;
input clk;
 
//
////////////////////////////////////////////////////////////////////////////////////
//
// Start of KCUART_TX
//
//
////////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////////
//
// wires used in KCUART_TX
//
////////////////////////////////////////////////////////////////////////////////////
//
wire data_01;
wire data_23;
wire data_45;
wire data_67;
wire data_0123;
wire data_4567;
wire data_01234567;
wire [2:0] bit_select;
wire [2:0] next_count;
wire [2:0] mask_count;
wire [2:0] mask_count_carry;
wire [2:0] count_carry;
wire ready_to_start;
wire decode_Tx_start;
wire Tx_start;
wire decode_Tx_run;
wire Tx_run;
wire decode_hot_state;
wire hot_state;
wire hot_delay;
wire Tx_bit;
wire decode_Tx_stop;
wire Tx_stop;
wire decode_Tx_complete;
 
////////////////////////////////////////////////////////////////////////////////////
//
// Start of KCUART_TX circuit description
//
////////////////////////////////////////////////////////////////////////////////////
//
 
// 8 to 1 multiplexer to convert parallel data to serial
 
LUT4 mux1_lut
( .I0(bit_select[0]),
.I1(data_in[0]),
.I2(data_in[1]),
.I3(Tx_run),
.O(data_01) );
defparam mux1_lut.INIT = 16'hE4FF;
 
LUT4 mux2_lut
( .I0(bit_select[0]),
.I1(data_in[2]),
.I2(data_in[3]),
.I3(Tx_run),
.O(data_23) );
defparam mux2_lut.INIT = 16'hE4FF;
 
LUT4 mux3_lut
(.I0(bit_select[0]),
.I1(data_in[4]),
.I2(data_in[5]),
.I3(Tx_run),
.O(data_45) );
defparam mux3_lut.INIT = 16'hE4FF;
 
LUT4 mux4_lut
(.I0(bit_select[0]),
.I1(data_in[6]),
.I2(data_in[7]),
.I3(Tx_run),
.O(data_67) );
defparam mux4_lut.INIT = 16'hE4FF;
 
MUXF5 mux5_muxf5
( .I1(data_23),
.I0(data_01),
.S(bit_select[1]),
.O(data_0123) );
 
MUXF5 mux6_muxf5
( .I1(data_67),
.I0(data_45),
.S(bit_select[1]),
.O(data_4567) );
 
MUXF6 mux7_muxf6
( .I1(data_4567),
.I0(data_0123),
.S(bit_select[2]),
.O(data_01234567) );
 
// Register serial output and force start and stop bits
 
FDRS pipeline_serial
( .D(data_01234567),
.Q(serial_out),
.R(Tx_start),
.S(Tx_stop),
.C(clk) ) ;
 
// 3-bit counter
// Counter is clock enabled by en_16_x_baud
// Counter will be reset when 'Tx_start' is active
// Counter will increment when Tx_bit is active
// Tx_run must be active to count
// count_carry[2] indicates when terminal count [7] is reached and Tx_bit=1 (ie overflow)
 
FDRE register_bit_0
(.D(next_count[0]),
.Q(bit_select[0]),
.CE(en_16_x_baud),
.R(Tx_start),
.C(clk) );
 
LUT2 count_lut_0
(.I0(bit_select[0]),
.I1(Tx_run),
.O(mask_count[0]) );
defparam count_lut_0.INIT = 4'h8;
 
MULT_AND mask_and_0
(.I0(bit_select[0]),
.I1(Tx_run),
.LO(mask_count_carry[0]) );
 
MUXCY count_muxcy_0
( .DI(mask_count_carry[0]),
.CI(Tx_bit),
.S(mask_count[0]),
.O(count_carry[0]) );
XORCY count_xor_0
(.LI(mask_count[0]),
.CI(Tx_bit),
.O(next_count[0]) );
FDRE register_bit_1
(.D(next_count[1]),
.Q(bit_select[1]),
.CE(en_16_x_baud),
.R(Tx_start),
.C(clk) );
 
LUT2 count_lut_1
(.I0(bit_select[1]),
.I1(Tx_run),
.O(mask_count[1]) );
defparam count_lut_1.INIT = 4'h8;
 
MULT_AND mask_and_1
( .I0(bit_select[1]),
.I1(Tx_run),
.LO(mask_count_carry[1]) );
 
MUXCY count_muxcy_1
( .DI(mask_count_carry[1]),
.CI(count_carry[0]),
.S(mask_count[1]),
.O(count_carry[1]) );
XORCY count_xor_1
( .LI(mask_count[1]),
.CI(count_carry[0]),
.O(next_count[1]) );
 
FDRE register_bit_2
( .D(next_count[2]),
.Q(bit_select[2]),
.CE(en_16_x_baud),
.R(Tx_start),
.C(clk) );
 
LUT2 count_lut_2
( .I0(bit_select[2]),
.I1(Tx_run),
.O(mask_count[2]) );
defparam count_lut_2.INIT = 4'h8;
MULT_AND mask_and_2
( .I0(bit_select[2]),
.I1(Tx_run),
.LO(mask_count_carry[2]) );
 
 
MUXCY count_muxcy_2
( .DI(mask_count_carry[2]),
.CI(count_carry[1]),
.S(mask_count[2]) ,
.O(count_carry[2]) );
XORCY count_xor_2
( .LI(mask_count[2]),
.CI(count_carry[1]),
.O(next_count[2]) );
 
// Ready to start decode
 
LUT3 ready_lut
( .I0(Tx_run),
.I1(Tx_start),
.I2(send_character),
.O(ready_to_start ) );
defparam ready_lut.INIT = 8'h10;
 
// Start bit enable
 
LUT4 start_lut
( .I0(Tx_bit),
.I1(Tx_stop),
.I2(ready_to_start),
.I3(Tx_start),
.O(decode_Tx_start ) );
defparam start_lut.INIT = 16'h0190;
 
FDE Tx_start_reg
( .D(decode_Tx_start),
.Q(Tx_start),
.CE(en_16_x_baud),
.C(clk) );
 
 
// Run bit enable
LUT4 run_lut
( .I0(count_carry[2]),
.I1(Tx_bit),
.I2(Tx_start),
.I3(Tx_run),
.O(decode_Tx_run ) );
defparam run_lut.INIT = 16'h1540;
 
FDE Tx_run_reg
( .D(decode_Tx_run),
.Q(Tx_run),
.CE(en_16_x_baud),
.C(clk) );
 
// Bit rate enable
 
LUT3 hot_state_lut
( .I0(Tx_stop),
.I1(ready_to_start),
.I2(Tx_bit),
.O(decode_hot_state) );
defparam hot_state_lut.INIT = 8'h94;
 
FDE hot_state_reg
( .D(decode_hot_state),
.Q(hot_state),
.CE(en_16_x_baud),
.C(clk) );
 
SRL16E delay14_srl
( .D(hot_state),
.CE(en_16_x_baud),
.CLK(clk),
.A0(1'b1),
.A1(1'b0),
.A2(1'b1),
.A3(1'b1),
.Q(hot_delay) );
defparam delay14_srl.INIT = 16'h0000;
 
FDE Tx_bit_reg
( .D(hot_delay),
.Q(Tx_bit),
.CE(en_16_x_baud),
.C(clk) );
 
// Stop bit enable
LUT4 stop_lut
( .I0(Tx_bit),
.I1(Tx_run),
.I2(count_carry[2]),
.I3(Tx_stop),
.O(decode_Tx_stop) );
defparam stop_lut.INIT = 16'h0180;
 
FDE Tx_stop_reg
( .D(decode_Tx_stop),
.Q(Tx_stop),
.CE(en_16_x_baud),
.C(clk) );
 
// Tx_complete strobe
 
LUT2 complete_lut
( .I0(count_carry[2]),
.I1(en_16_x_baud),
.O(decode_Tx_complete) );
defparam complete_lut.INIT = 4'h8;
 
FD Tx_complete_reg
( .D(decode_Tx_complete),
.Q(Tx_complete),
.C(clk) );
 
 
endmodule
 
////////////////////////////////////////////////////////////////////////////////////
//
// END OF FILE KCUART_TX.V
//
////////////////////////////////////////////////////////////////////////////////////
 
 
/trunk/rtl/openfire_iospace.v
0,0 → 1,449
/* MODULE: openfire vga
DESCRIPTION: I/O space and peripherals instantiation
 
AUTHOR:
Antonio J. Anton
Anro Ingenieros (www.anro-ingenieros.com)
aj@anro-ingenieros.com
 
REVISION HISTORY:
Revision 1.0, 26/03/2007
Initial release
 
COPYRIGHT:
Copyright (c) 2007 Antonio J. Anton
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
 
`timescale 1ns / 1ps
`include "openfire_define.v"
 
module openfire_iospace(
`ifdef SP3SK_USERIO
leds, drivers_n, segments_n, pushbuttons, switches,
`endif
`ifdef UART1_ENABLE
tx1, rx1,
`endif
`ifdef UART2_ENABLE
tx2, rx2,
`endif
`ifdef SP3SK_PROM_DATA
prom_din, prom_cclk, prom_reset_n,
`endif
`ifdef IO_MULTICYCLE
done,
`endif
`ifdef ENABLE_INTERRUPTS
interrupt,
`endif
clk, rst, read, write,
addr, data_in, data_out
);
 
input clk;
input rst;
input read; // iospace read requesst
input write; // iospace write request
`ifdef IO_MULTICYCLE
output done; // iospace operation completed
`endif
input [`IO_SIZE-1:0] addr; // address of operation
input [31:0] data_in; // data from cpu
output [31:0] data_out; // data to cpu
`ifdef SP3SK_USERIO
output [7:0] leds; // LEDS (1=on)
output [3:0] drivers_n; // 7SEG driver (negated)
output [7:0] segments_n; // segments (negated)
input [3:0] pushbuttons; // 4 pushbuttons ( pushbuttons[3] = reset)
input [7:0] switches; // 8 switches
`endif
`ifdef UART1_ENABLE
output tx1; // transmit #1
input rx1; // receive #1
`endif
`ifdef UART2_ENABLE
output tx2; // transmit #2
input rx2; // receive #2
`endif
`ifdef SP3SK_PROM_DATA
input prom_din; // data in from PROM
output prom_cclk; // clock to PROM
output prom_reset_n; // reset to PROM
`endif
`ifdef ENABLE_INTERRUPTS
output interrupt; // interrupt line to cpu
`endif
 
// ---- handle multicycle i/o operations ----
`ifdef IO_MULTICYCLE
assign ready = 1;
`endif
 
// --------------- UARTS -----------------
`ifdef UART1_ENABLE // assure that baudrate generator is
`define UART_BAUDRATEGEN_ENABLE // instantiated if a uart is in use
`endif
`ifdef UART2_ENABLE
`define UART_BAUDRATEGEN_ENABLE
`endif
 
`ifdef UART_BAUDRATEGEN_ENABLE
reg [4:0] baud_count; // counter for a tick generator each 16 clocks
reg en_16_x_baud; // tick signal every 16 clocks --> baud generator
`endif
 
`ifdef UART1_ENABLE
wire write_to_uart; // write byte into send FIFO
wire tx_full; // TX FIFO is full
wire tx_half_full; // TX FIFO is 1/2 full
reg read_from_uart; // read byte from receive FIFO
wire [7:0] rx_data; // recieved data
wire rx_data_present; // RX FIFO has data
wire rx_full; // RX FIFO is full
wire rx_half_full; // RX FIFO 1/2 full
`endif
 
`ifdef UART2_ENABLE
wire write_to_uart2; // indica que hay que meter en la TX FIFO un byte
wire tx2_full; // indica que la TX FIFO esta llena
wire tx2_half_full; // indica que la TX FIFO esta 1/2 llena
reg read_from_uart2; // obtener en rx_data un byte de la RX FIFO
wire [7:0] rx2_data; // donde esta el byte recibido
wire rx2_data_present; // indica que hay datos en RX FIFO
wire rx2_full; // RX FIFO llena
wire rx2_half_full; // RX FIFO 1/2 llena
`endif
 
//---------- baud rate generator -------------
// Set baud rate to 9600 for the UART communications DIV=CLK/(16*BAUDRATE)
// Requires en_16_x_baud to be 153600Hz which is a single cycle pulse every 325 cycles at 50MHz
// NOTE : If the highest value for baud_count exceeds 127 you will need to adjust
// the width in the reg declaration for baud_count.
`ifdef UART_BAUDRATEGEN_ENABLE
always @(posedge clk)
begin
if (baud_count == `BAUD_COUNT)
begin
baud_count <= 1'b0;
en_16_x_baud <= 1'b1;
end
else
begin
baud_count <= baud_count + 1;
en_16_x_baud <= 1'b0;
end
end
`endif
 
// -------- UART #1 ------------
// Connect the 8-bit, 1 stop-bit, no parity transmit and receive macros.
// Each contains an embedded 16-byte FIFO buffer.
 
`ifdef UART1_ENABLE // hack to enable status register
`define UART_STATUS_REG // if at least one uart is present
`endif
`ifdef UART2_ENABLE
`define UART_STATUS_REG
`endif
 
`ifdef UART1_ENABLE
uart_tx transmit(
.data_in(data_in[31:24]), // 8 bits bajos del registro = dato a enviar
.write_buffer(write_to_uart), //
.reset_buffer(rst),
.en_16_x_baud(en_16_x_baud),
.serial_out(tx1),
.buffer_full(tx_full),
.buffer_half_full(tx_half_full),
.clk(clk)
);
 
uart_rx receive(
.serial_in(rx1),
.data_out(rx_data),
.read_buffer(read_from_uart),
.reset_buffer(rst),
.en_16_x_baud(en_16_x_baud),
.buffer_data_present(rx_data_present),
.buffer_full(rx_full),
.buffer_half_full(rx_half_full),
.clk(clk)
);
`endif
 
// -------- UART #2 ------------
// Connect the 8-bit, 1 stop-bit, no parity transmit and receive macros.
// Each contains an embedded 16-byte FIFO buffer.
`ifdef UART2_ENABLE
uart_tx transmit2(
.data_in(data_out[31:24]), // 8 bits bajos del registro = dato a enviar
.write_buffer(write_to_uart2), //
.reset_buffer(rst),
.en_16_x_baud(en_16_x_baud),
.serial_out(tx2),
.buffer_full(tx2_full),
.buffer_half_full(tx2_half_full),
.clk(clk)
);
 
uart_rx receive2(
.serial_in(rx2),
.data_out(rx2_data),
.read_buffer(read_from_uart2),
.reset_buffer(rst),
.en_16_x_baud(en_16_x_baud),
.buffer_data_present(rx2_data_present),
.buffer_full(rx2_full),
.buffer_half_full(rx2_half_full),
.clk(clk)
);
`endif
 
// ----- SP3 STARTER KIT USER PORTS : LEDS, 7SEG DISPLAY, SWITCHES & PUSHBUTTONS ----
`ifdef SP3SK_USERIO
reg [7:0] leds; // 8 leds
reg [3:0] drivers_n; // 4 drivers
reg [7:0] segments_n; // 8 segments
`endif
 
// ----- SP3 STARTER KIT PLATFORM FLASH ------------
`ifdef SP3SK_PROM_DATA
reg prom_read; // signal the prom_reader to read next byte
reg prom_next_sync; // signal the prom_reader to seek next file
wire prom_synced; // notify prom is at the start of a file
wire prom_dataready; // notify prom has readed a byte
wire [7:0] prom_dataout; // data readed from prom
 
PROM_reader_serial prom_file(
.clock(clk),
.reset(rst),
.din(prom_din),
.cclk(prom_cclk),
.reset_prom_n(prom_reset_n),
.read(prom_read),
.next_sync(prom_next_sync),
.sync(prom_synced),
.data_ready(prom_dataready),
.dout(prom_dataout),
.sync_pattern(`PROM_SYNC_PATTERN)
);
`endif
 
// -------- TIMER #1 GENERATOR (31 bits) -----------
`ifdef TIMER1_GENERATOR
reg [30:0] max_timer1_count; // 32 bit max-timer value
reg [30:0] timer1_count; // current value of the counter
reg timer1_pulse; // positive pulse generated when max_timer1_count is reached
reg timer1_running; // indicates if timer is running/stopped
 
always @(posedge clk)
begin
if(rst | ~timer1_running) // rst or not running --> restart timer
begin
timer1_count <= 0;
timer1_pulse <= 0;
end
else if (timer1_count == max_timer1_count) // if max_timer1 reached --> generate 1 clock pulse
begin
timer1_count <= 1'b0;
timer1_pulse <= 1'b1;
//synthesis translate_off
$display("TIMER1 TRIGGERED (max_timer1_count=0x%x)", max_timer1_count);
//synthesis translate_on
end
else
begin
timer1_count <= timer1_count + 1;
timer1_pulse <= 1'b0;
end
end
`endif
 
// ------- interrupt controller ---------
`ifdef ENABLE_INTERRUPTS
reg [31:0] device_interrupt; // enable interrupt for specific device
 
wire interrupt = // interrupt line is an OR MASK of devices
`ifdef TIMER1_GENERATOR
(device_interrupt[0] & timer1_pulse) | // timer1 can generate interrupt
`endif
`ifdef UART1_ENABLE
(device_interrupt[1] & rx_data_present) | // uart1 rx data present
`endif
`ifdef UART2_ENABLE
(device_interrupt[2] & rx2_data_present) | // uart2 rx data present
`endif
0;
`endif
 
// --------------- decode output port (data to device) ----------------
always @(posedge clk)
begin
if(rst)
begin // initialize devices on reset
`ifdef SP3SK_USERIO
segments_n <= 8'hFF; // 7 segment display off
drivers_n <= 4'hF;
leds <= 8'h00; // leds off
`endif
`ifdef SP3SK_PROM_DATA
prom_next_sync <= 1'b0; // no prom activity
prom_read <= 1'b0;
`endif
`ifdef TIMER1_GENERATOR
max_timer1_count <= 0; // timer1 stopped
timer1_running <= 1'b0;
`endif
`ifdef ENABLE_INTERRUPTS
device_interrupt <= 0; // no interrupts
`endif
end
else if(write) // write to an output port
begin
case( addr[`IO_SIZE-1:0] )
`ifdef SP3SK_USERIO
`ADDR_SP3_IO : begin
segments_n <= data_in[31:24]; // LSByte is the high bits
drivers_n <= data_in[23:20];
leds <= data_in[15:8];
end
`endif
`ifdef UART1_ENABLE
`ADDR_UART1 : $display("UART1 WRITE: <%c>", data_in[31:24]);
`endif
`ifdef UART2_ENABLE
`ADDR_UART2 : $display("UART2 WRITE: <%c>", data_in[31:24]);
`endif
`ifdef SP3SK_PROM_DATA
`ADDR_PROM : begin
prom_next_sync <= data_in[23];
prom_read <= data_in[22];
end
`endif
`ifdef TIMER1_GENERATOR
`ADDR_TIMER1 : begin
max_timer1_count <= data_in[30:0];
timer1_running <= data_in[31];
//synthesis translate_off
if(data_in[31] == 0) $display("TIMER1 STOP");
else $display("TIMER1 START (max_timer1_count=0x%x)", data_in[30:0]);
//synthesis translate_on
end
`endif
`ifdef ENABLE_INTERRUPTS
`ADDR_INT : device_interrupt <= data_in;
`endif
default : $display("Error: Output port not valid: ", addr[`IO_SIZE-1:0]);
endcase
end
end
 
// write to UART transmitter FIFO buffer at address 01 hex.
// This is a combinatorial decode because the FIFO is the 'port register'.
`ifdef UART1_ENABLE
wire uart1_selected = addr[`IO_SIZE-1:0] == `ADDR_UART1;
assign write_to_uart = write & uart1_selected;
`endif
`ifdef UART2_ENABLE
wire uart2_selected = addr[`IO_SIZE-1:0] == `ADDR_UART2;
assign write_to_uart2 = write & uart2_selected;
`endif
 
// --------------- decode input port (data to cpu) ----------------
reg [31:0] data_out; // register to store data from an input port
//synthesis translate_off
initial data_out <= 0;
//synthesis translate_on
 
always @(posedge clk)
begin
if(read) // request an input port
begin
case( addr[`IO_SIZE-1:0] )
`ifdef SP3SK_USERIO
`ADDR_SP3_IO : begin
data_out[31:24] <= segments_n; // LSByte is the high bits
data_out[23:20] <= drivers_n;
data_out[19:16] <= pushbuttons;
data_out[15:8] <= leds;
data_out[7:0] <= switches;
end
`endif
`ifdef UART_STATUS_REG
`ADDR_UARTS : begin // depending which uarts are enabled, fill the status register
`ifdef UART1_ENABLE
data_out[28:24] <= { tx_full, tx_half_full, rx_full, rx_half_full, rx_data_present };
$display("UART-STATUS : rx1_data_present=%d, rx1_half_full=%d, rx1_full=%d, tx1_half_full=%d, tx1_full=%d", rx_data_present, rx_half_full, rx_full, tx_half_full, tx_full);
`endif
`ifdef UART2_ENABLE
data_out[12:8] <= { tx2_full, tx2_half_full, rx2_full, rx2_half_full, rx2_data_present };
$display("UART-STATUS : rx2_data_present=%d, rx2_half_full=%d, rx2_full=%d, tx2_half_full=%d, tx2_full=%d", rx2_data_present, rx2_half_full, rx2_full, tx2_half_full, tx2_full);
`endif
end
`endif
`ifdef UART1_ENABLE
`ADDR_UART1 : begin // receive data UART1
data_out[31:24] <= rx_data;
$display("UART1 READ: %c", rx_data);
end
`endif
`ifdef UART2_ENABLE
`ADDR_UART2 : begin // receive data UART2
data_out[31:24] <= rx_data2;
$display("UART2 READ: %c", rx_data2);
end
`endif
`ifdef SP3SK_PROM_DATA
`ADDR_PROM : begin
data_out[31:24] <= prom_dataout; // data from PROM (only valid if prom_dataready)
data_out[23] <= prom_next_sync; // actual register
data_out[22] <= prom_read; // register
data_out[21] <= prom_synced; // prom is synced?
data_out[20] <= prom_dataready; // data is ready?
end
`endif
`ifdef TIMER1_GENERATOR
`ADDR_TIMER1 : begin
data_out[30:0] <= timer1_count;
data_out[31] <= timer1_running;
//synthesis translate_off
if(timer1_running == 0) $display("TIMER1 STOPPED");
else $display("TIMER1 RUNNING (count=0x%x)", timer1_count);
//synthesis translate_on
end
`endif
`ifdef ENABLE_INTERRUPTS
`ADDR_INT : data_out <= device_interrupt;
`endif
default : $display("Error: Input port not valid: ", addr[`IO_SIZE-1:0]);
endcase
end
// Form read strobe for UART receiver FIFO buffer.
// The fact that the read strobe will occur after the actual data is read by
// the CPU is acceptable because it is really means 'I have read you'!
`ifdef UART1_ENABLE
read_from_uart <= read & uart1_selected; // strobe para dato leido desde uart #1
`endif
`ifdef UART2_ENABLE
read_from_uart2 <= read & uart2_selected; // strobe para dato leido desde uart #2
`endif
end
 
endmodule
/trunk/rtl/openfire_decode.v
0,0 → 1,448
/* MODULE: openfire_decode
 
DESCRIPTION: The decode module received the instruction from the fetch module
and produces all control signals needed by the execute stage and the register
file. In the case of IMM instructions, the decode module will stall the
execute module by issuing a NoOp instruction.
 
The COMPARE module is used for calculating if a branch is taken and CMPU
ops if support is selected. The DECODE module commands the comparator to output
a 1 for unconditional branchs and a 0 for all other non-branch instructions (other
than CMPU)..
 
While FSL instructions are optionally implemented (if FSL_LINK is defined),
only one link (FSL0) is currently supported.
 
MISSING INSTRUCTIONS:
- special register instruction: MSRCLR, MSRSET
- all instructions requiring extra hardware, except for optional multiply: IDIV, BS
- cache-related instruction: WDC, WIC
 
TO DO:
- Complete instruction set
- Simplify instruction extension
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug
 
Revision 0.4, 15/03/2007 SDC
Fixed CMP[U] with IMM bit
 
Revision 0.5 27/03/2007 Antonio J. Anton
Handling of interrupts/exceptions
MSR opcodes (mfs, mts)
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
 
`include "openfire_define.v"
 
module openfire_decode(
`ifdef ENABLE_MSR_BIP
update_msr_bip, value_msr_bip,
`endif
`ifdef ENABLE_INTERRUPTS
int_ip, int_dc, set_msr_ie,
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
opcode_exception,
`endif
`ifdef ENABLE_EXCEPTIONS
reset_msr_eip, insert_exception,
`endif
`ifdef ENABLE_MSR_OPCODES
rS_update,
`endif
clock, stall, reset, // top level
pc_decode, instruction, flush, // inputs
regA_addr, regB_addr, regD_addr, immediate, // outputs
alu_inputA_sel, alu_inputB_sel, alu_inputC_sel,
alu_fns_sel, comparator_fns_sel, branch_instr,
we_alu_branch, we_load, we_store, regfile_input_sel,
dmem_input_sel, delay_bit, update_carry, pc_exe
);
 
// From top level -- all active high unless otherwise noted
input stall;
input reset;
input clock;
 
// From DECODE module
input [`A_SPACE+1:0] pc_decode;
input [31:0] instruction;
 
// From Pipeline Controller
input flush; // a branch was taken... flush the pipeline
 
output [4:0] regA_addr;
output [4:0] regB_addr;
output [4:0] regD_addr;
output [31:0] immediate;
output [`A_SPACE+1:0] pc_exe; // pc for use by EXECUTE
output [2:0] alu_inputA_sel;
output [1:0] alu_inputB_sel;
output [1:0] alu_inputC_sel;
output [3:0] alu_fns_sel;
output [2:0] comparator_fns_sel;
output we_load; // write_en for regfile on Load
output we_store; // write_en for DMEM
output we_alu_branch; // write_en for regfile on ALU / Branch instr
output [3:0] regfile_input_sel; // selects input to regfile
output [1:0] dmem_input_sel; // selects input to DMEM
output delay_bit;
output update_carry; // tells EXECUTE to update carry bit in MSR
output branch_instr; // tells EXECUTE to use comparator for branching
`ifdef ENABLE_MSR_BIP
output update_msr_bip; // handle MSR[BIP]
output value_msr_bip;
`endif
`ifdef ENABLE_INTERRUPTS
input int_ip;
output int_dc;
output set_msr_ie;
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
output opcode_exception;
input insert_exception;
`endif
`ifdef ENABLE_EXCEPTIONS
output reset_msr_eip;
`endif
`ifdef ENABLE_MSR_OPCODES
output rS_update;
`endif
 
// Register All Outputs
reg [31:0] immediate;
reg [`A_SPACE+1:0] pc_exe; // Prog Cnter of instr being executed
reg [2:0] alu_inputA_sel;
reg [1:0] alu_inputB_sel;
reg [1:0] alu_inputC_sel;
reg [3:0] alu_fns_sel; // selects ALU function
reg [2:0] comparator_fns_sel;
reg we_load; // reg file write enable for load operations
reg we_store;
reg we_alu_branch; // reg file write enable for ALU or branch ops
reg [3:0] regfile_input_sel;
reg [1:0] dmem_input_sel;
reg [4:0] regA_addr; // 5-bit addresses into Reg File
reg [4:0] regB_addr;
reg [4:0] regD_addr;
reg update_carry; // update the Carry bit in the status reg for ADDs
reg delay_bit; // Use delay slot in Branches
reg branch_instr;
`ifdef ENABLE_MSR_BIP
reg update_msr_bip;
reg value_msr_bip;
`endif
`ifdef ENABLE_INTERRUPTS
reg int_dc;
reg set_msr_ie;
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
reg opcode_exception;
`endif
`ifdef ENABLE_EXCEPTIONS
reg reset_msr_eip;
`endif
`ifdef ENABLE_MSR_OPCODES
reg rS_update;
`endif
 
// Internal registers
reg [15:0] imm; // contains imm value from IMM instr
reg imm_valid; // indicates imm value is valid (aka previous instr was IMM)
 
always@(posedge clock)
begin
if (reset | (flush & !stall)) // flush only if not stalled, if not we may miss the executing state
begin
if (reset)
pc_exe <= 0;
else
pc_exe <= pc_decode;
update_carry <= 0;
regA_addr <= 0;
regB_addr <= 0;
regD_addr <= 0;
immediate <= 0;
alu_inputA_sel <= 0;
alu_inputB_sel <= 0;
alu_inputC_sel <= 0;
delay_bit <= 0;
branch_instr <= 0;
// EXECUTE NoOp on Reset / Flush. NoOp is OR r0, r0, r0
alu_fns_sel <= `ALU_logic_or;
comparator_fns_sel<= 0;
we_load <= 0;
we_store <= 0;
we_alu_branch <= 0;
regfile_input_sel <= `RF_zero; // write zero to r0 on reset -- R0 always zero
dmem_input_sel <= 0;
imm <= 0;
imm_valid <= 0;
`ifdef ENABLE_MSR_BIP
update_msr_bip <= 0;
value_msr_bip <= 0;
`endif
`ifdef ENABLE_INTERRUPTS
int_dc <= 0;
set_msr_ie <= 0;
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
opcode_exception <= 0;
`endif
`ifdef ENABLE_EXCEPTIONS
reset_msr_eip <= 0;
`endif
`ifdef ENABLE_MSR_OPCODES
rS_update <= 0;
`endif
`ifdef DEBUG_DECODE
$display("DECODE RESET/FLUSH: pc_exe=%x", pc_exe);
`endif
end
else if (!stall)
begin
// defaults for most instructions
branch_instr <= 0;
pc_exe <= pc_decode;
// Delay bit is tricky as each type of branch has a different location
delay_bit <= `uncond_branch ? ((`opcode == `RETURN) ? 1 : `D_bit_uncond) : `cond_branch ? `D_bit_cond : 0;
we_load <= 0;
we_store <= 0;
update_carry <= 0;
regA_addr <= `regA_sel;
regB_addr <= `regB_sel;
regD_addr <= `regD_sel;
immediate <= imm_valid ? {imm, `imm_value} : {{16{instruction[15]}}, `imm_value}; // 32-bit datapath
we_alu_branch <= 1'b1; // most instrs write to reg file
regfile_input_sel <= `RF_alu_result;
alu_inputA_sel <= `aluA_ra;
alu_inputB_sel <= `IMM_bit ? `aluB_imm : `aluB_rb;
alu_inputC_sel <= `aluC_zero;
alu_fns_sel <= `ALU_add;
comparator_fns_sel<= 0; // Not using comparator
imm_valid <= 0;
`ifdef ENABLE_MSR_BIP
update_msr_bip <= 0;
value_msr_bip <= 0;
`endif
`ifdef ENABLE_INTERRUPTS
set_msr_ie <= 0;
int_dc <= 0;
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
opcode_exception <= 0;
`endif
`ifdef ENABLE_EXCEPTIONS
reset_msr_eip <= 0;
`endif
`ifdef ENABLE_MSR_OPCODES
rS_update <= 0;
`endif
`ifdef ENABLE_OPCODE_EXCEPTION
// CPU asks to insert exception break: "brali r17,0x20"
if(insert_exception)
begin
branch_instr <= 1;
alu_inputA_sel <= `aluA_zero;
alu_inputB_sel <= `aluB_imm;
comparator_fns_sel <= `CMP_one; // force a branch
regfile_input_sel <= `RF_pc;
regD_addr <= `REG_RET_FROM_EXCEPTION;
immediate <= `ADDRESS_EXCEPTION_VECTOR;
$display("DECODE: Inserting OPCODE-EXCEPTION at pc_decode=0x%x, pc_exe=0x%x", pc_decode, pc_exe);
end
else
`endif
`ifdef ENABLE_INTERRUPTS
// when EXECUTE notifies "interrupt in progress", the DECODE module must insert "brali r14,0x10" when
// possible; this is not after a IMM opcode nor in a delay slot. When inserted the interrupt opcode,
// notify EXECUTE that the decode is completed
if(int_ip && !imm_valid && !delay_bit)
begin
branch_instr <= 1;
alu_inputA_sel <= `aluA_zero;
alu_inputB_sel <= `aluB_imm;
comparator_fns_sel <= `CMP_one; // force a branch
regfile_input_sel <= `RF_pc;
regD_addr <= `REG_RET_FROM_INTERRUPT;
immediate <= `ADDRESS_INTERRUPT_VECTOR;
int_dc <= 1; // notify that DECODE is completed
$display("DECODE: Inserting INTERRUPT at pc_decode=0x%x, pc_exe=0x%x", pc_decode, pc_exe);
end
else
`endif
// BIG Case statement here
// see openfire_define.v for definitions
casez (`opcode)
`ADD:
begin
alu_inputC_sel <= `C_bit ? `aluC_carry : `aluC_zero;
update_carry <= ~`K_bit;
end
`SUBTRACT:
begin
update_carry <= ~`K_bit;
if (`U_bit & `CMP_bit & !`IMM_bit) // CMPU
begin
alu_fns_sel <= `ALU_compare_uns;
comparator_fns_sel <= `CMP_dual_inputs;
end
else if (`CMP_bit & !`IMM_bit) // CMP
alu_fns_sel <= `ALU_compare;
else
alu_fns_sel <= `ALU_add;
alu_inputA_sel <= `aluA_ra_bar;
alu_inputC_sel <= `C_bit ? `aluC_carry : `aluC_one;
end
`LOGIC_OR: alu_fns_sel <= `ALU_logic_or;
`LOGIC_AND: alu_fns_sel <= `ALU_logic_and;
`LOGIC_XOR: alu_fns_sel <= `ALU_logic_xor;
`LOGIC_ANDN:
begin
alu_fns_sel <= `ALU_logic_and;
alu_inputB_sel <= `IMM_bit ? `aluB_imm_bar : `aluB_rb_bar;
end
`LOGIC_BIT:
begin
alu_inputC_sel <= `aluC_carry;
update_carry <= 1;
casez (`imm_value)
16'b1: alu_fns_sel <= `ALU_shiftR_arth;
16'b100001: alu_fns_sel <= `ALU_shiftR_c;
16'b1000001: alu_fns_sel <= `ALU_shiftR_log;
16'b1100000: alu_fns_sel <= `ALU_sex8;
16'b1100001: alu_fns_sel <= `ALU_sex16;
endcase
end
`BRANCH_UNCON: // Handles BREAKs as well
begin
branch_instr <= 1;
alu_inputA_sel <= `A_bit ? `aluA_zero : `aluA_pc;
alu_inputB_sel <= `IMM_bit ? `aluB_imm : `aluB_rb;
comparator_fns_sel <= `CMP_one; // force a branch
regfile_input_sel <= `RF_pc;
`ifdef ENABLE_MSR_BIP
update_msr_bip <= ~`D_bit_uncond & `A_bit & `L_bit; // is br[i]al --> break
value_msr_bip <= 1; // BREAK --> MSR[BIP] <= 1
`endif
end
`BRANCH_CON:
begin
branch_instr <= 1;
alu_inputA_sel <= `aluA_pc;
comparator_fns_sel<= `branch_compare;
we_alu_branch <= 1'b0;
end
`ifdef ENABLE_MSR_OPCODES
`SPECIAL_REG: // Handle mfs, mts
begin
if(`is_mfs) // mfs rD,rS --> move rS to ALU input A
begin
casez(`regS_sel_msr) // select corresponding ALU input based on rS
`rS_PC : alu_inputA_sel <= `aluA_pc;
`rS_MSR : alu_inputA_sel <= `aluA_msr;
default: $display("mfs: invalid rS=%x", `regS_sel_msr);
endcase
end
else if(`is_mts) // mts rS,rD (rS is only MSR). Ask EXE to update MSR from rA
rS_update <= 1;
end
`endif
`IMMEDIATE:
begin
we_alu_branch <= 1'b0; // have EXE do nothing
imm_valid <= 1;
imm <= `imm_value;
end
`RETURN: // ignores MSR, exceptions, and interrupts
begin
branch_instr <= 1;
alu_inputB_sel <= `aluB_imm;
comparator_fns_sel<= `CMP_one; // force a branch
we_alu_branch <= 1'b0;
`ifdef ENABLE_MSR_BIP
update_msr_bip <= `BRK_bit; // return from break?
value_msr_bip <= 0; // rtbd? MSR[BIP] <= 0
`endif
`ifdef ENABLE_INTERRUPTS
set_msr_ie <= `INT_bit; // MSR[IE] <= 1 if return from interrupt
`ifdef DEBUG_DECODE
`ifdef ENABLE_EXCEPTIONS
reset_msr_eip <= `EXC_bit; // MSR[EIP] <= 0 if return from exception
`endif
$display("DECODE: RETURN FROM INTERRUPT -- pc_exe=%x", pc_exe);
`endif
`endif
end
`LOAD:
begin
we_alu_branch <= 1'b0;
we_load <= 1'b1;
dmem_input_sel <= `word_size;
regfile_input_sel <= `word_size;
end
`STORE:
begin
we_alu_branch <= 1'b0;
we_store <= 1'b1;
dmem_input_sel <= `word_size;
end
`ifdef FSL_LINK
`FSL:
$display("ERROR! FSL not implemented");
`endif
`ifdef MUL
`MULTIPLY:
begin
alu_fns_sel <= `ALU_multiply;
// 32-bit mult takes several cycles -- do not write to Reg File until complete
we_alu_branch <= 1'b0;
end
`endif
default:
begin
$display("ERROR! Malformed OpCode! 0x%x", `opcode);
`ifdef ENABLE_OPCODE_EXCEPTION
opcode_exception <= 1; // notify EXECUTE that we are in "opcode exception"
`endif
end
endcase
`ifdef DEBUG_DECODE
$display("DECODE: pc_exe=%x, instruction=%x", pc_exe, instruction);
`endif
end
 
end // end of always@
endmodule
/trunk/rtl/prom_reader_my_lut2.v
0,0 → 1,31
// MODULE : my_LUT2.v
// AUTHOR : Stephan Neuhold
// VERSION : v1.00
//
// REVISION HISTORY:
// -----------------
// No revisions
//
// FUNCTION DESCRIPTION:
// ---------------------
// This module instantiates a simple LUT2
// primitive and initialises the contents
// to 9 creating an XOR function.
 
`timescale 1 ns / 1 ns
 
module my_LUT2( I0,
I1,
O);
 
input I0;
input I1;
output O;
 
LUT2 #(4'h9) my_LUT2_inst(
.I0(I0),
.I1(I1),
.O(O)
);
 
endmodule
/trunk/sw/sample/sample.c
0,0 → 1,12
#include <stdio.h>
#include <string.h>
 
char buffer[256];
 
void main(void)
{
xil_printf("como te llamas? ");
fgets(buffer, 255, stdin);
xil_printf("\r\nhola: %s\r\n", buffer);
 
}
/trunk/sw/sample/Makefile
0,0 → 1,29
PRJ = sample
CRT = ../crt/crt-sram
LIBIO = ../lib/uart1io
SRCS = $(PRJ).c
OBJS = $(SRCS:.c=.o)
LINK = ../link/sp3sk-sram.ld
 
$(PRJ).srec: $(PRJ).out
mb-objcopy -O srec $(PRJ).out $(PRJ).srec
mb-objcopy -O binary $(PRJ).out $(PRJ).bin
..\..\utils\bin2rom $(PRJ).bin $(PRJ).rom
 
$(OBJS): $(SRCS)
mb-gcc -B. -mno-xl-soft-mul -c -Wa,-ahlms=$(@:.o=.lst) -o $@ $(@:.o=.c)
 
$(PRJ).out: $(CRT).o $(OBJS)
mb-ld -T $(LINK) -Map=$(PRJ).map -o $(PRJ).out $(CRT).o $(OBJS) $(LIBIO).o -lgcc -lc -lm -lgcc
clean:
-rm *.o
-rm *.out
-rm *.bin
-rm *.v
-rm *.map
-rm *.lst
-rm *.bak
-rm *.srec
-rm *.prom
-rm *.rom
/trunk/sw/lib/uart1io.c
0,0 → 1,46
/* libio
functions for low level use with libc
*/
 
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#ifndef NULL
#define NULL 0
#endif
 
#define UARTS_STATUS_REGISTER 0x08000004
#define UART1_DATA_PRESENT 0x01
#define UART1_TX_BUFFER_FULL 0x10
 
#define UART1_TXRX_DATA 0x08000008
 
/* errno handling in a reentrant way *TODO?* */
int *__errno(void)
{
return &errno;
}
/* outbyte -- shove a byte out the serial port. We wait till the byte */
int outbyte( unsigned char c)
{
while ( *(unsigned char *)UARTS_STATUS_REGISTER & UART1_TX_BUFFER_FULL );
return (*(unsigned char*) UART1_TXRX_DATA = c);
}
 
/* inbyte -- get a byte from the serial port with eco and translates \r --> \n*/
unsigned char inbyte(void)
{
unsigned char c;
while ( (*(unsigned char *)UARTS_STATUS_REGISTER & UART1_DATA_PRESENT) == 0x0 );
c = *(unsigned char*) UART1_TXRX_DATA;
if(c == '\r') c = '\n';
outbyte(c);
return c;
}
 
/* havebyte() -- poll if a byte is available in the serial port */
int havebyte(void)
{
return *(unsigned char *)UARTS_STATUS_REGISTER & UART1_DATA_PRESENT;
}
 
/trunk/sw/lib/Makefile
0,0 → 1,14
all:
mb-gcc -c -mno-xl-soft-mul -c -Wa,-ahlms=uart1io.lst -o uart1io.o uart1io.c
 
clean:
-rm *.o
-rm *.out
-rm *.bin
-rm *.v
-rm *.map
-rm *.lst
-rm *.bak
-rm *.srec
-rm *.prom
-rm *.rom
/trunk/sw/lib/openfire.h
0,0 → 1,43
/* peripherals address and configurations */
/* openfire soc - 20070327 - a.anton */
 
#define SP3SK_GPIO 0x08000000
 
#define SP3SK_GPIO_SEGMENTS_N 0x000000FF
#define SP3SK_GPIO_DRIVERS_N 0x00000F00
#define SP3SK_GPIO_PUSHBUTTONS 0x0000F000
#define SP3SK_GPIO_LEDS 0x00FF0000
#define SP3SK_GPIO_SWITCHES 0xFF000000
 
#define UARTS_STATUS_REGISTER 0x08000004
 
#define UART1_DATA_PRESENT 0x00000001
#define UART1_RX_HALF_FULL 0x00000002
#define UART1_RX_FULL 0x00000004
#define UART1_TX_HALF_FULL 0x00000008
#define UART1_TX_BUFFER_FULL 0x00000010
 
#define UART2_DATA_PRESENT 0x00010000
#define UART2_RX_HALF_FULL 0x00020000
#define UART2_RX_FULL 0x00040000
#define UART2_TX_HALF_FULL 0x00080000
#define UART2_TX_FULL 0x00100000
 
#define UART1_TXRX_DATA 0x08000008
#define UART2_TXRX_DATA 0x0800000C
 
#define PROM_READER 0x08000010
#define PROM_DATA 0x000000FF
#define PROM_REQUEST_SYNC 0x00000100
#define PROM_REQUEST_DATA 0x00000200
#define PROM_SYNCED 0x00000400
#define PROM_DATA_READY 0x00000800
 
#define TIMER1_PORT 0x08000014
#define TIMER1_VALUE 0x7FFFFFFF
#define TIMER1_CONTROL 0x80000000
 
#define INTERRUPT_ENABLE 0x08000018
#define INTERRUPT_TIMER1 0x00000001
#define INTERRUPT_UART1_RX 0x00000002
#define INTERRUPT_UART2_RX 0x00000004
/trunk/sw/crt/crt-bram.s
0,0 → 1,72
# crt.asm
# C RunTime:
# Used for initialization of small data
# anchors and stack for programs compiled using
# Xilinx Gnu Tools.
# Used for initialization of user's bss area
# All external and static variables are initialized
 
/* Vector map (Interrupts, Exceptions, Breakpoints) */
# # 0x00 # Jump to Start (reset vector)
# # 0x04 # nop
# # 0x08 # Imm instr for soft exception address [Hi halfword]
# # 0x0c # Jump to sof Exception handler [Lo halfword]
# # 0x10 # Imm instr for interrupt address [Hi halfword]
# # 0x14 # Jump to interrupt handler [Lo halfword]
# # 0x18 # nop - Reserved for breakpoint vector
# # 0x1C # nop - Reserved for breakpoint vector
# # 0x20 # Imm instr for hw exception address [Hi halfword]
# # 0x24 # Jump instr to hw exception handler [Lo halfword]
 
.globl _start
 
.align 2
.ent _start
_start:
bri _start1 # 0x00 # reset vector
nop # 0x04
nop # 0x08 # Reserve space for software exception vector
nop # 0x0c
nop # 0x10 # Reserve space for interrupt vector
nop # 0x14
nop # 0x18 # Reserve space for breakpoint vector
nop # 0x1c
nop # 0x18 # Reserve space for hw exception vector
nop # 0x1c
 
_start1: /* Set the Small Data Anchors and the Stack pointer */
la r13, r0, _SDA_BASE_
la r2, r0, _SDA2_BASE_
la r1, r0, _STACK_START # stack is at end of block-ram
_crtinit: /* clear sbss */
addi r6,r0,__sbss_start /* SBSS beginning */
addi r7,r0,__sbss_end /* SBSS end */
rsub r18,r6,r7 /* Compare */
blei r18,.Lendsbss
.Lloopsbss:
sw r0,r6,r0
addi r6,r6,4
rsub r18,r6,r7
bgti r18,.Lloopsbss
.Lendsbss: /* clear bss */
addi r6,r0,__bss_start /* BSS beginning */
addi r7,r0,__bss_end /* BSS end */
rsub r18,r6,r7 /* Compare */
blei r18,.Lendbss
.Lloopbss:
sw r0,r6,r0
addi r6,r6,4
rsub r18,r6,r7
bgti r18,.Lloopbss
.Lendbss:
 
brlid r15,main # enter main program (ignoring parameters: r5, r6 & r7)
nop # fall throught to exit
.end _start
 
.globl exit # exit library call
.ent exit
exit:
bri exit
.end exit
/trunk/sw/crt/crt-sram.s
0,0 → 1,51
# crt.asm
# C RunTime:
# Used for initialization of small data
# anchors and stack for programs compiled using
# Xilinx Gnu Tools.
# Used for initialization of user's bss area
# All external and static variables are initialized
 
.globl _start
 
.align 2
.ent _start
_start:
/* todo : initialize system vectors */
 
/* Set the Small Data Anchors and the Stack pointer */
la r13, r0, _SDA_BASE_
la r2, r0, _SDA2_BASE_
la r1, r0, _stack # stack is at end of heap
_crtinit: /* clear sbss */
addi r6,r0,__sbss_start /* SBSS beginning */
addi r7,r0,__sbss_end /* SBSS end */
rsub r18,r6,r7 /* Compare */
blei r18,.Lendsbss
.Lloopsbss:
sw r0,r6,r0
addi r6,r6,4
rsub r18,r6,r7
bgti r18,.Lloopsbss
.Lendsbss: /* clear bss */
addi r6,r0,__bss_start /* BSS beginning */
addi r7,r0,__bss_end /* BSS end */
rsub r18,r6,r7 /* Compare */
blei r18,.Lendbss
.Lloopbss:
sw r0,r6,r0
addi r6,r6,4
rsub r18,r6,r7
bgti r18,.Lloopbss
.Lendbss:
 
brlid r15,main # enter main program (ignoring parameters: r5, r6 & r7)
nop # fall throught to exit
.end _start
 
.globl exit # exit library call
.ent exit
exit:
brai 0x0 # enter monitor again...
.end exit
/trunk/sw/crt/crt-sram-with-int.s
0,0 → 1,57
# crt.asm
# C RunTime:
# Used for initialization of small data
# anchors and stack for programs compiled using
# Xilinx Gnu Tools.
# Used for initialization of user's bss area
# All external and static variables are initialized
 
.globl _start
 
.align 2
.ent _start
_start:
la r1,r0,__interrupt_vector_reload /* move interrupt vector call */
lwi r2,r1,0 /* to the vector position in block ram */
swi r2,r0,0x10
lwi r2,r1,4
swi r2,r0,0x14
/* Set the Small Data Anchors and the Stack pointer */
la r13, r0, _SDA_BASE_
la r2, r0, _SDA2_BASE_
la r1, r0, 0x040e2000 # stack is at end of sram (before video ram)
_crtinit: /* clear sbss */
addi r6,r0,__sbss_start /* SBSS beginning */
addi r7,r0,__sbss_end /* SBSS end */
rsub r18,r6,r7 /* Compare */
blei r18,.Lendsbss
.Lloopsbss:
sw r0,r6,r0
addi r6,r6,4
rsub r18,r6,r7
bgti r18,.Lloopsbss
.Lendsbss: /* clear bss */
addi r6,r0,__bss_start /* BSS beginning */
addi r7,r0,__bss_end /* BSS end */
rsub r18,r6,r7 /* Compare */
blei r18,.Lendbss
.Lloopbss:
sw r0,r6,r0
addi r6,r6,4
rsub r18,r6,r7
bgti r18,.Lloopbss
.Lendbss:
 
brlid r15,main # enter main program (ignoring parameters: r5, r6 & r7)
nop # fall throught to exit
.end _start
 
.globl exit # exit library call
.ent exit
exit:
brai 0x0 # enter monitor again...
.end exit
 
__interrupt_vector_reload:
brai interrupt_handler
/trunk/sw/crt/Makefile
0,0 → 1,16
all:
mb-as -a=crt-bram.lst -o crt-bram.o crt-bram.s
mb-as -a=crt-sram.lst -o crt-sram.o crt-sram.s
mb-as -a=crt-sram-with-int.lst -o crt-sram-with-int.o crt-sram-with-int.s
 
clean:
-rm *.o
-rm *.out
-rm *.bin
-rm *.v
-rm *.map
-rm *.lst
-rm *.bak
-rm *.srec
-rm *.prom
-rm *.rom
/trunk/sw/monc/Makefile
0,0 → 1,32
PRJ = monc
CRT = ../crt/crt-bram
SRCS = $(PRJ).c
OBJS = $(SRCS:.c=.o)
LINK = ../link/script-bram.ld
 
$(PRJ).v: $(PRJ).out
mb-objcopy -O binary $(PRJ).out $(PRJ).bin
..\..\utils\bin2bram ..\..\rtl\openfire_template_bootram.v $(PRJ).bin $(PRJ).v
 
$(PRJ).srec: $(PRJ).out
mb-objcopy -O srec $(PRJ).out $(PRJ).srec
mb-objcopy -O binary $(PRJ).out $(PRJ).bin
..\..\utils\bin2rom $(PRJ).bin $(PRJ).rom
 
$(OBJS): $(SRCS)
mb-gcc -B. -mno-xl-soft-mul -c -Wa,-ahlms=$(@:.o=.lst) -o $@ $(@:.o=.c)
 
$(PRJ).out: $(CRT).o $(OBJS)
mb-ld -T $(LINK) -Map=$(PRJ).map -o $(PRJ).out $(CRT).o $(OBJS)
clean:
-rm *.o
-rm *.out
-rm *.bin
-rm *.v
-rm *.map
-rm *.lst
-rm *.bak
-rm *.srec
-rm *.prom
-rm *.rom
/trunk/sw/monc/monc.c
0,0 → 1,304
/* simple boot monitor in c
for the openfire soc
a.anton 27/02/2007 */
/* ----------------------------------------
S{1,2,3}xxxxx --> Motorola S-record
l --> load from PROM at SRAM start
x <hex32> --> execute code at @
d <hex32> <hex32> {1,2,4} --> dump starting at <hex32>, len=<hex32>, 1(bytes),2(halfw),4(words)
w <hex32> <hex32> {1,2,4} --> write at <hex32> value=<hex32> 1(byte), 2(halfw), 4(word)
f <hex32> <hex32> <hex32> --> fill starting at <hex32>, len=<hex32>, value=<hex32> (word)
---------------------------------------- */
 
#define UARTS_STATUS_PORT 0x08000004
#define UART1_TX_FULL 0x10
#define UART1_DATA_AVAILABLE 0x01
 
#define UART1_TXRX 0x08000008
 
#define PROM_DATA 0x08000010
#define PROM_CONTROL 0x08000011
#define REQUEST_SYNC 0x01
#define REQUEST_BYTE 0x02
#define IS_PROM_SYNCED 0x04
#define IS_DATA_AVAILABLE 0x08
 
#define SRAM_START 0x04000000
 
#define MAX_LINE 128
#define BYTES_PER_LINE 16
 
// -------------------------------------
 
void uart1_printchar(unsigned char);
void uart1_printline(char *);
char uart1_readchar(void);
void uart1_readline(char *);
 
unsigned gethexchar(char);
unsigned ishexdigit(char);
char *gethex(char *, unsigned *, unsigned);
 
char puthexchar(unsigned);
void puthexstring(char *, unsigned, unsigned);
 
void process_Sline(void);
void dump(unsigned, int, unsigned);
void write(unsigned, unsigned, unsigned);
void fill(unsigned, int, unsigned);
void load_promfile(unsigned);
unsigned char prom_readbyte(void);
 
// -------------------------------------
 
char banner[] = "MONC1\r\n";
char prompt[] = "$ ";
char linefeed[] = "\r\n";
char error[] = "ERROR\r\n";
char nofile[] = "No file\r\n";
char loading[] = "Loading...\r\n";
 
char input_buffer[MAX_LINE]; // = "d 0000 0010 1"; // input buffer (temporal)
 
// -------------------------------------
 
void main(void)
{
unsigned p1, p2, p3;
char *ptr;
uart1_printline(banner);
main_loop:
uart1_printline(prompt);
uart1_readline(input_buffer);
uart1_printline(linefeed);
 
switch(input_buffer[0])
{
case 'd' :
case 'w' :
case 'f' :
ptr = gethex(input_buffer + 2, &p1, 8); // start address
ptr = gethex(ptr + 1, &p2, 8); // lenght or value
ptr = gethex(ptr + 1, &p3, 8); // width=1,2,4 or value
if(input_buffer[0] == 'd') dump(p1, p2, p3);
else if(input_buffer[0] == 'w') write(p1, p2, p3);
else fill(p1, p2, p3);
break;
case 'S' : process_Sline();
break;
case 'l' : gethex(input_buffer + 2, &p1, 2); // file-id
load_promfile(p1);
break;
case 'x' : gethex(input_buffer + 2, &p1, 8);
((void (*)(void))p1)();
break;
}
goto main_loop;
}
 
// --------- uart #1 functions ----------
void uart1_printchar(unsigned char c)
{
while( (*(unsigned char *) UARTS_STATUS_PORT) & UART1_TX_FULL ); // wait empty buffer
*(char *) UART1_TXRX = c;
}
 
void uart1_printline(char *txt)
{
while( *(unsigned char *)txt ) uart1_printchar( (unsigned char) *(txt++));
}
 
char uart1_readchar(void)
{
while( ((*(unsigned char *) UARTS_STATUS_PORT) & UART1_DATA_AVAILABLE) == 0 ); // wait a received char
return *(char *) UART1_TXRX;
}
 
void uart1_readline(char *buffer)
{
char tmp;
do
{
*(buffer++) = tmp = uart1_readchar();
uart1_printchar(tmp);
} while(tmp != 0x0 && tmp != '\n' && tmp != '\r');
}
 
// ------------ ascii 2 hex -------------
unsigned gethexchar(char c)
{
if(c >= 'a') c = c - 'a' + '0' + 10;
else if(c >= 'A') c = c - 'A' + '0' + 10;
return c - '0';
}
 
unsigned ishexdigit(char c)
{
return (c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F');
}
 
char *gethex(char *string, unsigned *value, unsigned maxdigits)
{
unsigned number = 0;
while( ishexdigit( string[0] ) && maxdigits > 0)
{
number <<= 4;
number |= gethexchar(string[0]);
string++;
maxdigits--;
}
*value = number;
return string;
}
// ----------- hex 2 ascii ------------------
char puthexchar(unsigned n)
{
n &= 0xF;
return n + (n < 10 ? '0' : 'A' - 10);
}
 
void puthexstring(char *string, unsigned number, unsigned size)
{
int n = size - 1;
while(number && n >= 0) // hex 2 ascii right to left
{
string[n] = puthexchar(number & 0xf);
number >>= 4;
n--;
}
while(n >= 0) string[n--] = '0'; // left padding with 0
}
 
// --------------------------------------------------------------
// process S1, S2 and S3 records
// http://www.amelek.gda.pl/avr/uisp/srecord.htm
 
void process_Sline(void)
{
int tipo = input_buffer[1] - '0';
unsigned rec_len, address, checksum = 0, pos, byte, tmp;
 
if(tipo < 1 || tipo > 3) return; // process 1, 2 or 3 records only
 
gethex(input_buffer + 2, &rec_len, 2); // number of bytes in the record (address+data+checksum)
checksum += rec_len;
gethex(input_buffer + 4, &address, tipo == 1 ? 4 : (tipo == 2 ? 6 : 8) ); // read start address
pos = 4 + 2 + (tipo << 1); // 1st byte of data is at...
rec_len -= tipo == 1 ? 2 : (tipo == 2 ? 3 : 4);
tmp = address;
while(tipo >= 0) // compute address checksum
{
checksum += tmp & 0xff;
tmp >>= 8;
tipo--;
}
 
while(rec_len-- > 1) // read all data bytes and store in memory
{
gethex(input_buffer + pos, &byte, 2); // read byte
*(unsigned char *)address++ = (unsigned char) byte;
checksum += byte;
pos += 2;
}
 
gethex(input_buffer + pos, &byte, 2); // read checksum
checksum += byte;
if( (checksum & 0xff) != 0xff) uart1_printline(error); // verify checksum
}
 
// ---------- dump memory region --------------------------------
void dump(unsigned start, int len, unsigned width)
{
unsigned n = 0, pos, v;
while(len > 0)
{
if(n == 0) // init line: current address
{
puthexstring(input_buffer, start, 8);
input_buffer[8] = ' ';
pos = 9;
}
 
if(width == 1) v = *(unsigned char *)start; // fetch data
else if(width == 2) v = *(unsigned short *)start;
else v = *(unsigned *)start;
start += width; // next address
puthexstring(input_buffer + pos, v, width << 1); // data 2 ascii
pos += (width << 1);
input_buffer[pos++] = ' ';
n += width;
len -= width;
if(n >= BYTES_PER_LINE) // end of line
{
showline:
input_buffer[pos++] = '\r';
input_buffer[pos++] = '\n';
input_buffer[pos] = 0x0;
uart1_printline(input_buffer);
n = 0;
}
}
if(n != 0) goto showline; // hack to print incomplete lines
}
 
// ---------- write data to memory -------------
void write(unsigned address, unsigned value, unsigned width)
{
if(width == 1) *(unsigned char *)address = (unsigned char) value;
else if(width == 2) *(unsigned short *)address = (unsigned short) value;
else *(unsigned *)address = value;
}
 
// ----------- fill memory with dword ----------
void fill(unsigned start, int len, unsigned value)
{
while(len-- > 0) *(unsigned *)(start++) = value;
}
 
// ----------- load file from prom ----------
void load_promfile(unsigned file_id)
{
unsigned char *ptr = (unsigned char *)SRAM_START; // start of SRAM
unsigned char status, data;
unsigned fileno, size;
 
status = *(unsigned char *) PROM_CONTROL;
if( !(status & IS_PROM_SYNCED) ) // not in sync .. exit
{
uart1_printline(nofile);
return;
}
uart1_printline(loading);
fileno = prom_readbyte(); // ignore at the moment...
size = prom_readbyte(); // MSByte
size <<= 8;
size |= prom_readbyte();
size <<= 8;
size |= prom_readbyte(); // LSBbyte
while(size-- > 0) // read file
*(unsigned char *) ptr++ = prom_readbyte();
}
unsigned char prom_readbyte(void)
{
*(unsigned char *) PROM_CONTROL = REQUEST_BYTE; // request byte
while( !(*(unsigned char *) PROM_CONTROL & IS_DATA_AVAILABLE) ); // wait for data
*(unsigned char *) PROM_CONTROL = 0;
return *(unsigned char *) PROM_DATA; // return byte
}
/trunk/sw/link/script-bram.ld
0,0 → 1,139
SEARCH_DIR(/cygdrive/c/edk/gnu/microblaze/nt/microblaze/lib);
_STACK_START = DEFINED(_STACK_START) ? _STACK_START : 0x2000; /* initial stack at end of block-ram */
 
ENTRY (_start)
MEMORY {
flatmem : ORIGIN = 0x0, LENGTH = 0xfffffff /* flat memory model */
}
 
SECTIONS {
.text 0x0 : {
. = ALIGN(0x4) ;
_stext = . ;
*(.text)
*(.text.*)
*(.gnu.warning)
*(.stub)
*(.gnu.linkonce.t*)
*(.glue_7t)
*(.glue_7)
*(.jcr)
*(.init)
*(.fini)
 
*(.rodata)
*(.rodata1)
*(.rodata.*)
 
/* This is special code area at the end of the normal
text section. It contains a small lookup table at
the start followed by the code pointed to by entries
in the lookup table. */
. = ALIGN (0x4) ;
PROVIDE(__ctbp = .);
*(.call_table_data)
*(.call_table_text)
 
. = ALIGN(0x4) ;
_etext = . ;
} > flatmem
.data : {
. = ALIGN(0x4) ;
_sdata = . ;
__data_start = . ;
data_start = . ;
*(.got.plt)
*(.got)
/* FILL(0) ;
. = ALIGN(0x04) ;
LONG(-1)
. = ALIGN(0x04) ; */
*(.rodata)
*(.rodata1)
*(.rodata.*)
*(.gnu.linkonce.r*)
*(.data)
*(.data1)
*(.data.*)
*(.gnu.linkonce.d*)
*(.data1)
*(.eh_frame)
*(.gcc_except_table)
 
/* Microblaze has .sdata and .sbss (small bss). They must
be contiguous, so please don't move any of this. JW */
_ssrw = . ;
*(.sdata)
*(.sdata.*)
__sbss_start = . ;
*(.sbss) /* Don't move this! */
__sbss_end = . ;
_essrw = . ;
 
_ssrw_size = _essrw - _ssrw;
PROVIDE(_SDA_BASE_ = _ssrw + (_ssrw_size / 2));
 
*(.gnu.linkonce.s.*)
*(__libc_atexit)
*(__libc_subinit)
*(__libc_subfreeres)
*(.note.ABI-tag)
 
/* microblaze-specific read-only small data area
and associated locating symbols */
_ssro = . ;
*(.sdata2)
_essro = . ;
_ssro_size = _essro - _ssro;
PROVIDE(_SDA2_BASE_ = _ssro + (_ssro_size / 2));
 
. = ALIGN(4) ;
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
 
. = ALIGN(0x4) ;
_edata = . ;
} > flatmem
.bss : {
. = ALIGN(0x4) ;
_sbss = ALIGN(0x4) ;
__bss_start = . ;
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.scommon)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.bss*)
*(.gnu.linkonce.b*)
*(COMMON)
__bss_end = . ;
_ebss = . ;
_end = . ;
end = . ;
} > flatmem
 
.junk 0 : { *(.rel*) *(.rela*) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}
/trunk/sw/link/sp3sk-sram.ld
0,0 → 1,169
SEARCH_DIR(/cygdrive/c/xilinx/microblaze/bin/../lib/gcc/microblaze/3.4.1);
SEARCH_DIR(/cygdrive/c/xilinx/microblaze/bin/../lib/gcc);
SEARCH_DIR(/cygdrive/c/xilinx/microblaze/bin/../lib/gcc/microblaze/3.4.1/../../../../microblaze/lib);
 
SEARCH_DIR(/cygdrive/d/xilinx/microblaze/bin/../lib/gcc/microblaze/3.4.1);
SEARCH_DIR(/cygdrive/d/xilinx/microblaze/bin/../lib/gcc);
SEARCH_DIR(/cygdrive/d/xilinx/microblaze/bin/../lib/gcc/microblaze/3.4.1/../../../../microblaze/lib);
 
/*INPUT( -lgcc );*/
/*GROUP( libxil.a libc.a libm.a );
INPUT( -lgcc );*/
 
ENTRY(_start)
 
_TEXT_START_ADDR = DEFINED(_TEXT_START_ADDR) ? _TEXT_START_ADDR : 0x04000000; /* SRAM start */
_MEMORY_SIZE = DEFINED(_MEMORY_SIZE) ? _MEMORY_SIZE : 0x00100000; /* SRAM size (1Mbyte) */
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x00008000; /* Stack size */
_VIDEO_RAM_ADDR = DEFINED(_VIDEO_RAM_ADDR) ? _VIDEO_RAM_ADDR : 0x040E2000; /* VRAM start */
 
SECTIONS
{
. = _TEXT_START_ADDR;
_ftext = .;
.text : {
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
}
_etext = .;
.init : { KEEP (*(.init)) } =0
.fini : { KEEP (*(.fini)) } =0
PROVIDE (__CTOR_LIST__ = .);
PROVIDE (___CTOR_LIST__ = .);
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
PROVIDE (__CTOR_END__ = .);
PROVIDE (___CTOR_END__ = .);
PROVIDE (__DTOR_LIST__ = .);
PROVIDE (___DTOR_LIST__ = .);
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
PROVIDE (__DTOR_END__ = .);
PROVIDE (___DTOR_END__ = .);
. = ALIGN(4);
_frodata = . ;
.rodata : {
*(.rodata)
*(.gnu.linkonce.r.*)
CONSTRUCTORS; /* Is this needed? */
}
_erodata = .;
/* Alignments by 8 to ensure that _SDA2_BASE_ on a word boundary */
/* Note that .sdata2 and .sbss2 must be contiguous */
. = ALIGN(8);
_ssrw = .;
.sdata2 : {
*(.sdata2)
*(.gnu.linkonce.s2.*)
}
. = ALIGN(4);
.sbss2 : {
PROVIDE (__sbss2_start = .);
*(.sbss2)
*(.gnu.linkonce.sb2.*)
PROVIDE (__sbss2_end = .);
}
. = ALIGN(8);
_essrw = .;
_ssrw_size = _essrw - _ssrw;
PROVIDE (_SDA2_BASE_ = _ssrw + (_ssrw_size / 2 ));
. = ALIGN(4);
_fdata = .;
.data : {
*(.data)
*(.gnu.linkonce.d.*)
CONSTRUCTORS; /* Is this needed? */
}
_edata = . ;
/* Added to handle pic code */
.got : {
*(.got)
}
.got1 : {
*(.got1)
}
.got2 : {
*(.got2)
}
/* Added by Sathya to handle C++ exceptions */
.eh_frame : {
*(.eh_frame)
}
.jcr : {
*(.jcr)
}
.gcc_except_table : {
*(.gcc_except_table)
}
/* Alignments by 8 to ensure that _SDA_BASE_ on a word boundary */
/* Note that .sdata and .sbss must be contiguous */
. = ALIGN(8);
_ssro = .;
.sdata : {
*(.sdata)
*(.gnu.linkonce.s.*)
}
. = ALIGN(4);
.sbss : {
PROVIDE (__sbss_start = .);
*(.sbss)
*(.gnu.linkonce.sb.*)
PROVIDE (__sbss_end = .);
}
. = ALIGN(8);
_essro = .;
_ssro_size = _essro - _ssro;
PROVIDE (_SDA_BASE_ = _ssro + (_ssro_size / 2 ));
. = ALIGN(4);
_fbss = .;
.bss : {
PROVIDE (__bss_start = .);
*(.bss)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
PROVIDE (__bss_end = .);
_heap = .;
_heap_start = .;
. = (_VIDEO_RAM_ADDR - _STACK_SIZE - 16);
_heap_end = .;
_stack_end = .;
. += _STACK_SIZE;
. = ALIGN(8);
_stack = .;
_end = .;
_HEAP_SIZE = _heap_end - _heap_start; /* calculate heap size */
}
.tdata : {
*(.tdata)
*(.gnu.linkonce.td.*)
}
.tbss : {
*(.tbss)
*(.gnu.linkonce.tb.*)
}
}
/trunk/sw/link/script-sram.ld
0,0 → 1,149
SEARCH_DIR(/cygdrive/c/edk/gnu/microblaze/nt/lib/gcc/microblaze/3.4.1);
SEARCH_DIR(/cygdrive/c/edk/gnu/microblaze/nt/microblaze/lib);
 
SEARCH_DIR(/cygdrive/d/xilinx/microblaze/lib/gcc/microblaze/3.4.1);
SEARCH_DIR(/cygdrive/d/xilinx/microblaze/microblaze/lib);
 
_STACK_START = DEFINED(_STACK_START) ? _STACK_START : 0x040e2000; /* initial stack at end of sram (non video)*/
_SRAM_START = DEFINED(_SRAM_START) ? _SRAM_START : 0x04000000; /* external sram starts here */
 
INPUT( -lgcc );
GROUP( libc.a libm.a );
INPUT( -lgcc );
 
ENTRY (_start)
MEMORY {
flatmem : ORIGIN = 0x0, LENGTH = 0xfffffff /* flat memory model */
}
 
SECTIONS {
.text _SRAM_START : {
. = ALIGN(0x4) ;
_stext = . ;
*(.text)
*(.text.*)
*(.gnu.warning)
*(.stub)
*(.gnu.linkonce.t*)
*(.glue_7t)
*(.glue_7)
*(.jcr)
*(.init)
*(.fini)
 
*(.rodata)
*(.rodata1)
*(.rodata.*)
 
/* This is special code area at the end of the normal
text section. It contains a small lookup table at
the start followed by the code pointed to by entries
in the lookup table. */
. = ALIGN (0x4) ;
PROVIDE(__ctbp = .);
*(.call_table_data)
*(.call_table_text)
 
. = ALIGN(0x4) ;
_etext = . ;
} > flatmem
.data : {
. = ALIGN(0x4) ;
_sdata = . ;
__data_start = . ;
data_start = . ;
*(.got.plt)
*(.got)
/* FILL(0) ;
. = ALIGN(0x04) ;
LONG(-1)
. = ALIGN(0x04) ; */
*(.rodata)
*(.rodata1)
*(.rodata.*)
*(.gnu.linkonce.r*)
*(.data)
*(.data1)
*(.data.*)
*(.gnu.linkonce.d*)
*(.data1)
*(.eh_frame)
*(.gcc_except_table)
 
/* Microblaze has .sdata and .sbss (small bss). They must
be contiguous, so please don't move any of this. JW */
_ssrw = . ;
*(.sdata)
*(.sdata.*)
__sbss_start = . ;
*(.sbss) /* Don't move this! */
__sbss_end = . ;
_essrw = . ;
 
_ssrw_size = _essrw - _ssrw;
PROVIDE(_SDA_BASE_ = _ssrw + (_ssrw_size / 2));
 
*(.gnu.linkonce.s.*)
*(__libc_atexit)
*(__libc_subinit)
*(__libc_subfreeres)
*(.note.ABI-tag)
 
/* microblaze-specific read-only small data area
and associated locating symbols */
_ssro = . ;
*(.sdata2)
_essro = . ;
_ssro_size = _essro - _ssro;
PROVIDE(_SDA2_BASE_ = _ssro + (_ssro_size / 2));
 
. = ALIGN(4) ;
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
 
. = ALIGN(0x4) ;
_edata = . ;
} > flatmem
.bss : {
. = ALIGN(0x4) ;
_sbss = ALIGN(0x4) ;
__bss_start = . ;
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.scommon)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.bss*)
*(.gnu.linkonce.b*)
*(COMMON)
__bss_end = . ;
_ebss = . ;
_end = . ;
end = . ;
} > flatmem
 
.junk 0 : { *(.rel*) *(.rela*) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}
/trunk/sw/vga/vga_5x7_putline.c
0,0 → 1,20
#include "vga.h"
 
void vga_putline5x7(char *s, unsigned short x, unsigned short y)
{
unsigned c;
while( (c = *(s++)) != 0 )
{
if(c == '\r') x = 0;
else if(c == '\n') { x = 0; y++; }
else
{
if(c < 0x20 || c > 0x7f) c = '?';
vga_putchar5x7(c, x, y);
x++;
if(x == 128) { x = 0; y++; }
if(y == 68) y = 0;
}
}
}
/trunk/sw/vga/vga.h
0,0 → 1,17
/* datos para el vga 5x7 */
extern unsigned short bitmap_font_5x7[];
extern unsigned short background_5x7;
extern unsigned short foreground_5x7;
extern unsigned short colores_5x7[];
extern unsigned short xpos_5x7;
extern unsigned short ypos_5x7;
extern unsigned _VIDEO_RAM_ADDR;
 
void vga_putchar5x7(char caracter, unsigned short pos_x, unsigned short pos_y);
void vga_putline5x7(char *s, unsigned short x, unsigned short y);
void vga_setfgcolor5x7(unsigned short color);
void vga_setbgcolor5x7(unsigned short color);
 
/* funciones vga generales */
void vga_clearscreen(void);
void vga_drawpixel(unsigned short x, unsigned short y, unsigned short color);
/trunk/sw/vga/vga_5x7_setbgcolor.c
0,0 → 1,6
#include "vga.h"
 
void vga_setbgcolor5x7(unsigned short color)
{
background_5x7 = colores_5x7[color];
}
/trunk/sw/vga/vga_clearscreen.c
0,0 → 1,7
#include "vga.h"
 
void vga_clearscreen(void)
{
unsigned *ptr = (unsigned *)&_VIDEO_RAM_ADDR, n;
for(n = 0; n < 64 * 480; n++) *(ptr++) = background_5x7;
}
/trunk/sw/vga/vga_5x7_fuente.c
0,0 → 1,110
#include "vga.h"
 
/* fuente de 5x7 en vga de 640x480 --> 128 x 68 */
/* ---------------------------------------------- */
unsigned short bitmap_font_5x7[96 * 7] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x20 -espacio- */
0x01C0, 0x01C0, 0x01C0, 0x0000, 0x01C0, 0x0000, 0x0000, /* cada word es: 0 RGB RGB RGB RGB RGB */
0x0E38, 0x0E38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* siendo R=G=B, ocupa el doble de espacio */
0x0E38, 0x7FFF, 0x0E38, 0x7FFF, 0x0E38, 0x0000, 0x0000, /* pero ahorra muchos ciclos de reloj */
0x0FF8, 0x71C0, 0x0FF8, 0x01C7, 0x0FF8, 0x0000, 0x0000,
0x7E07, 0x7E38, 0x01C0, 0x0E3F, 0x703F, 0x0000, 0x0000,
0x0FC0, 0x0E38, 0x0FC0, 0x7038, 0x0FC7, 0x0000, 0x0000,
0x01C0, 0x0E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x01C0, 0x0E00, 0x0E00, 0x0E00, 0x01C0, 0x0000, 0x0000,
0x01C0, 0x0038, 0x0038, 0x0038, 0x01C0, 0x0000, 0x0000,
0x71C7, 0x0FF8, 0x01C0, 0x0FF8, 0x71C7, 0x0000, 0x0000,
0x01C0, 0x01C0, 0x7FFF, 0x01C0, 0x01C0, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x01F8, 0x0038, 0x01C0, 0x0000,
0x0000, 0x0000, 0x7FFF, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x01F8, 0x01F8, 0x0000, 0x0000,
0x0007, 0x0038, 0x01C0, 0x0E00, 0x7000, 0x0000, 0x0000,
0x0FF8, 0x7007, 0x71C7, 0x7007, 0x0FF8, 0x0000, 0x0000,
0x01C0, 0x0FC0, 0x01C0, 0x01C0, 0x0FF8, 0x0000, 0x0000,
0x0FF8, 0x0007, 0x0FF8, 0x7000, 0x7FFF, 0x0000, 0x0000,
0x0FF8, 0x0007, 0x0FF8, 0x0007, 0x0FF8, 0x0000, 0x0000,
0x7038, 0x7038, 0x7FFF, 0x0038, 0x0038, 0x0000, 0x0000,
0x7FF8, 0x7000, 0x7FF8, 0x0007, 0x7FF8, 0x0000, 0x0000,
0x0FF8, 0x7000, 0x7FF8, 0x7007, 0x0FF8, 0x0000, 0x0000,
0x7FFF, 0x0038, 0x01C0, 0x01C0, 0x01C0, 0x0000, 0x0000,
0x0FF8, 0x7007, 0x0FF8, 0x7007, 0x0FF8, 0x0000, 0x0000,
0x0FF8, 0x7007, 0x0FFF, 0x0007, 0x0FF8, 0x0000, 0x0000,
0x0000, 0x01F8, 0x01F8, 0x0000, 0x01F8, 0x01F8, 0x0000,
0x0000, 0x01F8, 0x01F8, 0x0000, 0x01F8, 0x0FC0, 0x0000,
0x0038, 0x01C0, 0x0E00, 0x01C0, 0x0038, 0x0000, 0x0000,
0x0000, 0x7FFF, 0x0000, 0x7FFF, 0x0000, 0x0000, 0x0000,
0x0E00, 0x01C0, 0x0038, 0x01C0, 0x0E00, 0x0000, 0x0000,
0x0FF8, 0x0007, 0x01F8, 0x0000, 0x01C0, 0x0000, 0x0000,
0x0FF8, 0x71FF, 0x71FF, 0x7000, 0x0FF8, 0x0000, 0x0000,
0x0FF8, 0x7007, 0x7FFF, 0x7007, 0x7007, 0x0000, 0x0000,
0x7FF8, 0x7007, 0x7FF8, 0x7007, 0x7FF8, 0x0000, 0x0000,
0x0FF8, 0x7000, 0x7000, 0x7000, 0x0FF8, 0x0000, 0x0000,
0x7FF8, 0x7007, 0x7007, 0x7007, 0x7FF8, 0x0000, 0x0000,
0x7FFF, 0x7000, 0x7FC0, 0x7000, 0x7FFF, 0x0000, 0x0000,
0x7FFF, 0x7000, 0x7FF8, 0x7000, 0x7000, 0x0000, 0x0000,
0x0FF8, 0x7000, 0x703F, 0x7007, 0x0FF8, 0x0000, 0x0000,
0x7007, 0x7007, 0x7FFF, 0x7007, 0x7007, 0x0000, 0x0000,
0x0FF8, 0x01C0, 0x01C0, 0x01C0, 0x0FF8, 0x0000, 0x0000,
0x0007, 0x0007, 0x0007, 0x7007, 0x0FF8, 0x0000, 0x0000,
0x7007, 0x7038, 0x7FC0, 0x7038, 0x7007, 0x0000, 0x0000,
0x7000, 0x7000, 0x7000, 0x7000, 0x7FFF, 0x0000, 0x0000,
0x7007, 0x7E3F, 0x71C7, 0x7007, 0x7007, 0x0000, 0x0000,
0x7007, 0x7E07, 0x71C7, 0x703F, 0x7007, 0x0000, 0x0000,
0x0FF8, 0x7007, 0x7007, 0x7007, 0x0FF8, 0x0000, 0x0000,
0x7FF8, 0x7007, 0x7FF8, 0x7000, 0x7000, 0x0000, 0x0000,
0x0FF8, 0x7007, 0x7007, 0x703F, 0x0FFF, 0x0000, 0x0000,
0x7FF8, 0x7007, 0x7FF8, 0x7038, 0x7007, 0x0000, 0x0000,
0x0FF8, 0x7000, 0x0FF8, 0x0007, 0x0FF8, 0x0000, 0x0000,
0x7FFF, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x0000, 0x0000,
0x7007, 0x7007, 0x7007, 0x7007, 0x0FF8, 0x0000, 0x0000,
0x7007, 0x7007, 0x0E38, 0x0E38, 0x01C0, 0x0000, 0x0000,
0x7007, 0x7007, 0x71C7, 0x71C7, 0x0E38, 0x0000, 0x0000,
0x7007, 0x0E38, 0x01C0, 0x0E38, 0x7007, 0x0000, 0x0000,
0x7007, 0x0E38, 0x01C0, 0x01C0, 0x01C0, 0x0000, 0x0000,
0x7FFF, 0x0038, 0x01C0, 0x0E00, 0x7FFF, 0x0000, 0x0000,
0x0FF8, 0x0E00, 0x0E00, 0x0E00, 0x0FF8, 0x0000, 0x0000,
0x7000, 0x0E00, 0x01C0, 0x0038, 0x0007, 0x0000, 0x0000,
0x0FF8, 0x0038, 0x0038, 0x0038, 0x0FF8, 0x0000, 0x0000,
0x01C0, 0x0E38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x7FFF, 0x0000, 0x0000,
0x0E00, 0x0E00, 0x01C0, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0FC0, 0x0038, 0x7FF8, 0x0FF8, 0x0000, 0x0000,
0x7000, 0x7FC0, 0x7038, 0x7038, 0x7FC0, 0x0000, 0x0000,
0x0000, 0x0FF8, 0x7000, 0x7000, 0x0FF8, 0x0000, 0x0000,
0x0038, 0x0FF8, 0x7038, 0x7038, 0x0FF8, 0x0000, 0x0000,
0x0000, 0x0FC0, 0x7FF8, 0x7000, 0x0FC0, 0x0000, 0x0000,
0x01C0, 0x0E00, 0x7FC0, 0x0E00, 0x0E00, 0x0000, 0x0000,
0x0000, 0x0FC0, 0x7038, 0x7038, 0x0FF8, 0x0038, 0x0FC0,
0x7000, 0x7FC0, 0x7038, 0x7038, 0x7038, 0x0000, 0x0000,
0x0000, 0x0FC0, 0x01C0, 0x01C0, 0x0FF8, 0x0000, 0x0000,
0x0000, 0x01F8, 0x0038, 0x0038, 0x0038, 0x7038, 0x0FC0,
0x7000, 0x7038, 0x7FC0, 0x7FC0, 0x7038, 0x0000, 0x0000,
0x0FC0, 0x01C0, 0x01C0, 0x01C0, 0x0FF8, 0x0000, 0x0000,
0x0000, 0x7E38, 0x71C7, 0x7007, 0x7007, 0x0000, 0x0000,
0x0000, 0x7FC0, 0x7038, 0x7038, 0x7038, 0x0000, 0x0000,
0x0000, 0x0FC0, 0x7038, 0x7038, 0x0FC0, 0x0000, 0x0000,
0x0000, 0x7FC0, 0x7038, 0x7038, 0x7FC0, 0x7000, 0x7000,
0x0000, 0x0FF8, 0x7038, 0x7038, 0x0FF8, 0x0038, 0x0038,
0x0000, 0x7FC0, 0x7038, 0x7000, 0x7000, 0x0000, 0x0000,
0x0000, 0x0FF8, 0x7E00, 0x01F8, 0x7FC0, 0x0000, 0x0000,
0x01C0, 0x0FF8, 0x01C0, 0x01C0, 0x01C0, 0x0000, 0x0000,
0x0000, 0x7038, 0x7038, 0x7038, 0x0FF8, 0x0000, 0x0000,
0x0000, 0x7038, 0x7038, 0x71C0, 0x0E00, 0x0000, 0x0000,
0x0000, 0x7007, 0x7007, 0x71C7, 0x0E38, 0x0000, 0x0000,
0x0000, 0x7038, 0x0FC0, 0x0FC0, 0x7038, 0x0000, 0x0000,
0x0000, 0x7038, 0x7038, 0x7038, 0x0FF8, 0x0038, 0x0FC0,
0x0000, 0x7FF8, 0x01C0, 0x0E00, 0x7FF8, 0x0000, 0x0000,
0x01C0, 0x0E00, 0x7FC0, 0x0E00, 0x01C0, 0x0000, 0x0000,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x01C0, 0x0038, 0x01FF, 0x0038, 0x01C0, 0x0000, 0x0000,
0x0E00, 0x71C7, 0x0038, 0x0000, 0x0000, 0x0000, 0x0000,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, /* 0x7f --- */
};
 
/* ---------------------------------------------- */
unsigned short background_5x7 = 0x0000; /* background */
unsigned short foreground_5x7 = 0x7FFF; /* mascara para el color de los textos */
unsigned short colores_5x7[] = /* mascaras para los colores */
{ 0x0000, 0x1249, 0x2492, 0x36DB, 0x4924, 0x5b6d, 0x6db6, 0x7fff };
unsigned short xpos_5x7 = 0;
unsigned short ypos_5x7 = 0;
/trunk/sw/vga/vga_5x7_putchar.c
0,0 → 1,17
#include "vga.h"
 
/* ---------------------------------------------- */
void vga_putchar5x7(char caracter, unsigned short pos_x, unsigned short pos_y)
{
unsigned short y, scanline, row, scan;
unsigned ptr = (unsigned)&_VIDEO_RAM_ADDR;
 
scanline = (caracter - 0x20) * 7; /* bitmap del caracter a mostrar */
y = pos_y * 7; /* 7 bits de alto por caracter */
for(row = 0; row < 7; row++) /* procesamos el caracter */
{ /* pintamos la linea */
scan = bitmap_font_5x7[scanline++];
*(unsigned short *) (ptr + (y++ * 256) + pos_x * 2) = (scan & foreground_5x7) | (background_5x7 & ~scan);
}
}
/trunk/sw/vga/vga_5x7_setfgcolor.c
0,0 → 1,6
#include "vga.h"
 
void vga_setfgcolor5x7(unsigned short color)
{
foreground_5x7 = colores_5x7[color];
}
/trunk/sw/vga/Makefile
0,0 → 1,33
PRJ = vga
CRT = ../crt/crt-sram
LIB = vga_5x7_fuente.c vga_5x7_putchar.c vga_5x7_putline.c vga_5x7_setfgcolor.c vga_5x7_setbgcolor.c vga_clearscreen.c vga_drawpixel.c
SRCS = $(PRJ).c $(LIB)
OBJS = $(SRCS:.c=.o) ../lib/uart1io.o
LINK = ../link/sp3sk-sram.ld
 
$(PRJ).srec: $(PRJ).out
mb-objcopy -O srec $(PRJ).out $(PRJ).srec
mb-objcopy -O binary $(PRJ).out $(PRJ).bin
..\..\utils\bin2rom $(PRJ).bin $(PRJ).rom
 
libvga:
--rm $(PRJ).a
mb-ar q lib$(PRJ).a $(OBJS)
 
$(OBJS): $(SRCS)
mb-gcc -B. -mno-xl-soft-mul -c -Wa,-ahlms=$(@:.o=.lst) -o $@ $(@:.o=.c)
 
$(PRJ).out: $(CRT).o $(OBJS)
mb-ld -T $(LINK) -Map=$(PRJ).map -o $(PRJ).out $(CRT).o $(OBJS) -lgcc -lc -lm -lgcc
clean:
-rm *.o
-rm *.out
-rm *.bin
-rm *.v
-rm *.map
-rm *.lst
-rm *.bak
-rm *.srec
-rm *.prom
-rm *.rom
/trunk/sw/vga/vga_drawpixel.c
0,0 → 1,21
#include "vga.h"
 
void vga_drawpixel(unsigned short x, unsigned short y, unsigned short color)
{
unsigned ptr = (unsigned) &_VIDEO_RAM_ADDR;
unsigned short pixel, mascara = 0x7;
unsigned short w = x / 5; /* word donde esta el pixel */
unsigned short p = 12 - (x % 5) * 3; /* obtenemos el # de pixel dentro del grupo */
ptr += y * 256 + w * 2;
pixel = *(unsigned short *) ptr; /* obtenemos el valor del grupo de 5 pixels */
mascara = ~(0x7 << p); /* mascara para el pixel */
color <<= p; /* ponemos el pixel en su sitio */
pixel &= mascara; /* aplicamos la mascara en el pixel actual */
pixel |= color; /* dibujamos el pixel en el hueco de la mascara */
*(unsigned short *) ptr = pixel;
}
/trunk/sw/vga/vga.c
0,0 → 1,50
#include "vga.h"
#include <stdio.h>
#include <math.h>
 
#define PI 3.14159265
 
char buffer[256];
 
void main(void)
{
unsigned n, m, c = 0;
vga_clearscreen();
for(m = 0; m < 8; m++)
{
for(n = 0; n < 8; n++)
{
vga_setfgcolor5x7( n );
vga_setbgcolor5x7( m );
vga_putline5x7("HOLA", 10 + m * 4, 10 + n);
}
}
vga_setfgcolor5x7(7);
vga_setbgcolor5x7(1);
for(n = 100; n < 540; n++)
{
vga_drawpixel(n, 100, 7);
vga_drawpixel(n, 380, 7);
}
for(n = 100; n < 380; n++)
{
vga_drawpixel(100, n, 7);
vga_drawpixel(540, n, 7);
}
for(n = 0; n < 360; n++)
{
float x, y;
x = 320 + 100 * cos(n * (2*PI) / 360.0);
y = 240 + 100 * sin(n * (2*PI) / 360.0);
//printf("n=%u, x=%f y=%f\r\n", n, x, y);
//vga_putline5x7(buffer, 5, 5);
vga_drawpixel(x, y, 7);
}
}

powered by: WebSVN 2.1.0

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