blob: e4fa77ac9b89675c03e93052b696d5c460f3b74d [file] [log] [blame]
// File name: wb_slave.sv
// Created: 6/1/2020
// Author: Zachary Ellis
// Version: Initial design entry
// Description: wishbone slave interface for CAN controller
/////////////////////////////////////////////////////
// Changes to be made
// - implement signals added based on notes
// - finish all IO
// - make assignments in the main always block
// - interrupts?
// - mailbox status register?
/////////////////////////////////////////////////////
module wb_slave (
//wb_interface
input wb_clk_i,
input wb_rst_i,
input [31:0] wb_adr_i,
input [31:0] wb_dat_i,
input [3:0] wb_sel_i,
input wb_we_i,
input wb_cyc_i,
input wb_stb_i,
output wb_ack_o,
output [31:0] wb_dat_o,
//connection to the rest of the peripheral
//general inputs
input bitstrobe,
input curr_sample,
input rx_busy,
input tx_busy,
//general outputs
output reg CAN_clk,
output CAN_nRST,
output tx_enable,
//timing stuff
output [3:0] TS1, //need to add this to timer
output [3:0] TS2, //need to add this to timer
//error stuff
input [7:0] REC,
input [7:0] TEC,
input error_passive,
input bus_off,
input [2:0] LEC, //need to add this to ECU
//fifo stuff
input [3:0] fifo_occupancy,
input fifo_full,
input fifo_empty,
input fifo_overrun,
input [31:0] fifo_data_L,
input [31:0] fifo_data_H,
input [28:0] fifo_ID,
input [3:0] fifo_pkt_size,
input fifo_RTR,
input fifo_EXT,
input [4:0] fifo_fmi,
input fifo_read,
output fifo_clear,
output overrun_enable,
output [19:0] mask_enable,
output [30:0] filter_0, //this is a yosys thing since you cant do input [19:0] [31:0]
output [30:0] mask_0,
output [30:0] filter_1,
output [30:0] mask_1,
output [30:0] filter_2,
output [30:0] mask_2,
output [30:0] filter_3,
output [30:0] mask_3,
output [30:0] filter_4,
output [30:0] mask_4,
output [30:0] filter_5,
output [30:0] mask_5,
output [30:0] filter_6,
output [30:0] mask_6,
output [30:0] filter_7,
output [30:0] mask_7,
output [30:0] filter_8,
output [30:0] mask_8,
output [30:0] filter_9,
output [30:0] mask_9,
output [30:0] filter_10,
output [30:0] mask_10,
output [30:0] filter_11,
output [30:0] mask_11,
output [30:0] filter_12,
output [30:0] mask_12,
output [30:0] filter_13,
output [30:0] mask_13,
output [30:0] filter_14,
output [30:0] mask_14,
output [30:0] filter_15,
output [30:0] mask_15,
output [30:0] filter_16,
output [30:0] mask_16,
output [30:0] filter_17,
output [30:0] mask_17,
output [30:0] filter_18,
output [30:0] mask_18,
output [30:0] filter_19,
output [30:0] mask_19,
output read_fifo,
//tx mailbox output to TCU
input tx_done, //add to TCU
input tx_arb_loss,//add to TCU
output reg tx_pkt_ready,
output reg [28:0] tx_ID,
output reg [3:0] tx_pkt_size,
output reg tx_RTR,
output reg tx_EXT,
output reg [63:0] tx_data
);
localparam BASE_ADDR = 32'h30000000;
typedef struct packed {
logic [25:0] res;
logic overrun_enable;
logic auto_retrans;
logic tx_priority; //need to implement these two features somewhere
logic sleep;
logic reset;
logic start;
} MCR_t; //Master control register 0x0000
MCR_t MCR;
assign overrun_enable = MCR.overrun_enable;
typedef struct packed {
logic [26:0] res;
logic tx_busy;
logic rx_busy;
logic curr_sample;
logic [1:0] mode;
} MSR_t; //Master status register 0x0004
MSR_t MSR;
typedef struct packed {
logic [22:0] res;
logic empty;
logic full;
logic [3:0] occupancy;
logic overrun;
logic read_fifo;
logic clear;
} FSCR_t; //FIFO status and control register 0x0008
FSCR_t FSCR;
assign fifo_clear = FSCR.clear;
assign read_fifo = FSCR.read_fifo;
typedef struct packed {
logic [20:0] res;
logic [4:0] fmi;
logic EXT;
logic RTR;
logic [3:0] size;
} FIR_t; //FIFO packet info register 0x000c
FIR_t FIR;
typedef struct packed {
logic [2:0] res;
logic [28:0] ID;
} FIDR_t; //FIFO ID register 0x0010
FIDR_t FIDR;
reg [31:0] FDLR; //FIFO data low register 0x0014
reg [31:0] FDHR; //FIFO data high register 0x0018
reg [31:0] FMER; //Filter enable register 0x001c
`ifdef SIM //vivado and yosys disagree
reg [19:0] [31:0] filters; //filter registers 0x0020 - 0x006c
reg [19:0] [31:0] masks; //filter mask registers 0x0070 - 0x00bc
`else
reg [31:0] filters[19:0]; //filter registers 0x0020 - 0x006c
reg [31:0] masks[19:0]; //filter mask registers 0x0070 - 0x00bc
`endif
typedef struct packed {
logic [10:0] res;
logic [2:0] LEC; //last error code
logic bus_off;
logic error_passive;
logic [7:0] TEC;
logic [7:0] REC;
} ESR_t; //Error status register 0x00c0
ESR_t ESR;
typedef struct packed {
logic [15:0] res;
logic [2:0] TS2;
logic [2:0] TS1;
logic [9:0] BRP;
} TMGR_t; //timing 0x00c4
TMGR_t TMGR;
assign TS1 = TMGR.TS1 + 1;
assign TS2 = TMGR.TS2 + 1;
typedef struct packed {
logic data_ready;
logic EXT;
logic RTR;
logic [28:0] ID;
} MLIDxR_t; //TX mailbox #x ID register
MLIDxR_t [2:0] MLIDxR; //0x00c8 - 0x00d0
typedef struct packed {
logic [27:0] res;
logic [3:0] DLC;
} MLSxR_t; //TX mailbox #x packet size register
MLSxR_t [2:0] MLSxR; //0x00d4 -0x00dc
`ifdef SIM //vivado and yosys disagree
reg [2:0] [31:0] MLDLxR; //TX mailbox data low registers 0x00e0 - 0x00e8
reg [2:0] [31:0] MLDHxR; //TX mailbox data high registers 0x00ec - 0x00f4
`else
reg [31:0] MLDLxR[2:0]; //TX mailbox data low registers 0x00e0 - 0x00e8
reg [31:0] MLDHxR[2:0]; //TX mailbox data high registers 0x00ec - 0x00f4
`endif
wire nRST = ~wb_rst_i;
wire [31:0] data_sel;
assign data_sel[31:24] = {8{wb_sel_i[3]}};
assign data_sel[23:16] = {8{wb_sel_i[2]}};
assign data_sel[15:8] = {8{wb_sel_i[1]}};
assign data_sel[7:0] = {8{wb_sel_i[0]}};
reg [31:0] raw_dat_o;
assign wb_dat_o = raw_dat_o & data_sel;
wire valid = wb_cyc_i & wb_stb_i;
reg [1:0] chosen_mailbox;
reg lock; //lock output while it is being transmitted
reg [1:0] ack;
assign wb_ack_o = ack[1] & valid;
always @(posedge wb_clk_i, negedge nRST) begin
if(nRST == 0) begin
MCR <= '0;
MSR <= '0;
FSCR <= '0;
FIR <= '0;
FIDR <= '0;
FDLR <= '0;
FDHR <= '0;
FMER <= '0;
filters <= '0;
masks <= '0;
ESR <= '0;
TMGR <= '0;
MLIDxR <= '0;
MLSxR <= '0;
MLDLxR <= '0;
MLDHxR <= '0;
ack <= '0;
raw_dat_o <= '0;
lock <= 0;
end
else begin
ack[0] <= wb_cyc_i & wb_stb_i;
ack[1] <= ack[0];
raw_dat_o <= '0;
MCR.reset <= 1'b0;
if(valid) begin
case(wb_adr_i[7:2])
6'd0: begin
if(wb_we_i) MCR <= wb_dat_i & data_sel;
else raw_dat_o <= MCR & data_sel;
MCR.res <= '0;
end
6'd1: begin
if(~wb_we_i) raw_dat_o <= MSR & data_sel;
MSR.res <= '0;
end
6'd2: begin
if(wb_we_i) FSCR <= wb_dat_i & data_sel;
else raw_dat_o <= FSCR & data_sel;
FSCR.res <= '0;
end
6'd3: begin
if(~wb_we_i) raw_dat_o <= FIR & data_sel;
FIR.res <= '0;
end
6'd4: begin
if(~wb_we_i) raw_dat_o <= FIDR & data_sel;
FIDR.res <= '0;
end
6'd5: if(~wb_we_i) raw_dat_o <= FDLR & data_sel;
6'd6: if(~wb_we_i) raw_dat_o <= FDHR & data_sel;
6'd7: begin
if(wb_we_i) FMER <= wb_dat_i & data_sel;
else raw_dat_o <= FMER & data_sel;
FMER[31:20] <= '0;
end
6'd8: begin
if(wb_we_i) filters[0] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[0] & data_sel;
filters[0][31] <= 1'b0;
end
6'd9: begin
if(wb_we_i) filters[1] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[1] & data_sel;
filters[1][31] <= 1'b0;
end
6'd10: begin
if(wb_we_i) filters[2] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[2] & data_sel;
filters[2][31] <= 1'b0;
end
6'd11: begin
if(wb_we_i) filters[3] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[3] & data_sel;
filters[3][31] <= 1'b0;
end
6'd12: begin
if(wb_we_i) filters[4] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[4] & data_sel;
filters[4][31] <= 1'b0;
end
6'd13: begin
if(wb_we_i) filters[5] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[5] & data_sel;
filters[5][31] <= 1'b0;
end
6'd14: begin
if(wb_we_i) filters[6] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[6] & data_sel;
filters[6][31] <= 1'b0;
end
6'd15: begin
if(wb_we_i) filters[7] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[7] & data_sel;
filters[7][31] <= 1'b0;
end
6'd16: begin
if(wb_we_i) filters[8] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[8] & data_sel;
filters[8][31] <= 1'b0;
end
6'd17: begin
if(wb_we_i) filters[9] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[9] & data_sel;
filters[9][31] <= 1'b0;
end
6'd18: begin
if(wb_we_i) filters[10] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[10] & data_sel;
filters[10][31] <= 1'b0;
end
6'd19: begin
if(wb_we_i) filters[11] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[11] & data_sel;
filters[11][31] <= 1'b0;
end
6'd20: begin
if(wb_we_i) filters[12] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[12] & data_sel;
filters[12][31] <= 1'b0;
end
6'd21: begin
if(wb_we_i) filters[13] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[13] & data_sel;
filters[13][31] <= 1'b0;
end
6'd22: begin
if(wb_we_i) filters[14] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[14] & data_sel;
filters[14][31] <= 1'b0;
end
6'd23: begin
if(wb_we_i) filters[15] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[15] & data_sel;
filters[15][31] <= 1'b0;
end
6'd24: begin
if(wb_we_i) filters[16] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[16] & data_sel;
filters[16][31] <= 1'b0;
end
6'd25: begin
if(wb_we_i) filters[17] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[17] & data_sel;
filters[17][31] <= 1'b0;
end
6'd26: begin
if(wb_we_i) filters[18] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[18] & data_sel;
filters[18][31] <= 1'b0;
end
6'd27: begin
if(wb_we_i) filters[19] <= wb_dat_i & data_sel;
else raw_dat_o <= filters[19] & data_sel;
filters[19][31] <= 1'b0;
end
6'd28: begin
if(wb_we_i) masks[0] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[0] & data_sel;
masks[0][31] <= 1'b0;
end
6'd29: begin
if(wb_we_i) masks[1] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[1] & data_sel;
masks[1][31] <= 1'b0;
end
6'd30: begin
if(wb_we_i) masks[2] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[2] & data_sel;
masks[2][31] <= 1'b0;
end
6'd31: begin
if(wb_we_i) masks[3] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[3] & data_sel;
masks[3][31] <= 1'b0;
end
6'd32: begin
if(wb_we_i) masks[4] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[4] & data_sel;
masks[4][31] <= 1'b0;
end
6'd33: begin
if(wb_we_i) masks[5] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[5] & data_sel;
masks[5][31] <= 1'b0;
end
6'd34: begin
if(wb_we_i) masks[6] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[6] & data_sel;
masks[6][31] <= 1'b0;
end
6'd35: begin
if(wb_we_i) masks[7] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[7] & data_sel;
masks[7][31] <= 1'b0;
end
6'd36: begin
if(wb_we_i) masks[8] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[8] & data_sel;
masks[8][31] <= 1'b0;
end
6'd37: begin
if(wb_we_i) masks[9] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[9] & data_sel;
masks[9][31] <= 1'b0;
end
6'd38: begin
if(wb_we_i) masks[10] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[10] & data_sel;
masks[10][31] <= 1'b0;
end
6'd39: begin
if(wb_we_i) masks[11] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[11] & data_sel;
masks[11][31] <= 1'b0;
end
6'd40: begin
if(wb_we_i) masks[12] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[12] & data_sel;
masks[12][31] <= 1'b0;
end
6'd41: begin
if(wb_we_i) masks[13] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[13] & data_sel;
masks[13][31] <= 1'b0;
end
6'd42: begin
if(wb_we_i) masks[14] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[14] & data_sel;
masks[14][31] <= 1'b0;
end
6'd43: begin
if(wb_we_i) masks[15] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[15] & data_sel;
masks[15][31] <= 1'b0;
end
6'd44: begin
if(wb_we_i) masks[16] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[16] & data_sel;
masks[16][31] <= 1'b0;
end
6'd45: begin
if(wb_we_i) masks[17] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[17] & data_sel;
masks[17][31] <= 1'b0;
end
6'd46: begin
if(wb_we_i) masks[18] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[18] & data_sel;
masks[18][31] <= 1'b0;
end
6'd47: begin
if(wb_we_i) masks[19] <= wb_dat_i & data_sel;
else raw_dat_o <= masks[19] & data_sel;
masks[19][31] <= 1'b0;
end
6'd48: begin
if(~wb_we_i) raw_dat_o <= ESR & data_sel;
ESR.res <= '0;
end
6'd49: begin
if(wb_we_i) TMGR <= wb_dat_i & data_sel;
else raw_dat_o = TMGR & data_sel;
TMGR.res <= '0;
end
6'd50: begin
if(wb_we_i) MLIDxR[0] <= wb_dat_i & data_sel;
else raw_dat_o <= MLIDxR[0] & data_sel;
end
6'd51: begin
if(wb_we_i) MLIDxR[1] <= wb_dat_i & data_sel;
else raw_dat_o <= MLIDxR[1] & data_sel;
end
6'd52: begin
if(wb_we_i) MLIDxR[2] <= wb_dat_i & data_sel;
else raw_dat_o <= MLIDxR[2] & data_sel;
end
6'd53: begin
if(wb_we_i) MLSxR[0] <= wb_dat_i & data_sel;
else raw_dat_o <= MLSxR[0] & data_sel;
MLSxR[0].res <= '0;
end
6'd54: begin
if(wb_we_i) MLSxR[1] <= wb_dat_i & data_sel;
else raw_dat_o <= MLSxR[1] & data_sel;
MLSxR[1].res <= '0;
end
6'd55: begin
if(wb_we_i) MLSxR[2] <= wb_dat_i & data_sel;
else raw_dat_o <= MLSxR[2] & data_sel;
MLSxR[2].res <= '0;
end
6'd56: begin
if(wb_we_i) MLDLxR[0] <= wb_dat_i & data_sel;
else raw_dat_o <= MLDLxR[0] & data_sel;
end
6'd57: begin
if(wb_we_i) MLDLxR[1] <= wb_dat_i & data_sel;
else raw_dat_o <= MLDLxR[1] & data_sel;
end
6'd58: begin
if(wb_we_i) MLDLxR[2] <= wb_dat_i & data_sel;
else raw_dat_o <= MLDLxR[2] & data_sel;
end
6'd59: begin
if(wb_we_i) MLDHxR[0] <= wb_dat_i & data_sel;
else raw_dat_o <= MLDHxR[0] & data_sel;
end
6'd60: begin
if(wb_we_i) MLDHxR[1] <= wb_dat_i & data_sel;
else raw_dat_o <= MLDHxR[1] & data_sel;
end
6'd61: begin
if(wb_we_i) MLDHxR[2] <= wb_dat_i & data_sel;
else raw_dat_o <= MLDHxR[2] & data_sel;
end
default: raw_dat_o <= 0;
endcase
end
if(~(valid)) raw_dat_o <= '0;
MCR.reset <= 1'b0;
FSCR.clear <= 1'b0;
if(MSR.mode == 0) MCR.sleep <= 1'b0;
MSR.curr_sample <= curr_sample;
MSR.rx_busy <= rx_busy;
MSR.tx_busy <= tx_busy;
FSCR.overrun <= fifo_overrun;
FSCR.occupancy <= fifo_occupancy;
FSCR.full <= fifo_full;
FSCR.empty <= fifo_empty;
FIR.size <= fifo_pkt_size;
FIR.RTR <= fifo_RTR;
FIR.EXT <= fifo_EXT;
FIR.fmi <= fifo_fmi;
FIDR.ID <= fifo_ID;
ESR.REC <= REC;
ESR.TEC <= TEC;
ESR.error_passive <= error_passive;
ESR.bus_off <= bus_off;
ESR.LEC <= LEC;
FDLR <= fifo_data_L;
FDHR <= fifo_data_H;
if(fifo_read) FSCR.read_fifo <= '0;
if(tx_done) begin
MLIDxR[chosen_mailbox].data_ready <= 0;
lock <= 0;
end
else if(~MCR.auto_retrans && tx_arb_loss) begin
MLIDxR[chosen_mailbox].data_ready <= 0;
lock <= 0;
end
end
end
reg enable_CAN, next_enable_CAN;
reg [1:0] next_MSR_mode;
wire TX_clear;
always_ff @(posedge wb_clk_i, negedge nRST) begin //might need to integrate this into main always block
if(nRST == 0) begin
enable_CAN <= 1'b0;
MSR.mode <= '0;
end
else begin
enable_CAN <= next_enable_CAN;
MSR.mode <= next_MSR_mode;
end
end
always_comb begin
next_enable_CAN = enable_CAN;
next_MSR_mode = MSR.mode;
case(MSR.mode)
2'b00: begin
if(MCR.start) begin
next_MSR_mode = 2'b01;
next_enable_CAN = 1'b1;
end
end
2'b01: if(TX_clear) next_MSR_mode = 2'b10;
2'b10: begin
if(MCR.sleep && ~tx_busy) begin
next_MSR_mode = 2'b00;
next_enable_CAN = 1'b0;
end
end
endcase
end
assign CAN_nRST = nRST & ~MCR.reset;
assign tx_enable = MSR.mode == 2;
wire [10:0] BRP = TMGR.BRP + 1;
reg [10:0] prescaler_count;
always @(posedge wb_clk_i, negedge nRST) begin
if(nRST == 0) begin
prescaler_count <= '0;
CAN_clk <= '0;
end
else if(enable_CAN) begin
if(prescaler_count == BRP) begin
prescaler_count <= 1;
CAN_clk <= 1;
end
else begin
prescaler_count <= prescaler_count + 1;
CAN_clk <= 0;
end
end
end
flex_counter #(
.NUM_CNT_BITS(4)
)
TX_CLEAR(
.clk(bitstrobe),
.n_rst(nRST),
.clear(~curr_sample),
.count_enable(curr_sample),
.rollover_val(4'd11),
.count_out(),
.rollover_flag(TX_clear)
);
assign filter_0 = filters[0][30:0];
assign mask_0 = masks[0][30:0];
assign filter_1 = filters[1][30:0];
assign mask_1 = masks[1][30:0];
assign filter_2 = filters[2][30:0];
assign mask_2 = masks[2][30:0];
assign filter_3 = filters[3][30:0];
assign mask_3 = masks[3][30:0];
assign filter_4 = filters[4][30:0];
assign mask_4 = masks[4][30:0];
assign filter_5 = filters[5][30:0];
assign mask_5 = masks[5][30:0];
assign filter_6 = filters[6][30:0];
assign mask_6 = masks[6][30:0];
assign filter_7 = filters[7][30:0];
assign mask_7 = masks[7][30:0];
assign filter_8 = filters[8][30:0];
assign mask_8 = masks[8][30:0];
assign filter_9 = filters[9][30:0];
assign mask_9 = masks[9][30:0];
assign filter_10 = filters[10][30:0];
assign mask_10 = masks[10][30:0];
assign filter_11 = filters[11][30:0];
assign mask_11 = masks[11][30:0];
assign filter_12 = filters[12][30:0];
assign mask_12 = masks[12][30:0];
assign filter_13 = filters[13][30:0];
assign mask_13 = masks[13][30:0];
assign filter_14 = filters[14][30:0];
assign mask_14 = masks[14][30:0];
assign filter_15 = filters[15][30:0];
assign mask_15 = masks[15][30:0];
assign filter_16 = filters[16][30:0];
assign mask_16 = masks[16][30:0];
assign filter_17 = filters[17][30:0];
assign mask_17 = masks[17][30:0];
assign filter_18 = filters[18][30:0];
assign mask_18 = masks[18][30:0];
assign filter_19 = filters[19][30:0];
assign mask_19 = masks[19][30:0];
assign mask_enable = FMER[19:0];
//WARNING: need to make sure to hold while mailbox is being read
always_ff @(posedge wb_clk_i, negedge nRST) begin
if(nRST == 0) begin
tx_pkt_ready <= '0;
tx_ID <= '0;
tx_pkt_size <= '0;
tx_RTR <= '0;
tx_EXT <= '0;
tx_data <= '0;
chosen_mailbox <= '0;
end
else begin
if(MCR.tx_priority & ~lock) begin
if(MLIDxR[0].data_ready) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[0].ID;
tx_pkt_size <= MLSxR[0].DLC;
tx_RTR <= MLIDxR[0].RTR;
tx_EXT <= MLIDxR[0].EXT;
tx_data <= {MLDHxR[0], MLDLxR[0]};
chosen_mailbox <= '0;
lock <= 1;
end
else if(MLIDxR[1].data_ready) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[1].ID;
tx_pkt_size <= MLSxR[1].DLC;
tx_RTR <= MLIDxR[1].RTR;
tx_EXT <= MLIDxR[1].EXT;
tx_data <= {MLDHxR[1], MLDLxR[1]};
chosen_mailbox <= 1;
lock <= 1;
end
else if(MLIDxR[2].data_ready) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[2].ID;
tx_pkt_size <= MLSxR[2].DLC;
tx_RTR <= MLIDxR[2].RTR;
tx_EXT <= MLIDxR[2].EXT;
tx_data <= {MLDHxR[2], MLDLxR[2]};
chosen_mailbox <= 2;
lock <= 1;
end
else begin
tx_pkt_ready <= 0;
chosen_mailbox <= '0;
lock <= 0;
end
end
else if(~lock) begin
case({MLIDxR[2].data_ready, MLIDxR[1].data_ready, MLIDxR[0].data_ready})
3'b001: begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[0].ID;
tx_pkt_size <= MLSxR[0].DLC;
tx_RTR <= MLIDxR[0].RTR;
tx_EXT <= MLIDxR[0].EXT;
tx_data <= {MLDHxR[0], MLDLxR[0]};
chosen_mailbox <= '0;
lock <= 1;
end
3'b010: begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[1].ID;
tx_pkt_size <= MLSxR[1].DLC;
tx_RTR <= MLIDxR[1].RTR;
tx_EXT <= MLIDxR[1].EXT;
tx_data <= {MLDHxR[1], MLDLxR[1]};
chosen_mailbox <= 1;
lock <= 1;
end
3'b100: begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[2].ID;
tx_pkt_size <= MLSxR[2].DLC;
tx_RTR <= MLIDxR[2].RTR;
tx_EXT <= MLIDxR[2].EXT;
tx_data <= {MLDHxR[2], MLDLxR[2]};
chosen_mailbox <= 2;
lock <= 1;
end
3'b011: begin
if(MLIDxR[0].ID <= MLIDxR[1].ID) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[0].ID;
tx_pkt_size <= MLSxR[0].DLC;
tx_RTR <= MLIDxR[0].RTR;
tx_EXT <= MLIDxR[0].EXT;
tx_data <= {MLDHxR[0], MLDLxR[0]};
chosen_mailbox <= '0;
lock <= 1;
end
else begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[1].ID;
tx_pkt_size <= MLSxR[1].DLC;
tx_RTR <= MLIDxR[1].RTR;
tx_EXT <= MLIDxR[1].EXT;
tx_data <= {MLDHxR[1], MLDLxR[1]};
chosen_mailbox <= 1;
lock <= 1;
end
end
3'b101: begin
if(MLIDxR[0].ID <= MLIDxR[2].ID) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[0].ID;
tx_pkt_size <= MLSxR[0].DLC;
tx_RTR <= MLIDxR[0].RTR;
tx_EXT <= MLIDxR[0].EXT;
tx_data <= {MLDHxR[0], MLDLxR[0]};
chosen_mailbox <= '0;
lock <= 1;
end
else begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[2].ID;
tx_pkt_size <= MLSxR[2].DLC;
tx_RTR <= MLIDxR[2].RTR;
tx_EXT <= MLIDxR[2].EXT;
tx_data <= {MLDHxR[2], MLDLxR[2]};
chosen_mailbox <= 2;
lock <= 1;
end
end
3'b110: begin
if(MLIDxR[1].ID <= MLIDxR[2].ID) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[1].ID;
tx_pkt_size <= MLSxR[1].DLC;
tx_RTR <= MLIDxR[1].RTR;
tx_EXT <= MLIDxR[1].EXT;
tx_data <= {MLDHxR[1], MLDLxR[1]};
chosen_mailbox <= 1;
lock <= 1;
end
else begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[2].ID;
tx_pkt_size <= MLSxR[2].DLC;
tx_RTR <= MLIDxR[2].RTR;
tx_EXT <= MLIDxR[2].EXT;
tx_data <= {MLDHxR[2], MLDLxR[2]};
chosen_mailbox <= 2;
lock <= 1;
end
end
3'b111: begin
if(MLIDxR[0].ID <= MLIDxR[1].ID) begin
if(MLIDxR[0].ID <= MLIDxR[2].ID) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[0].ID;
tx_pkt_size <= MLSxR[0].DLC;
tx_RTR <= MLIDxR[0].RTR;
tx_EXT <= MLIDxR[0].EXT;
tx_data <= {MLDHxR[0], MLDLxR[0]};
chosen_mailbox <= '0;
lock <= 1;
end
else begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[2].ID;
tx_pkt_size <= MLSxR[2].DLC;
tx_RTR <= MLIDxR[2].RTR;
tx_EXT <= MLIDxR[2].EXT;
tx_data <= {MLDHxR[2], MLDLxR[2]};
chosen_mailbox <= 2;
lock <= 1;
end
end
else if(MLIDxR[1].ID <= MLIDxR[2].ID) begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[1].ID;
tx_pkt_size <= MLSxR[1].DLC;
tx_RTR <= MLIDxR[1].RTR;
tx_EXT <= MLIDxR[1].EXT;
tx_data <= {MLDHxR[1], MLDLxR[1]};
chosen_mailbox <= 1;
lock <= 1;
end
else begin
tx_pkt_ready <= 1;
tx_ID <= MLIDxR[2].ID;
tx_pkt_size <= MLSxR[2].DLC;
tx_RTR <= MLIDxR[2].RTR;
tx_EXT <= MLIDxR[2].EXT;
tx_data <= {MLDHxR[2], MLDLxR[2]};
chosen_mailbox <= 2;
lock <= 1;
end
end
default: begin
tx_pkt_ready <= 0;
chosen_mailbox <= '0;
lock <= 0;
end
endcase
end
end
end
endmodule