Uploaded 11/25/2019
This commit is contained in:
parent
cfc9771b46
commit
e8da990e8d
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,530 @@
|
|||
//
|
||||
//
|
||||
// File Name : four_module_lockstep.v
|
||||
// Used on :
|
||||
// Author : Ted Fried, MicroCore Labs
|
||||
// Creation : 9/16/16
|
||||
// Code Type : Synthesizable
|
||||
//
|
||||
// Description:
|
||||
// ============
|
||||
//
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Modification History:
|
||||
// =====================
|
||||
//
|
||||
// Revision 1.0 9/16/16
|
||||
// Initial revision
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
`timescale 1ns/100ps
|
||||
|
||||
|
||||
module four_module_lockstep
|
||||
(
|
||||
input CORE_CLK, // Core Signals
|
||||
input RST_n,
|
||||
|
||||
|
||||
input [3:0] KILL_MODE,
|
||||
input [3:0] PB_SWITCH,
|
||||
output [3:0] LEDS,
|
||||
output [3:0] PROBE,
|
||||
|
||||
input UART_RX, // UART
|
||||
output UART_TX,
|
||||
output SPEAKER
|
||||
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Internal Signals
|
||||
|
||||
|
||||
reg proxy_wr;
|
||||
reg proxy_rd;
|
||||
reg [15:0] proxy_address;
|
||||
reg [7:0] prody_wr_data;
|
||||
wire module0_broadcast_ok;
|
||||
wire module1_broadcast_ok;
|
||||
wire module2_broadcast_ok;
|
||||
wire module3_broadcast_ok;
|
||||
wire timer_wr_strobe;
|
||||
wire uart_wr_strobe;
|
||||
wire uart_rd_strobe;
|
||||
wire core_clk_int;
|
||||
wire module0_sync;
|
||||
wire module1_sync;
|
||||
wire module2_sync;
|
||||
wire module3_sync;
|
||||
wire interrupt2;
|
||||
wire interrupt3;
|
||||
wire [7:0] module0_strobe;
|
||||
wire [7:0] module1_strobe;
|
||||
wire [7:0] module2_strobe;
|
||||
wire [7:0] module3_strobe;
|
||||
wire [7:0] top_strobe;
|
||||
wire [15:0] module0_address;
|
||||
wire [15:0] module1_address;
|
||||
wire [15:0] module2_address;
|
||||
wire [15:0] module3_address;
|
||||
wire [15:0] top_address;
|
||||
wire [7:0] module0_data;
|
||||
wire [7:0] module1_data;
|
||||
wire [7:0] module2_data;
|
||||
wire [7:0] module3_data;
|
||||
wire [7:0] top_data;
|
||||
wire [7:0] proxy_rd_data_int;
|
||||
wire [7:0] timer_dataout;
|
||||
wire [7:0] uart_dataout;
|
||||
wire [15:0] module0_ip;
|
||||
wire [15:0] module1_ip;
|
||||
wire [15:0] module2_ip;
|
||||
wire [15:0] module3_ip;
|
||||
|
||||
|
||||
reg [3:0] pbsw_d1;
|
||||
reg [3:0] pbsw_d2;
|
||||
reg [3:0] pbsw_d3;
|
||||
reg [3:0] pbsw_d4;
|
||||
reg [3:0] pbsw_d5;
|
||||
|
||||
reg rst_n_d1;
|
||||
reg rst_n_d2;
|
||||
reg rst_n_d3;
|
||||
reg rst_n_d4;
|
||||
|
||||
reg [3:0] kmode_d1;
|
||||
reg [3:0] kmode_d2;
|
||||
reg [3:0] kmode_d3;
|
||||
reg [3:0] kmode_d4;
|
||||
|
||||
reg kill0;
|
||||
reg kill1;
|
||||
reg kill2;
|
||||
reg kill3;
|
||||
|
||||
wire core_clk_locked;
|
||||
|
||||
reg speaker_int_d1;
|
||||
reg speaker_int_d2;
|
||||
reg speaker_int_d3;
|
||||
wire speaker_int;
|
||||
|
||||
|
||||
assign core_clk_int = CORE_CLK;
|
||||
|
||||
|
||||
|
||||
assign LEDS[3] = ~module3_broadcast_ok;
|
||||
assign LEDS[2] = ~module2_broadcast_ok;
|
||||
assign LEDS[1] = ~module1_broadcast_ok;
|
||||
assign LEDS[0] = ~module0_broadcast_ok;
|
||||
|
||||
assign PROBE[3] = ~module3_broadcast_ok;
|
||||
assign PROBE[2] = ~module2_broadcast_ok;
|
||||
assign PROBE[1] = ~module1_broadcast_ok;
|
||||
assign PROBE[0] = ~module0_broadcast_ok;
|
||||
|
||||
assign SPEAKER = speaker_int_d3;
|
||||
|
||||
|
||||
always @(posedge core_clk_int)
|
||||
begin : BUTTON_DEBOUNCE
|
||||
|
||||
speaker_int_d1 <= speaker_int;
|
||||
speaker_int_d2 <= speaker_int_d1;
|
||||
speaker_int_d3 <= speaker_int_d2;
|
||||
|
||||
rst_n_d1 <= RST_n;
|
||||
rst_n_d2 <= rst_n_d1;
|
||||
rst_n_d3 <= rst_n_d2;
|
||||
rst_n_d4 <= rst_n_d3;
|
||||
|
||||
pbsw_d1 <= PB_SWITCH;
|
||||
pbsw_d2 <= pbsw_d1;
|
||||
pbsw_d3 <= pbsw_d2;
|
||||
pbsw_d4 <= pbsw_d3;
|
||||
pbsw_d5 <= pbsw_d4;
|
||||
|
||||
kmode_d1 <= KILL_MODE;
|
||||
kmode_d2 <= kmode_d1;
|
||||
kmode_d3 <= kmode_d2;
|
||||
kmode_d4 <= kmode_d3;
|
||||
|
||||
if (pbsw_d5[3]==1'b1 && pbsw_d4[3]==1'b1 && pbsw_d3[3]==1'b1 && pbsw_d2[3]==1'b1) begin kill3 <= 1'b1; end
|
||||
else if (pbsw_d5[3]==1'b0 && pbsw_d4[3]==1'b0 && pbsw_d3[3]==1'b0 && pbsw_d2[3]==1'b0) begin kill3 <= 1'b0; end
|
||||
|
||||
if (pbsw_d5[2]==1'b1 && pbsw_d4[2]==1'b1 && pbsw_d3[2]==1'b1 && pbsw_d2[2]==1'b1) begin kill2 <= 1'b1; end
|
||||
else if (pbsw_d5[2]==1'b0 && pbsw_d4[2]==1'b0 && pbsw_d3[2]==1'b0 && pbsw_d2[2]==1'b0) begin kill2 <= 1'b0; end
|
||||
|
||||
if (pbsw_d5[1]==1'b1 && pbsw_d4[1]==1'b1 && pbsw_d3[1]==1'b1 && pbsw_d2[1]==1'b1) begin kill1 <= 1'b1; end
|
||||
else if (pbsw_d5[1]==1'b0 && pbsw_d4[1]==1'b0 && pbsw_d3[1]==1'b0 && pbsw_d2[1]==1'b0) begin kill1 <= 1'b0; end
|
||||
|
||||
if (pbsw_d5[0]==1'b1 && pbsw_d4[0]==1'b1 && pbsw_d3[0]==1'b1 && pbsw_d2[0]==1'b1) begin kill0 <= 1'b1; end
|
||||
else if (pbsw_d5[0]==1'b0 && pbsw_d4[0]==1'b0 && pbsw_d3[0]==1'b0 && pbsw_d2[0]==1'b0) begin kill0 <= 1'b0; end
|
||||
|
||||
|
||||
|
||||
end // BIU Controller
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Lockstep Modules
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
module_block MODULE0
|
||||
(
|
||||
.CORE_CLK (core_clk_int),
|
||||
.RST_n (rst_n_d4),
|
||||
.KILL (kill0),
|
||||
.KILL_MODE (kmode_d4),
|
||||
.MODULE_ID (2'h0),
|
||||
|
||||
.BROADCAST_OK (module0_broadcast_ok),
|
||||
.BROADCAST_STROBE (module0_strobe),
|
||||
.BROADCAST_ADDRESS (module0_address),
|
||||
.BROADCAST_DATA (module0_data),
|
||||
.BROADCAST_IP (module0_ip),
|
||||
.BROADCAST_SYNC (module0_sync),
|
||||
.BROADCAST_IDSBL (module0_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN0 (module1_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN0 (module1_strobe),
|
||||
.BROADCAST_ADDRESS_IN0 (module1_address),
|
||||
.BROADCAST_DATA_IN0 (module1_data),
|
||||
.BROADCAST_IP_IN0 (module1_ip),
|
||||
.BROADCAST_SYNC_IN0 (module1_sync),
|
||||
.BROADCAST_IDSBL_IN0 (module1_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN1 (module2_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN1 (module2_strobe),
|
||||
.BROADCAST_ADDRESS_IN1 (module2_address),
|
||||
.BROADCAST_DATA_IN1 (module2_data),
|
||||
.BROADCAST_IP_IN1 (module2_ip),
|
||||
.BROADCAST_SYNC_IN1 (module2_sync),
|
||||
.BROADCAST_IDSBL_IN1 (module2_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN2 (module3_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN2 (module3_strobe),
|
||||
.BROADCAST_ADDRESS_IN2 (module3_address),
|
||||
.BROADCAST_DATA_IN2 (module3_data),
|
||||
.BROADCAST_IP_IN2 (module3_ip),
|
||||
.BROADCAST_SYNC_IN2 (module3_sync),
|
||||
.BROADCAST_IDSBL_IN2 (module3_idsbl),
|
||||
|
||||
. INT2 (interrupt2),
|
||||
. INT3 (interrupt3),
|
||||
|
||||
.PROXY_RD_DATA (proxy_rd_data_int)
|
||||
|
||||
);
|
||||
|
||||
|
||||
module_block MODULE1
|
||||
(
|
||||
.CORE_CLK (core_clk_int),
|
||||
.RST_n (rst_n_d4),
|
||||
.KILL (kill1),
|
||||
.KILL_MODE (kmode_d4),
|
||||
.MODULE_ID (2'h1),
|
||||
|
||||
.BROADCAST_OK (module1_broadcast_ok),
|
||||
.BROADCAST_STROBE (module1_strobe),
|
||||
.BROADCAST_ADDRESS (module1_address),
|
||||
.BROADCAST_DATA (module1_data),
|
||||
.BROADCAST_IP (module1_ip),
|
||||
.BROADCAST_SYNC (module1_sync),
|
||||
.BROADCAST_IDSBL (module1_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN0 (module2_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN0 (module2_strobe),
|
||||
.BROADCAST_ADDRESS_IN0 (module2_address),
|
||||
.BROADCAST_DATA_IN0 (module2_data),
|
||||
.BROADCAST_IP_IN0 (module2_ip),
|
||||
.BROADCAST_SYNC_IN0 (module2_sync),
|
||||
.BROADCAST_IDSBL_IN0 (module2_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN1 (module3_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN1 (module3_strobe),
|
||||
.BROADCAST_ADDRESS_IN1 (module3_address),
|
||||
.BROADCAST_DATA_IN1 (module3_data),
|
||||
.BROADCAST_IP_IN1 (module3_ip),
|
||||
.BROADCAST_SYNC_IN1 (module3_sync),
|
||||
.BROADCAST_IDSBL_IN1 (module3_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN2 (module0_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN2 (module0_strobe),
|
||||
.BROADCAST_ADDRESS_IN2 (module0_address),
|
||||
.BROADCAST_DATA_IN2 (module0_data),
|
||||
.BROADCAST_IP_IN2 (module0_ip),
|
||||
.BROADCAST_SYNC_IN2 (module0_sync),
|
||||
.BROADCAST_IDSBL_IN2 (module0_idsbl),
|
||||
|
||||
. INT2 (interrupt2),
|
||||
. INT3 (interrupt3),
|
||||
|
||||
.PROXY_RD_DATA (proxy_rd_data_int)
|
||||
|
||||
);
|
||||
|
||||
|
||||
module_block MODULE2
|
||||
(
|
||||
.CORE_CLK (core_clk_int),
|
||||
.RST_n (rst_n_d4),
|
||||
.KILL (kill2),
|
||||
.KILL_MODE (kmode_d4),
|
||||
.MODULE_ID (2'h2),
|
||||
|
||||
.BROADCAST_OK (module2_broadcast_ok),
|
||||
.BROADCAST_STROBE (module2_strobe),
|
||||
.BROADCAST_ADDRESS (module2_address),
|
||||
.BROADCAST_DATA (module2_data),
|
||||
.BROADCAST_IP (module2_ip),
|
||||
.BROADCAST_SYNC (module2_sync),
|
||||
.BROADCAST_IDSBL (module2_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN0 (module3_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN0 (module3_strobe),
|
||||
.BROADCAST_ADDRESS_IN0 (module3_address),
|
||||
.BROADCAST_DATA_IN0 (module3_data),
|
||||
.BROADCAST_IP_IN0 (module3_ip),
|
||||
.BROADCAST_SYNC_IN0 (module3_sync),
|
||||
.BROADCAST_IDSBL_IN0 (module3_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN1 (module0_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN1 (module0_strobe),
|
||||
.BROADCAST_ADDRESS_IN1 (module0_address),
|
||||
.BROADCAST_DATA_IN1 (module0_data),
|
||||
.BROADCAST_IP_IN1 (module0_ip),
|
||||
.BROADCAST_SYNC_IN1 (module0_sync),
|
||||
.BROADCAST_IDSBL_IN1 (module0_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN2 (module1_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN2 (module1_strobe),
|
||||
.BROADCAST_ADDRESS_IN2 (module1_address),
|
||||
.BROADCAST_DATA_IN2 (module1_data),
|
||||
.BROADCAST_IP_IN2 (module1_ip),
|
||||
.BROADCAST_SYNC_IN2 (module1_sync),
|
||||
.BROADCAST_IDSBL_IN2 (module1_idsbl),
|
||||
|
||||
. INT2 (interrupt2),
|
||||
. INT3 (interrupt3),
|
||||
|
||||
.PROXY_RD_DATA (proxy_rd_data_int)
|
||||
|
||||
);
|
||||
|
||||
|
||||
module_block MODULE3
|
||||
(
|
||||
.CORE_CLK (core_clk_int),
|
||||
.RST_n (rst_n_d4),
|
||||
.KILL (kill3),
|
||||
.KILL_MODE (kmode_d4),
|
||||
.MODULE_ID (2'h3),
|
||||
|
||||
.BROADCAST_OK (module3_broadcast_ok),
|
||||
.BROADCAST_STROBE (module3_strobe),
|
||||
.BROADCAST_ADDRESS (module3_address),
|
||||
.BROADCAST_DATA (module3_data),
|
||||
.BROADCAST_IP (module3_ip),
|
||||
.BROADCAST_SYNC (module3_sync),
|
||||
.BROADCAST_IDSBL (module3_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN0 (module0_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN0 (module0_strobe),
|
||||
.BROADCAST_ADDRESS_IN0 (module0_address),
|
||||
.BROADCAST_DATA_IN0 (module0_data),
|
||||
.BROADCAST_IP_IN0 (module0_ip),
|
||||
.BROADCAST_SYNC_IN0 (module0_sync),
|
||||
.BROADCAST_IDSBL_IN0 (module0_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN1 (module1_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN1 (module1_strobe),
|
||||
.BROADCAST_ADDRESS_IN1 (module1_address),
|
||||
.BROADCAST_DATA_IN1 (module1_data),
|
||||
.BROADCAST_IP_IN1 (module1_ip),
|
||||
.BROADCAST_SYNC_IN1 (module1_sync),
|
||||
.BROADCAST_IDSBL_IN1 (module1_idsbl),
|
||||
|
||||
.BROADCAST_OK_IN2 (module2_broadcast_ok),
|
||||
.BROADCAST_STROBE_IN2 (module2_strobe),
|
||||
.BROADCAST_ADDRESS_IN2 (module2_address),
|
||||
.BROADCAST_DATA_IN2 (module2_data),
|
||||
.BROADCAST_IP_IN2 (module2_ip),
|
||||
.BROADCAST_SYNC_IN2 (module2_sync),
|
||||
.BROADCAST_IDSBL_IN2 (module2_idsbl),
|
||||
|
||||
. INT2 (interrupt2),
|
||||
. INT3 (interrupt3),
|
||||
|
||||
.PROXY_RD_DATA (proxy_rd_data_int)
|
||||
|
||||
);
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// Fixed-priority arbiter that chooses which
|
||||
// core's outputs to direct to the peripherals.
|
||||
//
|
||||
|
||||
assign top_strobe = (module0_broadcast_ok==1'b1) ? module0_strobe :
|
||||
(module1_broadcast_ok==1'b1) ? module1_strobe :
|
||||
(module2_broadcast_ok==1'b1) ? module2_strobe :
|
||||
(module3_broadcast_ok==1'b1) ? module3_strobe :
|
||||
8'hEE;
|
||||
|
||||
|
||||
assign top_address = (module0_broadcast_ok==1'b1) ? module0_address :
|
||||
(module1_broadcast_ok==1'b1) ? module1_address :
|
||||
(module2_broadcast_ok==1'b1) ? module2_address :
|
||||
(module3_broadcast_ok==1'b1) ? module3_address :
|
||||
16'hEEEE;
|
||||
|
||||
|
||||
|
||||
assign top_data = (module0_broadcast_ok==1'b1) ? module0_data :
|
||||
(module1_broadcast_ok==1'b1) ? module1_data :
|
||||
(module2_broadcast_ok==1'b1) ? module2_data :
|
||||
(module3_broadcast_ok==1'b1) ? module3_data :
|
||||
8'hEE;
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Proxy addressing for peripherals
|
||||
//
|
||||
// This code mirrors the module accesses to the proxy addressing
|
||||
// registers and buffers them to the peripherals.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
always @(posedge core_clk_int)
|
||||
begin : PROXY_ADDRESSING
|
||||
|
||||
if (rst_n_d4==1'b0)
|
||||
begin
|
||||
proxy_wr <= 'h0;
|
||||
proxy_rd <= 'h0;
|
||||
proxy_address <= 'h0;
|
||||
prody_wr_data <= 'h0;
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
|
||||
if (top_strobe[7:0]==8'h11 && top_address[15:0]==16'h00C1)
|
||||
begin
|
||||
proxy_wr <= 1'b1;
|
||||
prody_wr_data <= top_data;
|
||||
end
|
||||
else
|
||||
begin
|
||||
proxy_wr <= 1'b0;
|
||||
end
|
||||
|
||||
if (top_strobe[7:0]==8'h11 && top_address[15:0]==16'h00C2)
|
||||
begin
|
||||
proxy_rd <= 1'b1;
|
||||
proxy_address <= top_data;
|
||||
end
|
||||
else
|
||||
begin
|
||||
proxy_rd <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Peripherals accessed with proxy addressing
|
||||
//
|
||||
// BIU SFR proxy_address - 0xC2 = Address[7:0]
|
||||
// proxy_wr_data - 0xC1 = Write Data and strobe to the peripherals
|
||||
// proxy_rd_data - 0xC0 = Read Data from the peripherals
|
||||
//
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
// Steer the peripheral read data back to the modules
|
||||
//
|
||||
assign proxy_rd_data_int = (proxy_address[7:4]==4'h0) ? timer_dataout :
|
||||
(proxy_address[7:4]==4'h1) ? uart_dataout :
|
||||
8'hEE ;
|
||||
|
||||
// Gate the peripheral read and write strobes
|
||||
assign timer_wr_strobe = (proxy_address[7:4]==4'h0) ? proxy_wr : 1'b0;
|
||||
assign uart_wr_strobe = (proxy_address[7:4]==4'h1) ? proxy_wr : 1'b0;
|
||||
assign uart_rd_strobe = (proxy_address[7:4]==4'h1) ? proxy_rd : 1'b0;
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Timer - Dual output 24-bit programmable timer
|
||||
//
|
||||
// Timer-0 = Frequency generator
|
||||
// Timer-1 = Pulse generator
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
timer TIMER
|
||||
(
|
||||
.CORE_CLK (core_clk_int),
|
||||
.RST_n (rst_n_d4),
|
||||
.ADDRESS (proxy_address[3:0]),
|
||||
.DATA_IN (prody_wr_data),
|
||||
.DATA_OUT (timer_dataout),
|
||||
.STROBE_WR (timer_wr_strobe),
|
||||
.TIMER0_OUT (speaker_int),
|
||||
.TIMER1_OUT (interrupt2)
|
||||
);
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// UART - Fixed 9600 baud
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
uart UART
|
||||
(
|
||||
.CLK (core_clk_int),
|
||||
.RST_n (rst_n_d4),
|
||||
.ADDRESS (proxy_address[1:0]),
|
||||
.DATA_IN (prody_wr_data),
|
||||
.DATA_OUT (uart_dataout),
|
||||
.STROBE_RD (uart_rd_strobe),
|
||||
.STROBE_WR (uart_wr_strobe),
|
||||
.UART_RX (UART_RX),
|
||||
.UART_TX (UART_TX),
|
||||
.UART_INT (interrupt3)
|
||||
);
|
||||
|
||||
|
||||
endmodule // four_module_lockstep.v
|
|
@ -0,0 +1,818 @@
|
|||
//
|
||||
//
|
||||
// File Name : module_block.v
|
||||
// Used on : Reliable 8051 Project
|
||||
// Author : Ted Fried, MicroCore Labs
|
||||
// Creation : 7/13/2016
|
||||
// Code Type : Synthesizable
|
||||
//
|
||||
// Description:
|
||||
// ============
|
||||
//
|
||||
// Module for a LockStep Quad Modular Redundant processor
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Modification History:
|
||||
// =====================
|
||||
//
|
||||
// Revision 1.0 7/13/16
|
||||
// Initial revision
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
`timescale 1ns/100ps
|
||||
|
||||
|
||||
module module_block
|
||||
(
|
||||
input CORE_CLK,
|
||||
input RST_n,
|
||||
input KILL,
|
||||
input [3:0] KILL_MODE,
|
||||
input [1:0] MODULE_ID,
|
||||
|
||||
|
||||
output BROADCAST_OK,
|
||||
output [7:0] BROADCAST_STROBE,
|
||||
output [15:0] BROADCAST_ADDRESS,
|
||||
output [7:0] BROADCAST_DATA,
|
||||
output [15:0] BROADCAST_IP,
|
||||
output BROADCAST_SYNC,
|
||||
output BROADCAST_IDSBL,
|
||||
|
||||
|
||||
input BROADCAST_OK_IN0,
|
||||
input [7:0] BROADCAST_STROBE_IN0,
|
||||
input [15:0] BROADCAST_ADDRESS_IN0,
|
||||
input [7:0] BROADCAST_DATA_IN0,
|
||||
input [15:0] BROADCAST_IP_IN0,
|
||||
input BROADCAST_SYNC_IN0,
|
||||
input BROADCAST_IDSBL_IN0,
|
||||
|
||||
input BROADCAST_OK_IN1,
|
||||
input [7:0] BROADCAST_STROBE_IN1,
|
||||
input [15:0] BROADCAST_ADDRESS_IN1,
|
||||
input [7:0] BROADCAST_DATA_IN1,
|
||||
input [15:0] BROADCAST_IP_IN1,
|
||||
input BROADCAST_SYNC_IN1,
|
||||
input BROADCAST_IDSBL_IN1,
|
||||
|
||||
input BROADCAST_OK_IN2,
|
||||
input [7:0] BROADCAST_STROBE_IN2,
|
||||
input [15:0] BROADCAST_ADDRESS_IN2,
|
||||
input [7:0] BROADCAST_DATA_IN2,
|
||||
input [15:0] BROADCAST_IP_IN2,
|
||||
input BROADCAST_SYNC_IN2,
|
||||
input BROADCAST_IDSBL_IN2,
|
||||
|
||||
|
||||
|
||||
input INT2, // Interrupts
|
||||
input INT3,
|
||||
|
||||
input[7:0] PROXY_RD_DATA
|
||||
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Internal Signals for EU
|
||||
|
||||
reg eu_add_carry;
|
||||
reg eu_add_carry16;
|
||||
reg eu_add_aux_carry;
|
||||
reg eu_add_overflow;
|
||||
reg eu_stall_pipeline;
|
||||
reg core_interrupt_disable;
|
||||
wire eu_opcode_jump_call;
|
||||
wire eu_jump_gate;
|
||||
wire biu_sfr_select;
|
||||
wire acc_parity;
|
||||
wire biu_timer_wr_strobe;
|
||||
wire biu_uart_rd_strobe;
|
||||
wire biu_uart_wr_strobe;
|
||||
wire biu_interrupt_int;
|
||||
wire rebuild_wr;
|
||||
wire voter_good;
|
||||
wire rebuild_wr0;
|
||||
wire rebuild_wr1;
|
||||
wire rebuild_wr2;
|
||||
wire rebuild_wr3;
|
||||
wire rebuild_sync_in;
|
||||
reg [9:0] eu_rom_address;
|
||||
reg [19:0] eu_calling_address;
|
||||
reg [15:0] eu_register_r0;
|
||||
reg [15:0] eu_register_r1;
|
||||
reg [15:0] eu_register_r2;
|
||||
reg [15:0] eu_register_r3;
|
||||
reg [15:0] eu_register_ip;
|
||||
reg [7:0] eu_biu_strobe;
|
||||
reg [7:0] eu_biu_dataout;
|
||||
reg [15:0] eu_alu_last_result;
|
||||
reg [15:0] eu_register_r3_d1;
|
||||
reg [7:0] biu_sfr_dpl_int;
|
||||
reg [7:0] biu_sfr_dph_int;
|
||||
reg [7:0] biu_sfr_ie_int;
|
||||
reg [7:0] biu_sfr_psw_int;
|
||||
reg [7:0] biu_sfr_acc_int;
|
||||
reg [7:0] biu_sfr_sp_int;
|
||||
reg [7:0] biu_sfr_b_int;
|
||||
reg [15:0] rebuild_addr_out;
|
||||
reg [15:0] rebuild_addr_out_d;
|
||||
reg [2:0] rebuild_cross_zero;
|
||||
wire [15:0] adder_out;
|
||||
wire [16:0] carry;
|
||||
wire [2:0] eu_opcode_type;
|
||||
wire [2:0] eu_opcode_dst_sel;
|
||||
wire [3:0] eu_opcode_op0_sel;
|
||||
wire [2:0] eu_opcode_op1_sel;
|
||||
wire [15:0] eu_opcode_immediate;
|
||||
wire [2:0] eu_opcode_jump_src;
|
||||
wire [2:0] eu_opcode_jump_cond;
|
||||
wire [15:0] eu_alu2;
|
||||
wire [15:0] eu_alu3;
|
||||
wire [15:0] eu_alu4;
|
||||
wire [15:0] eu_alu5;
|
||||
wire [15:0] eu_alu6;
|
||||
wire [15:0] eu_alu7;
|
||||
wire [15:0] eu_alu_out;
|
||||
wire [15:0] eu_operand0;
|
||||
wire [15:0] eu_operand1;
|
||||
wire [31:0] eu_rom_data;
|
||||
wire [15:0] eu_flags_r;
|
||||
wire [15:0] rebuild_addr;
|
||||
wire [7:0] biu_return_data_int;
|
||||
wire [7:0] biu_sfr_dataout;
|
||||
wire [7:0] biu_sfr_is_int;
|
||||
wire [7:0] biu_program_data;
|
||||
wire [2:0] eu_biu_strobe_mode;
|
||||
wire [2:0] eu_biu_strobe_int;
|
||||
wire [7:0] biu_ram_dataout;
|
||||
wire [7:0] biu_timer_dataout;
|
||||
wire [7:0] biu_uart_dataout;
|
||||
wire [7:0] rebuild_data_in;
|
||||
wire [15:0] neighbor_address;
|
||||
wire [7:0] neighbor_data;
|
||||
wire [15:0] neighbor_ip;
|
||||
wire [7:0] neighbor_strobe;
|
||||
wire [7:0] rebuild_data_out;
|
||||
wire [7:0] rebuild_data_out0;
|
||||
wire [7:0] rebuild_data_out1;
|
||||
wire [7:0] rebuild_data_out2;
|
||||
wire [7:0] rebuild_data_out3;
|
||||
wire [7:0] rebuild_strobe_in;
|
||||
wire [15:0] rebuild_ip_in;
|
||||
|
||||
|
||||
reg kill_d1;
|
||||
reg kill_d2;
|
||||
reg kill_d3;
|
||||
reg kill_d4;
|
||||
|
||||
reg rebuild_sync_in_d1;
|
||||
reg rebuild_sync_in_d2;
|
||||
reg rebuild_sync_in_d3;
|
||||
|
||||
wire neighbor_idsbl;
|
||||
wire kill_microcode;
|
||||
|
||||
reg [1:0] run_level;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// EU Microcode ROM. 1Kx32x8
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
assign kill_microcode = (KILL_MODE==4'h0 && kill_d4==1'b1) ? 1'b1 : 1'b0;
|
||||
|
||||
dpram_1Kx32x8 EU_1Kx32x8
|
||||
(
|
||||
.clka (CORE_CLK),
|
||||
// .wea (1'b0),
|
||||
.wea (kill_microcode),
|
||||
.addra (eu_rom_address[9:0]),
|
||||
.dina ({ MODULE_ID , 30'h0000_0000 }),
|
||||
.douta (eu_rom_data),
|
||||
|
||||
.clkb (CORE_CLK),
|
||||
.web (rebuild_wr0),
|
||||
.addrb (rebuild_addr[11:0]),
|
||||
.dinb (rebuild_data_in),
|
||||
.doutb (rebuild_data_out0)
|
||||
);
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// User Program ROM. 4Kx8x8
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
dpram_4Kx8x8 BIU_4Kx8x8
|
||||
(
|
||||
.clka (CORE_CLK),
|
||||
.wea (1'b0),
|
||||
.addra (eu_register_ip[11:0]),
|
||||
.dina (8'h00),
|
||||
.douta (biu_program_data),
|
||||
|
||||
.clkb (CORE_CLK),
|
||||
.web (rebuild_wr1),
|
||||
.addrb (rebuild_addr[11:0]),
|
||||
.dinb (rebuild_data_in),
|
||||
.doutb (rebuild_data_out1)
|
||||
);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// User Data RAM. 512x8x8
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
dpram_512x8x8 BIU_512x8x8
|
||||
(
|
||||
.clka (CORE_CLK),
|
||||
.wea (biu_ram_wr),
|
||||
.addra (eu_register_r3_d1[8:0]),
|
||||
.dina (eu_biu_dataout),
|
||||
.douta (biu_ram_dataout),
|
||||
|
||||
.clkb (CORE_CLK),
|
||||
.web (rebuild_wr2),
|
||||
.addrb (rebuild_addr[8:0]),
|
||||
.dinb (rebuild_data_in),
|
||||
.doutb (rebuild_data_out2)
|
||||
);
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Broadcast logic
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// When registers/flags are updated, the STROBE is assrted along with the new data
|
||||
// Otherwise the module continously broadcasts the contents of their RAMS so
|
||||
// listening modules can rebuild their local RAMS.
|
||||
//
|
||||
assign BROADCAST_OK = ((RST_n==1'b0 || run_level==2'h3) && voter_good==1'b1) ? 1'b1 : 1'b0;
|
||||
assign BROADCAST_ADDRESS = (run_level!=2'h3) ? { 14'h0, MODULE_ID } : (eu_biu_strobe==8'h00) ? rebuild_addr_out_d : eu_register_r3;
|
||||
assign BROADCAST_DATA = ((KILL_MODE==4'h2 && kill_d4==1'b1) || (run_level!=2'h3)) ? { 6'h0 , MODULE_ID } : (eu_biu_strobe==8'h00) ? rebuild_data_out : (eu_biu_strobe[2:0]==3'h1) ? eu_biu_dataout : 8'hAA;
|
||||
assign BROADCAST_IP = eu_register_ip;
|
||||
assign BROADCAST_STROBE = (run_level!=2'h3) ? { 6'h0 , MODULE_ID } : eu_biu_strobe;
|
||||
assign BROADCAST_SYNC = (eu_rom_address==9'h103) ? 1'b1 : 1'b0;
|
||||
assign BROADCAST_IDSBL = core_interrupt_disable;
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Voter and neighboring module data steering logic
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// Voter reports module data is OK if it matches at least one other neighbor module.
|
||||
//
|
||||
assign voter_good = ( ((BROADCAST_ADDRESS == BROADCAST_ADDRESS_IN0) && (BROADCAST_DATA == BROADCAST_DATA_IN0) && (BROADCAST_SYNC == BROADCAST_SYNC_IN0)) ||
|
||||
((BROADCAST_ADDRESS == BROADCAST_ADDRESS_IN1) && (BROADCAST_DATA == BROADCAST_DATA_IN1) && (BROADCAST_SYNC == BROADCAST_SYNC_IN1)) ||
|
||||
((BROADCAST_ADDRESS == BROADCAST_ADDRESS_IN2) && (BROADCAST_DATA == BROADCAST_DATA_IN2) && (BROADCAST_SYNC == BROADCAST_SYNC_IN2)) ) ? 1'b1 : 1'b0;
|
||||
|
||||
|
||||
|
||||
assign neighbor_address = (BROADCAST_OK_IN0==1'b1) ? BROADCAST_ADDRESS_IN0 :
|
||||
(BROADCAST_OK_IN1==1'b1) ? BROADCAST_ADDRESS_IN1 :
|
||||
(BROADCAST_OK_IN2==1'b1) ? BROADCAST_ADDRESS_IN2 :
|
||||
16'hEEEE;
|
||||
|
||||
assign neighbor_data = (BROADCAST_OK_IN0==1'b1) ? BROADCAST_DATA_IN0 :
|
||||
(BROADCAST_OK_IN1==1'b1) ? BROADCAST_DATA_IN1 :
|
||||
(BROADCAST_OK_IN2==1'b1) ? BROADCAST_DATA_IN2 :
|
||||
8'hEE;
|
||||
|
||||
assign neighbor_ip = (BROADCAST_OK_IN0==1'b1) ? BROADCAST_IP_IN0 :
|
||||
(BROADCAST_OK_IN1==1'b1) ? BROADCAST_IP_IN1 :
|
||||
(BROADCAST_OK_IN2==1'b1) ? BROADCAST_IP_IN2 :
|
||||
16'hEEEE;
|
||||
|
||||
assign neighbor_strobe = (BROADCAST_OK_IN0==1'b1) ? BROADCAST_STROBE_IN0 :
|
||||
(BROADCAST_OK_IN1==1'b1) ? BROADCAST_STROBE_IN1 :
|
||||
(BROADCAST_OK_IN2==1'b1) ? BROADCAST_STROBE_IN2 :
|
||||
8'hEE;
|
||||
|
||||
assign neighbor_sync = (BROADCAST_OK_IN0==1'b1) ? BROADCAST_SYNC_IN0 :
|
||||
(BROADCAST_OK_IN1==1'b1) ? BROADCAST_SYNC_IN1 :
|
||||
(BROADCAST_OK_IN2==1'b1) ? BROADCAST_SYNC_IN2 :
|
||||
1'b0;
|
||||
|
||||
assign neighbor_idsbl = (BROADCAST_OK_IN0==1'b1) ? BROADCAST_IDSBL_IN0 :
|
||||
(BROADCAST_OK_IN1==1'b1) ? BROADCAST_IDSBL_IN1 :
|
||||
(BROADCAST_OK_IN2==1'b1) ? BROADCAST_IDSBL_IN2 :
|
||||
1'b0;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Rebuilding logic
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
assign rebuild_data_out3 = (rebuild_addr_out_d[7:0]==8'h81) ? biu_sfr_sp_int :
|
||||
(rebuild_addr_out_d[7:0]==8'h82) ? biu_sfr_dpl_int :
|
||||
(rebuild_addr_out_d[7:0]==8'h83) ? biu_sfr_dph_int :
|
||||
(rebuild_addr_out_d[7:0]==8'hA8) ? biu_sfr_ie_int :
|
||||
(rebuild_addr_out_d[7:0]==8'hD0) ? biu_sfr_psw_int :
|
||||
(rebuild_addr_out_d[7:0]==8'hE0) ? biu_sfr_acc_int :
|
||||
(rebuild_addr_out_d[7:0]==8'hF0) ? biu_sfr_b_int :
|
||||
8'h77;
|
||||
|
||||
|
||||
// Select which RAM to output when broadcasting rebuilding addresses
|
||||
//
|
||||
assign rebuild_data_out = (rebuild_addr_out_d[13:12]==2'h0) ? rebuild_data_out0 :
|
||||
(rebuild_addr_out_d[13:12]==2'h1) ? rebuild_data_out1 :
|
||||
(rebuild_addr_out_d[13:12]==2'h2) ? rebuild_data_out2 :
|
||||
rebuild_data_out3 ;
|
||||
|
||||
|
||||
// Mux the inputs to the RAMS when rebuilding from neighbor cores.
|
||||
//
|
||||
assign rebuild_addr = (run_level[1]==1'b1) ? rebuild_addr_out : neighbor_address;
|
||||
assign rebuild_data_in = neighbor_data;
|
||||
assign rebuild_ip_in = neighbor_ip;
|
||||
assign rebuild_strobe_in = neighbor_strobe;
|
||||
assign rebuild_sync_in = neighbor_sync;
|
||||
|
||||
|
||||
assign rebuild_wr0 = (run_level[1]==1'b0 && neighbor_strobe==8'h00 && neighbor_address[13:12]==2'h0) ? 1'b1 : 1'b0;
|
||||
|
||||
assign rebuild_wr1 = (run_level[1]==1'b0 && neighbor_strobe==8'h00 && neighbor_address[13:12]==2'h1) ? 1'b1 : 1'b0;
|
||||
|
||||
assign rebuild_wr2 = (run_level[1]==1'b0 && neighbor_strobe==8'h00 && neighbor_address[13:12]==2'h2) ? 1'b1 :
|
||||
(run_level[1]==1'b0 && neighbor_strobe==8'h11 && neighbor_address[15:7] ==9'b0000_0000_0) ? 1'b1 : 1'b0;
|
||||
|
||||
assign rebuild_wr3 = (run_level[1]==1'b0 && neighbor_strobe==8'h00 && neighbor_address[13:12]==2'h3) ? 1'b1 :
|
||||
(run_level[1]==1'b0 && neighbor_strobe==8'h11 && neighbor_address[15:7] ==9'b0000_0000_1) ? 1'b1 : 1'b0;
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// EU Combinationals
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// EU ROM opcode decoder
|
||||
assign eu_opcode_type = (KILL_MODE==4'h3 && kill_d4==1'b1) ? 'h0 :eu_rom_data[30:28];
|
||||
assign eu_opcode_dst_sel = eu_rom_data[26:24];
|
||||
assign eu_opcode_op0_sel = eu_rom_data[23:20];
|
||||
assign eu_opcode_op1_sel = eu_rom_data[18:16];
|
||||
assign eu_opcode_immediate = eu_rom_data[15:0];
|
||||
|
||||
assign eu_opcode_jump_call = eu_rom_data[24];
|
||||
assign eu_opcode_jump_src = eu_rom_data[22:20];
|
||||
assign eu_opcode_jump_cond = eu_rom_data[18:16];
|
||||
|
||||
|
||||
|
||||
assign eu_operand0 = (eu_opcode_op0_sel==4'h0) ? eu_register_r0 :
|
||||
(eu_opcode_op0_sel==4'h1) ? eu_register_r1 :
|
||||
(eu_opcode_op0_sel==4'h2) ? eu_register_r2 :
|
||||
(eu_opcode_op0_sel==4'h3) ? eu_register_r3 :
|
||||
(eu_opcode_op0_sel==4'h4) ? { 8'h00 , biu_return_data_int } :
|
||||
(eu_opcode_op0_sel==4'h5) ? { eu_flags_r[15:0] } :
|
||||
(eu_opcode_op0_sel==4'h6) ? { 8'h00 , biu_sfr_acc_int } :
|
||||
(eu_opcode_op0_sel==4'h7) ? eu_register_ip :
|
||||
16'h0000 ;
|
||||
|
||||
assign eu_operand1 = (eu_opcode_op1_sel==3'h0) ? eu_register_r0 :
|
||||
(eu_opcode_op1_sel==3'h1) ? eu_register_r1 :
|
||||
(eu_opcode_op1_sel==3'h2) ? eu_register_r2 :
|
||||
(eu_opcode_op1_sel==3'h3) ? eu_register_r3 :
|
||||
(eu_opcode_op1_sel==3'h4) ? { 8'h00 , biu_sfr_sp_int } :
|
||||
//(eu_opcode_op1_sel==3'h5) ? eu_alu_last_result :
|
||||
(eu_opcode_op1_sel==3'h6) ? { biu_sfr_dph_int , biu_sfr_dpl_int } :
|
||||
eu_opcode_immediate ;
|
||||
|
||||
|
||||
// JUMP condition codes
|
||||
assign eu_jump_gate = (eu_opcode_jump_cond==4'h0) ? 1'b1 : // unconditional jump
|
||||
(eu_opcode_jump_cond==4'h1 && eu_alu_last_result!=16'h0) ? 1'b1 :
|
||||
(eu_opcode_jump_cond==4'h2 && eu_alu_last_result==16'h0) ? 1'b1 :
|
||||
1'b0 ;
|
||||
|
||||
|
||||
|
||||
// ** Flags must be written to the PSW through the BIU
|
||||
|
||||
assign eu_flags_r[15] = eu_add_carry;
|
||||
assign eu_flags_r[14] = eu_add_aux_carry;
|
||||
assign eu_flags_r[13] = eu_add_carry16;
|
||||
//assign eu_flags_r[12] =
|
||||
//assign eu_flags_r[11] =
|
||||
assign eu_flags_r[10] = eu_add_overflow;
|
||||
//assign eu_flags_r[9] =
|
||||
assign eu_flags_r[8] = biu_interrupt_int;
|
||||
|
||||
assign eu_flags_r[7] = biu_sfr_psw_int[7]; // C
|
||||
assign eu_flags_r[6] = biu_sfr_psw_int[6]; // AC
|
||||
assign eu_flags_r[5] = biu_sfr_psw_int[5]; // F0
|
||||
assign eu_flags_r[4] = biu_sfr_psw_int[4]; // RS1
|
||||
assign eu_flags_r[3] = biu_sfr_psw_int[3]; // RS0
|
||||
assign eu_flags_r[2] = biu_sfr_psw_int[2]; // Overflow
|
||||
assign eu_flags_r[1] = biu_sfr_psw_int[1]; // User Defined Flag
|
||||
assign eu_flags_r[0] = acc_parity; // ACC Parity generated in the BIU
|
||||
|
||||
|
||||
|
||||
|
||||
// EU ALU Operations
|
||||
// ------------------------------------------
|
||||
// eu_alu0 = NOP
|
||||
// eu_alu1 = JUMP
|
||||
assign eu_alu2 = adder_out; // ADD
|
||||
assign eu_alu3 = eu_operand0 ^ eu_operand1; // XOR
|
||||
assign eu_alu4 = eu_operand0 | eu_operand1; // OR
|
||||
assign eu_alu5 = eu_operand0 & eu_operand1; // AND
|
||||
assign eu_alu6 = { eu_operand0[7:0] , eu_operand0[15:8] }; // BYTESWAP
|
||||
assign eu_alu7 = (eu_opcode_immediate[1:0]==2'h0) ? { 8'h00 , eu_operand0[0] , eu_operand0[7:1] } : // Rotate in bit[0]
|
||||
(eu_opcode_immediate[1:0]==2'h1) ? { 8'h00 , biu_sfr_psw_int[7] , eu_operand0[7:1] } : // Rotate in Carry bit
|
||||
{ eu_add_carry16 , eu_operand0[15:1] } ; // 16-bit shift-right
|
||||
|
||||
|
||||
// Mux the ALU operations
|
||||
assign eu_alu_out = (eu_opcode_type==3'h2) ? eu_alu2 :
|
||||
(eu_opcode_type==3'h3) ? eu_alu3 :
|
||||
(eu_opcode_type==3'h4) ? eu_alu4 :
|
||||
(eu_opcode_type==3'h5) ? eu_alu5 :
|
||||
(eu_opcode_type==3'h6) ? eu_alu6 :
|
||||
(eu_opcode_type==3'h7) ? eu_alu7 :
|
||||
16'hEEEE;
|
||||
|
||||
|
||||
|
||||
// Generate 16-bit full adder for the EU
|
||||
assign carry[0] = 1'b0;
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < 16; i=i+1)
|
||||
begin : GEN_ADDER
|
||||
assign adder_out[i] = eu_operand0[i] ^ eu_operand1[i] ^ carry[i];
|
||||
assign carry[i+1] = (eu_operand0[i] & eu_operand1[i]) | (eu_operand0[i] & carry[i]) | (eu_operand1[i] & carry[i]);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// BIU Combinationals
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Outputs to the EU
|
||||
//
|
||||
|
||||
|
||||
assign biu_return_data_int = (KILL_MODE==4'h4 && kill_d4==1'b1) ? { MODULE_ID, MODULE_ID, MODULE_ID, MODULE_ID } :
|
||||
(eu_biu_strobe_mode==2'h0) ? biu_program_data :
|
||||
(biu_sfr_select==1'b1) ? biu_sfr_dataout :
|
||||
biu_ram_dataout ;
|
||||
|
||||
|
||||
// Parity for the Accumulator
|
||||
// This can be removed if parity is not used in firmware.
|
||||
assign acc_parity = (biu_sfr_acc_int[0]^biu_sfr_acc_int[1]^biu_sfr_acc_int[2]^biu_sfr_acc_int[3]^biu_sfr_acc_int[4]^biu_sfr_acc_int[5]^biu_sfr_acc_int[6]^biu_sfr_acc_int[7]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// EU strobes to request BIU processing.
|
||||
assign eu_biu_strobe_mode[2:0] = eu_biu_strobe[6:4];
|
||||
assign eu_biu_strobe_int[2:0] = eu_biu_strobe[2:0];
|
||||
|
||||
|
||||
|
||||
// Select the SFR range if the address is 0x0080 to 0x00FF and addressing mode is Direct
|
||||
assign biu_sfr_select = ( eu_register_r3_d1[15:7]==9'b0000_0000_1 && eu_biu_strobe_mode[1:0]==3'h1) ? 1'b1 : 1'b0;
|
||||
|
||||
|
||||
// Decode the write enable to the RAM block
|
||||
assign biu_ram_wr = (biu_sfr_select==1'b0 && eu_biu_strobe_int==3'h1) ? 1'b1 : 1'b0;
|
||||
|
||||
|
||||
// Mux the SFR data outputs
|
||||
assign biu_sfr_dataout = (eu_register_r3_d1[7:0]==8'h81) ? biu_sfr_sp_int :
|
||||
(eu_register_r3_d1[7:0]==8'h82) ? biu_sfr_dpl_int :
|
||||
(eu_register_r3_d1[7:0]==8'h83) ? biu_sfr_dph_int :
|
||||
(eu_register_r3_d1[7:0]==8'hA8) ? biu_sfr_ie_int :
|
||||
(eu_register_r3_d1[7:0]==8'hA9) ? biu_sfr_is_int :
|
||||
(eu_register_r3_d1[7:0]==8'hC0) ? PROXY_RD_DATA :
|
||||
(eu_register_r3_d1[7:0]==8'hD0) ? biu_sfr_psw_int :
|
||||
(eu_register_r3_d1[7:0]==8'hE0) ? biu_sfr_acc_int :
|
||||
(eu_register_r3_d1[7:0]==8'hF0) ? biu_sfr_b_int :
|
||||
8'hEE ;
|
||||
|
||||
|
||||
|
||||
|
||||
// Simple fixed priority interrupt controller
|
||||
// biu_sfr_ie_int[7] is the global_intr_enable
|
||||
// biu_sfr_is_int[3:0] contains the interrupt source
|
||||
// Interrupt 2 = Timer Interrupt Vector at address 0x4
|
||||
// 3 = UART-RX Interrupt Vector at address 0x6
|
||||
//
|
||||
assign biu_interrupt_int = (core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && INT2==1'b1) ? 1'b1 :
|
||||
(core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && INT3==1'b1) ? 1'b1 : 1'b0;
|
||||
// (core_interrupt_disable==1'b0 && biu_sfr_ie_int[7]==1'b1 && INT4==1'b1) ? 1'b1 :
|
||||
// 1'b0 ;
|
||||
|
||||
// Decode the vector address of the interrupt
|
||||
//
|
||||
assign biu_sfr_is_int = (INT2==1'b1) ? 8'h02 :
|
||||
(INT3==1'b1) ? 8'h03 : 8'h0F;
|
||||
// 8'h04 ;
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//
|
||||
// EU Microsequencer
|
||||
//
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
always @(posedge CORE_CLK)
|
||||
begin : EU_MICROSEQUENCER
|
||||
|
||||
if (RST_n==1'b0)
|
||||
begin
|
||||
eu_add_carry16 <= 'h0;
|
||||
eu_add_carry <= 'h0;
|
||||
eu_add_aux_carry <= 'h0;
|
||||
eu_add_overflow <= 'h0;
|
||||
eu_alu_last_result <= 'h0;
|
||||
eu_register_r0 <= 'h0;
|
||||
eu_register_r1 <= 'h0;
|
||||
eu_register_r2 <= 'h0;
|
||||
eu_register_r3 <= 'h0;
|
||||
eu_register_ip <= 16'hFFFF; // User Program code starts at 0x0000 after reset. Main loop does initial increment.
|
||||
eu_biu_strobe <= 'h0;
|
||||
eu_biu_dataout <= 'h0;
|
||||
eu_stall_pipeline <= 'h0;
|
||||
eu_rom_address <= 9'h100; // Microcode starts here after reset
|
||||
eu_calling_address <= 'h0;
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
kill_d1 <= KILL;
|
||||
kill_d2 <= kill_d1;
|
||||
kill_d3 <= kill_d2;
|
||||
kill_d4 <= kill_d3;
|
||||
|
||||
// Generate and store flags for addition
|
||||
if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h2)
|
||||
begin
|
||||
eu_add_carry16 <= carry[16];
|
||||
eu_add_carry <= carry[8];
|
||||
eu_add_aux_carry <= carry[4];
|
||||
eu_add_overflow <= carry[8] ^ carry[7];
|
||||
end
|
||||
|
||||
|
||||
// Register writeback
|
||||
if (run_level==2'h1)
|
||||
begin
|
||||
eu_register_ip <= rebuild_ip_in;
|
||||
eu_biu_strobe <= 'h0;
|
||||
end
|
||||
|
||||
else if (eu_stall_pipeline==1'b0 && eu_opcode_type!=3'h0 && eu_opcode_type!=3'h1)
|
||||
begin
|
||||
eu_alu_last_result <= eu_alu_out[15:0];
|
||||
case (eu_opcode_dst_sel) // synthesis parallel_case
|
||||
3'h0 : eu_register_r0 <= eu_alu_out[15:0];
|
||||
3'h1 : eu_register_r1 <= eu_alu_out[15:0];
|
||||
3'h2 : eu_register_r2 <= eu_alu_out[15:0];
|
||||
3'h3 : eu_register_r3 <= eu_alu_out[15:0];
|
||||
3'h4 : eu_biu_dataout <= eu_alu_out[7:0];
|
||||
3'h6 : eu_biu_strobe <= eu_alu_out[7:0];
|
||||
3'h7 : eu_register_ip <= eu_alu_out[15:0];
|
||||
default : ;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
// JUMP Opcode
|
||||
if (run_level[1]==1'b0)
|
||||
begin
|
||||
eu_rom_address[9:0] <= 10'h104; // Hold at microcode between instruction decodes while rebuilding
|
||||
eu_stall_pipeline <= 1'b0;
|
||||
end
|
||||
|
||||
else if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h1 && eu_jump_gate==1'b1)
|
||||
begin
|
||||
eu_stall_pipeline <= 1'b1;
|
||||
|
||||
// For subroutine CALLs, store next opcode address
|
||||
if (eu_opcode_jump_call==1'b1)
|
||||
begin
|
||||
eu_calling_address[19:0] <= {eu_calling_address[9:0] , eu_rom_address[9:0] }; // Two deep calling addresses
|
||||
end
|
||||
|
||||
case (eu_opcode_jump_src) // synthesis parallel_case
|
||||
3'h0 : eu_rom_address <= eu_opcode_immediate[9:0];
|
||||
3'h1 : eu_rom_address <= { 2'h0 , biu_return_data_int }; // Initial opcode jump decoding
|
||||
3'h2 : eu_rom_address <= { eu_opcode_immediate[9:4] , eu_register_r0[11:8] }; // EA decoding
|
||||
3'h3 : begin // CALL Return
|
||||
eu_rom_address <= eu_calling_address[9:0];
|
||||
eu_calling_address[9:0] <= eu_calling_address[19:10];
|
||||
end
|
||||
3'h4 : eu_rom_address <= { eu_opcode_immediate[5:0] , biu_return_data_int[2:0] , 1'b0 }; // Bit Mask decoding table
|
||||
|
||||
default : ;
|
||||
endcase
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
eu_stall_pipeline <= 1'b0; // Debounce the pipeline stall
|
||||
if (KILL_MODE==4'h1 && kill_d4==1'b1)
|
||||
begin
|
||||
eu_rom_address <= 'h0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
eu_rom_address <= eu_rom_address + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end // EU Microsequencer
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// BIU Controller
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
always @(posedge CORE_CLK)
|
||||
begin : BIU_CONTROLLER
|
||||
|
||||
if (RST_n==1'b0)
|
||||
begin
|
||||
biu_sfr_dpl_int <= 'h0;
|
||||
biu_sfr_dph_int <= 'h0;
|
||||
biu_sfr_ie_int <= 'h0;
|
||||
biu_sfr_psw_int <= 'h0;
|
||||
biu_sfr_acc_int <= 'h0;
|
||||
biu_sfr_b_int <= 8'h00;
|
||||
biu_sfr_sp_int <= 'h07;
|
||||
eu_register_r3_d1 <= 'h0;
|
||||
core_interrupt_disable <= 'h0;
|
||||
rebuild_addr_out <= 'h0;
|
||||
rebuild_addr_out_d <= 'h0;
|
||||
rebuild_cross_zero <= 'h0;
|
||||
run_level <= 'h3;
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
|
||||
// Delay address out by one clock to line up with the broadcast data
|
||||
if (KILL_MODE==4'h5 && kill_d4==1'b1)
|
||||
begin
|
||||
rebuild_addr_out_d <= 'h0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
rebuild_addr_out_d <= rebuild_addr_out;
|
||||
end
|
||||
|
||||
// Pipeline the neighboring code SYNC pulse
|
||||
rebuild_sync_in_d1 <= rebuild_sync_in;
|
||||
rebuild_sync_in_d2 <= rebuild_sync_in_d1;
|
||||
rebuild_sync_in_d3 <= rebuild_sync_in_d2;
|
||||
|
||||
|
||||
// When in rebuilding run-level 1, synchronize the broadcast address with the other modules
|
||||
if (run_level==2'h1)
|
||||
begin
|
||||
rebuild_addr_out <= rebuild_addr + 2'h2;
|
||||
end
|
||||
// When biu_strobe is asserted, back-off the address so it can restart with no missed locations
|
||||
else if (eu_biu_strobe!=8'h00)
|
||||
begin
|
||||
rebuild_addr_out <= rebuild_addr_out - 16'h0002;
|
||||
end
|
||||
else
|
||||
begin
|
||||
rebuild_addr_out <= rebuild_addr_out + 1'b1;
|
||||
end
|
||||
|
||||
|
||||
// Allow four passes of the full range or memory and register addresses when rebuilding a module
|
||||
if (run_level==2'h3)
|
||||
begin
|
||||
rebuild_cross_zero <= 'h0;
|
||||
end
|
||||
else if (run_level==2'h0 && rebuild_addr=='h0)
|
||||
begin
|
||||
rebuild_cross_zero <= rebuild_cross_zero + 1'b1;
|
||||
end
|
||||
|
||||
|
||||
// If Voter has detected a failure and module is not currently in rebuilding mode, then enter rebuilding mode.
|
||||
if ( run_level==2'h3 && voter_good==1'b0)
|
||||
begin
|
||||
run_level <= 2'h0;
|
||||
end
|
||||
// When the local RAM is refreshed multiple times, then go to run-level 1
|
||||
else if (run_level==2'h0 && rebuild_cross_zero==3'b010)
|
||||
begin
|
||||
run_level <= 2'h1;
|
||||
end
|
||||
// When the SYNC pulse fron neighboring modules is seen, then go to run-level 2
|
||||
else if (run_level==2'h1 && rebuild_sync_in==1'b1)
|
||||
begin
|
||||
run_level <= 2'h2;
|
||||
end
|
||||
// After a few clocks this module's broadcast should be pipelined out, so we can rejoin the lockstep at run-level 3
|
||||
else if (run_level==2'h2 && rebuild_sync_in_d3==1'b1)
|
||||
begin
|
||||
run_level <= 2'h3;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
eu_register_r3_d1 <= eu_register_r3;
|
||||
|
||||
if (run_level==2'h2)
|
||||
begin
|
||||
core_interrupt_disable <= neighbor_idsbl;
|
||||
end
|
||||
else if (eu_biu_strobe_int==3'h3)
|
||||
begin
|
||||
core_interrupt_disable <= 1'b1;
|
||||
end
|
||||
else if (eu_biu_strobe_int==3'h4)
|
||||
begin
|
||||
core_interrupt_disable <= 1'b0;
|
||||
end
|
||||
|
||||
|
||||
|
||||
// Writes to SFR's during rebuilding
|
||||
if (run_level!=2'h3)
|
||||
begin
|
||||
if (rebuild_wr3==1'b1)
|
||||
begin
|
||||
case (rebuild_addr[7:0]) // synthesis parallel_case
|
||||
|
||||
8'h81 : biu_sfr_sp_int <= rebuild_data_in[7:0];
|
||||
8'h82 : biu_sfr_dpl_int <= rebuild_data_in[7:0];
|
||||
8'h83 : biu_sfr_dph_int <= rebuild_data_in[7:0];
|
||||
8'hA8 : biu_sfr_ie_int <= rebuild_data_in[7:0];
|
||||
8'hD0 : biu_sfr_psw_int <= rebuild_data_in[7:0];
|
||||
8'hE0 : biu_sfr_acc_int <= rebuild_data_in[7:0];
|
||||
8'hF0 : biu_sfr_b_int <= rebuild_data_in[7:0];
|
||||
|
||||
default : ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Writes to SFR's
|
||||
else if (biu_sfr_select==1'b1 && eu_biu_strobe_int==3'h1)
|
||||
begin
|
||||
case (eu_register_r3_d1[7:0]) // synthesis parallel_case
|
||||
|
||||
8'h81 : biu_sfr_sp_int <= eu_biu_dataout[7:0];
|
||||
8'h82 : biu_sfr_dpl_int <= eu_biu_dataout[7:0];
|
||||
8'h83 : biu_sfr_dph_int <= eu_biu_dataout[7:0];
|
||||
8'hA8 : biu_sfr_ie_int <= eu_biu_dataout[7:0];
|
||||
8'hD0 : biu_sfr_psw_int <= eu_biu_dataout[7:0];
|
||||
8'hE0 : biu_sfr_acc_int <= eu_biu_dataout[7:0];
|
||||
8'hF0 : biu_sfr_b_int <= eu_biu_dataout[7:0];
|
||||
|
||||
default : ;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end // BIU Controller
|
||||
|
||||
|
||||
endmodule // module_block.v
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,210 @@
|
|||
//
|
||||
//
|
||||
// File Name : timer.v
|
||||
// Used on :
|
||||
// Author : Ted Fried, MicroCore Labs
|
||||
// Creation : 4/15/16
|
||||
// Code Type : Synthesizable
|
||||
//
|
||||
// Description:
|
||||
// ============
|
||||
//
|
||||
// Two channel, 24-bit timers.
|
||||
//
|
||||
// Timer-0 = Frequency generator
|
||||
// Timer-1 = One-shot generator
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Modification History:
|
||||
// =====================
|
||||
//
|
||||
// Revision 1.0 4/15/16
|
||||
// Initial revision
|
||||
//
|
||||
// Revision 2.0 5/23/16
|
||||
// Hard-wired MIDI note to 24-bit counter value converter for use with Music Player.
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
module timer
|
||||
(
|
||||
|
||||
input CORE_CLK,
|
||||
input RST_n,
|
||||
|
||||
input [3:0] ADDRESS,
|
||||
input [7:0] DATA_IN,
|
||||
output [7:0] DATA_OUT,
|
||||
input STROBE_WR,
|
||||
|
||||
output TIMER0_OUT,
|
||||
output TIMER1_OUT
|
||||
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Internal Signals
|
||||
|
||||
reg timer0_enable;
|
||||
reg timer1_enable;
|
||||
reg timer1_debounce;
|
||||
reg timer0_out_int;
|
||||
reg timer1_out_int;
|
||||
reg strobe_wr_d;
|
||||
reg [23:0] timer0_counter;
|
||||
reg [23:0] timer1_counter;
|
||||
reg [23:0] timer1_count_max;
|
||||
reg [7:0] timer0_note;
|
||||
wire [23:0] timer0_count_max;
|
||||
|
||||
// Notes @ 100Mhz FPGA core frequency
|
||||
assign timer0_count_max = (timer0_note==8'h3B) ? 24'h0316EE : // B3 - 246.94Hz
|
||||
(timer0_note==8'h3C) ? 24'h02EA85 : // C4 - 261.63 ** Middle C
|
||||
(timer0_note==8'h3D) ? 24'h02C0A4 : // Db4 - 277.18
|
||||
(timer0_note==8'h3E) ? 24'h029913 : // D4 - 293.67
|
||||
(timer0_note==8'h3F) ? 24'h0273C0 : // Eb4 - 311.13
|
||||
(timer0_note==8'h40) ? 24'h025085 : // E4 - 329.63
|
||||
(timer0_note==8'h41) ? 24'h022F44 : // F4 - 349.23
|
||||
(timer0_note==8'h42) ? 24'h020FDF : // Gb4 - 370.00
|
||||
(timer0_note==8'h43) ? 24'h01F23F : // G4 - 392.00
|
||||
(timer0_note==8'h44) ? 24'h01D647 : // Ab4 - 415.31
|
||||
(timer0_note==8'h45) ? 24'h01BBE4 : // A4 - 440.00
|
||||
(timer0_note==8'h46) ? 24'h01A2FB : // Bb4 - 466.16
|
||||
(timer0_note==8'h47) ? 24'h018B77 : // B4 - 493.88
|
||||
(timer0_note==8'h48) ? 24'h017544 : // C5 - 523.25
|
||||
(timer0_note==8'h49) ? 24'h016050 : // Db5 - 554.37
|
||||
(timer0_note==8'h4A) ? 24'h014C86 : // D5 - 587.33
|
||||
(timer0_note==8'h4B) ? 24'h0139E1 : // Eb5 - 622.25
|
||||
(timer0_note==8'h4C) ? 24'h012842 : // E5 - 659.26
|
||||
(timer0_note==8'h4D) ? 24'h0117A2 : // F5 - 698.46
|
||||
(timer0_note==8'h4E) ? 24'h0107F0 : // Gb5 - 739.99
|
||||
(timer0_note==8'h4F) ? 24'h00F920 : // G5 - 783.99
|
||||
(timer0_note==8'h50) ? 24'h00EB24 : // Ab5 - 830.61
|
||||
(timer0_note==8'h51) ? 24'h00DDF2 : // A5 - 880.00
|
||||
(timer0_note==8'h52) ? 24'h00D17D : // Bb5 - 932.33
|
||||
(timer0_note==8'h53) ? 24'h00C5BB : // B5 - 987.77
|
||||
(timer0_note==8'h54) ? 24'h00BAA2 : // C6 - 1046.50
|
||||
(timer0_note==8'h55) ? 24'h00B028 : // Db6 - 1108.73
|
||||
(timer0_note==8'h56) ? 24'h00A645 : // D6 - 1174.66
|
||||
(timer0_note==8'h57) ? 24'h009CF0 : // Eb6 - 1244.51
|
||||
(timer0_note==8'h58) ? 24'h009421 : // E6 - 1318.51
|
||||
'hFFFFFF ;
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Combinationals
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
assign TIMER0_OUT = (timer0_enable==1'b1 && timer0_out_int==1'b1) ? 1'b1 : 1'b0;
|
||||
assign TIMER1_OUT = (timer1_enable==1'b1 && timer1_out_int==1'b1) ? 1'b1 : 1'b0;
|
||||
|
||||
assign DATA_OUT = 8'h5A; // Timer Device ID
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Timer
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
always @(posedge CORE_CLK)
|
||||
begin : BIU_CONTROLLER
|
||||
|
||||
if (RST_n==1'b0)
|
||||
begin
|
||||
// timer0_count_max <= 24'h02EA85; // C4 - Middle C 261.63Hz @ 100Mhz core frequency
|
||||
timer0_note <= 'h0;
|
||||
timer0_enable <= 1'b0;
|
||||
timer0_counter <= 'h0;
|
||||
timer0_out_int <= 1'b0;
|
||||
timer1_count_max <= 'h0;
|
||||
timer1_enable <= 'h0;
|
||||
timer1_counter <= 'h0;
|
||||
timer1_out_int <= 1'b0;
|
||||
timer1_debounce <= 'h0;
|
||||
strobe_wr_d <= 'h0;
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
|
||||
strobe_wr_d <= STROBE_WR;
|
||||
|
||||
// Writes to Registers
|
||||
if (STROBE_WR==1'b1 || strobe_wr_d==1'b1)
|
||||
begin
|
||||
case (ADDRESS[3:0]) // synthesis parallel_case
|
||||
//4'h0 : timer0_count_max[23:16] <= DATA_IN[7:0];
|
||||
//4'h1 : timer0_count_max[15:8] <= DATA_IN[7:0];
|
||||
4'h2 : timer0_note[7:0] <= DATA_IN[7:0];
|
||||
4'h3 : timer0_enable <= DATA_IN[0];
|
||||
4'h4 : timer1_count_max[23:16] <= DATA_IN[7:0];
|
||||
4'h5 : timer1_count_max[15:8] <= DATA_IN[7:0];
|
||||
4'h6 : timer1_count_max[7:0] <= DATA_IN[7:0];
|
||||
4'h7 : timer1_enable <= DATA_IN[0];
|
||||
4'h8 : timer1_debounce <= 1'b1;
|
||||
default : ;
|
||||
endcase
|
||||
end
|
||||
else
|
||||
begin
|
||||
timer1_debounce <= 1'b0;
|
||||
end
|
||||
|
||||
|
||||
// Timer0 - Frequency Generator
|
||||
if (timer0_enable==1'b0 || timer0_counter==timer0_count_max)
|
||||
begin
|
||||
timer0_counter <= 'h0;
|
||||
timer0_out_int <= ~ timer0_out_int;
|
||||
end
|
||||
else
|
||||
begin
|
||||
timer0_counter <= timer0_counter + 1'b1;
|
||||
end
|
||||
|
||||
|
||||
|
||||
// Timer1 - One-shot Generator
|
||||
if (timer1_enable==1'b0 || timer1_counter[22:0]==timer1_count_max[23:1])
|
||||
begin
|
||||
timer1_counter <= 'h0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
timer1_counter <= timer1_counter + 1'b1;
|
||||
end
|
||||
|
||||
if (timer1_enable==1'b0 || timer1_debounce==1'b1)
|
||||
begin
|
||||
timer1_out_int <= 1'b0;
|
||||
end
|
||||
else if (timer1_counter[22:0]==timer1_count_max[23:1])
|
||||
begin
|
||||
timer1_out_int <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
endmodule // timer.v
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
//
|
||||
//
|
||||
// File Name : uart.v
|
||||
// Used on :
|
||||
// Author : Ted Fried, MicroCore Labs
|
||||
// Creation : 4/30/16
|
||||
// Code Type : Synthesizable
|
||||
//
|
||||
// Description:
|
||||
// ============
|
||||
//
|
||||
// Fixed 9600 baud rate UART
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
module uart
|
||||
(
|
||||
input CLK,
|
||||
input RST_n,
|
||||
|
||||
input [1:0] ADDRESS,
|
||||
input [7:0] DATA_IN,
|
||||
output [7:0] DATA_OUT,
|
||||
input STROBE_RD,
|
||||
input STROBE_WR,
|
||||
|
||||
input UART_RX,
|
||||
output UART_TX,
|
||||
output UART_INT
|
||||
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Internal Signals
|
||||
|
||||
reg RX_STATE;
|
||||
reg uart_rx_d;
|
||||
reg uart_rx_d1;
|
||||
reg uart_rx_d2;
|
||||
reg bit_clk;
|
||||
reg bit_clk_d;
|
||||
reg rx_havebyte;
|
||||
reg host_tx_go;
|
||||
reg host_tx_go_d;
|
||||
reg rx_byte_available;
|
||||
reg [7:0] tx_byte;
|
||||
reg [10:0] tx_count;
|
||||
reg [10:0] tx_shift_out;
|
||||
reg [8:0] rx_byte;
|
||||
reg [11:0] rx_count;
|
||||
reg [4:0] rx_bits;
|
||||
reg [15:0] prescaler;
|
||||
wire [1:0] uart_status;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Combinationals
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
assign UART_TX = tx_shift_out[0];
|
||||
|
||||
assign UART_INT = rx_byte_available;
|
||||
|
||||
assign DATA_OUT = (ADDRESS==2'h0) ? rx_byte[7:0] :
|
||||
(ADDRESS==2'h1) ? uart_status :
|
||||
8'hEE;
|
||||
|
||||
assign uart_status[1] = (tx_count[9:0]==10'b0000000000) ? 1'b0 : 1'b1; // 1=TX_BUSY
|
||||
assign uart_status[0] = rx_byte_available;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// UART Controller
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
always @(posedge CLK)
|
||||
begin : STATE_MACHINE
|
||||
|
||||
if (RST_n==1'b0)
|
||||
begin
|
||||
RX_STATE <= 'h0;
|
||||
uart_rx_d <= 1'b1;
|
||||
uart_rx_d1 <= 1'b1;
|
||||
uart_rx_d2 <= 1'b1;
|
||||
bit_clk <= 'h0;
|
||||
bit_clk_d <= 'h0;
|
||||
prescaler <= 'h0;
|
||||
rx_havebyte <= 'h0;
|
||||
rx_count <= 'h0;
|
||||
rx_byte <= 9'b1111_1111_1;
|
||||
tx_shift_out <= 11'b111_1111_1111;
|
||||
tx_count <= 'h0;
|
||||
host_tx_go <= 'h0;
|
||||
host_tx_go_d <= 'h0;
|
||||
tx_byte <= 8'hFF;
|
||||
rx_byte_available <= 'h0;
|
||||
rx_bits <= 'h0;
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Host interface and prescaler
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Prescaler fixed for 9600 baud - Xilinx 100Mhz = 16'h28B0
|
||||
// Prescaler fixed for 9600 baud - Xilinx 50Mhz = 16'h1458
|
||||
if (prescaler[15:0]==16'h1458)
|
||||
begin
|
||||
bit_clk <= ~ bit_clk;
|
||||
prescaler <= 'h0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
prescaler <= prescaler + 1'b1;
|
||||
end
|
||||
|
||||
bit_clk_d <= bit_clk;
|
||||
|
||||
|
||||
// Address: 0x0 - RO - RX_BYTE - reading clears the RX_HAS_BYTE bit
|
||||
// 0x1 - RO - UART status [1]=TX_BUSY [0]=RX_HAS_BYTE
|
||||
// 0x2 - WO - TX Byte - Sends the TX byte over UART
|
||||
|
||||
|
||||
// Writes to Registers
|
||||
if (STROBE_WR==1'b1 && ADDRESS[1:0]==2'h2)
|
||||
begin
|
||||
host_tx_go <= 1'b1;
|
||||
tx_byte <= DATA_IN;
|
||||
end
|
||||
else
|
||||
begin
|
||||
host_tx_go <= 1'b0;
|
||||
end
|
||||
|
||||
|
||||
if (rx_havebyte==1'b1)
|
||||
begin
|
||||
rx_byte_available <= 1'b1;
|
||||
end
|
||||
else if (STROBE_RD==1'b1 && ADDRESS[1:0]==2'h0)
|
||||
begin
|
||||
rx_byte_available <= 1'b0;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// RX Controller
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
uart_rx_d <= UART_RX;
|
||||
uart_rx_d1 <= uart_rx_d;
|
||||
uart_rx_d2 <= uart_rx_d1;
|
||||
|
||||
|
||||
case (RX_STATE) // synthesis parallel_case
|
||||
|
||||
1'h0 : begin
|
||||
// Debounce signals
|
||||
rx_havebyte <= 1'b0;
|
||||
rx_bits <= 'h0;
|
||||
|
||||
// Look for start bit
|
||||
if (uart_rx_d2==1'b0)
|
||||
begin
|
||||
rx_count <= rx_count + 1'b1;
|
||||
end
|
||||
|
||||
// Count half-way into the start bit
|
||||
if (rx_count==14'h1458)
|
||||
begin
|
||||
rx_count <= 'h0;
|
||||
rx_byte <= 9'b1_11111111;
|
||||
RX_STATE <= 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
1'h1 : begin
|
||||
rx_count <= rx_count + 1'b1;
|
||||
|
||||
// Count complete bit-times
|
||||
if (rx_count==14'h28B0)
|
||||
begin
|
||||
rx_byte[8:0] <= { uart_rx_d2 , rx_byte[8:1] };
|
||||
rx_bits <= rx_bits + 1'b1;
|
||||
rx_count <= 'h0;
|
||||
end
|
||||
|
||||
// Complete byte has been shifted in
|
||||
if (rx_bits==4'h9)
|
||||
begin
|
||||
rx_havebyte <= 1'b1;
|
||||
RX_STATE <= 1'h0;
|
||||
end
|
||||
end
|
||||
|
||||
default : ;
|
||||
endcase
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// TX Controller
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// Load transmit shifter on rising edge of host request
|
||||
host_tx_go_d <= host_tx_go;
|
||||
if (host_tx_go_d==1'b0 && host_tx_go==1'b1)
|
||||
begin
|
||||
tx_shift_out <= { 1'b1 , tx_byte , 1'b0 , 1'b1 };
|
||||
tx_count <= 11'b11111111111;
|
||||
end
|
||||
|
||||
// Otherwise shift out bits at each bit clock.
|
||||
// When tx_count is all zeros tye byte has been sent.
|
||||
else
|
||||
begin
|
||||
if (bit_clk_d != bit_clk)
|
||||
begin
|
||||
tx_shift_out[10:0] <= { 1'b1 , tx_shift_out[10:1] };
|
||||
tx_count[10:0] <= { 1'b0 , tx_count[10:1] };
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
Binary file not shown.
|
@ -0,0 +1,42 @@
|
|||
|
||||
MicroCore Labs – Lockstep Quad Modular Redundant System
|
||||
|
||||
|
||||
Description:
|
||||
------------
|
||||
Implementation of a Lockstep Quad Modular Redundant System using four MCL51's which are microsequencer-based 8051 CPU cores.
|
||||
|
||||
Please see the Application Note in the Documents directory for detailed information on this project.
|
||||
|
||||
|
||||
Highlights:
|
||||
-----------
|
||||
- Four MCL51 modules running in Lock Step
|
||||
- Four Voters - one per module
|
||||
- All 8051 CPU register and peripheral accesses are broadcast to neighgboring modules.
|
||||
- Modules are constantly broadcasting Microcode, Registers, User RAM, and Program ROM contents to neighboring cores.
|
||||
- If a Module's Voter detects a discrepancy, it puts module into Rebuild Mode.
|
||||
- While in Rebuild Mode the Module listens to neighbor core broadcasts and updates his resources accordingly.
|
||||
- Once a number of iterations of the complete broadcast cycle have complete, the module rejoins the Lock Step at the beginning of the next instruction.
|
||||
- The time from detecting a failure to rebuilding the module and rejoining the Lock Step is around 800uS for the example design.
|
||||
- Peripherals such as UARTs and Timers chose which module results to use based on the Module's Voter.
|
||||
- Modules failing, rebuilding, and rejoining the Lock Step is undetectable by the downstream peripherals and the other modules.
|
||||
- Healthy Modules are not actively involved with rebuilding failed modules and program execution proceeds unaffected and unnoticed by module failures.
|
||||
- Module cannot rejoin the lockstep while an interrupt is in progress because of the interrupt_flag
|
||||
|
||||
When Voter detects a failure:
|
||||
- The Module is put into rebuild mode where it listens to RAM, microcore, and register broadcasts from healthy modules.
|
||||
- The Lockstep's broadcasts are copied to the Rebuilding Module's local resources.
|
||||
- The Rebuilding Module will listen for a duration of to two address wrap-arounds to ensure that all memories are updated.
|
||||
- After this, the module waits for a SYNC pulse so it can then rejoin the lockstep.
|
||||
|
||||
|
||||
Notes:
|
||||
------
|
||||
Run Levels: Each of the four modules contains a run_level signal that indicates its "health"
|
||||
|
||||
run_level 0 = Rebuild running - Gate the BROADCAST_OK signal. Look for 3 address passes
|
||||
1 = Rebuilding is done - Waiting for SYNC
|
||||
2 = Switch from listening to Broadcast Mode
|
||||
3 = Rejoined Lockstep - ungate the BROADCAST_OK voter - Final Mode
|
||||
|
Loading…
Reference in New Issue