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); |
} |
|
} |