blob: b22d945256f4f26ebb9444c2c43f5679bfd0ef93 [file] [log] [blame]
// MIT License
// Copyright (c) [2022] [Yonga Technology Microelectronics R&D]
// 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.
// DESCRIPTION
// The yonga_can_top module includes the register access logic and
// top-level logic of CAN peripheral
`default_nettype none
module yonga_can_top #(
parameter BITS = 32
)(
input wire clk,
input wire rst,
output reg ready,
input wire valid,
output reg [BITS-1:0] rdata,
input wire [BITS-1:0] wdata,
input wire [3:0] wstrb,
input wire device_reg_wr_en,
input wire [4:0] device_addr,
input wire [BITS-1:0] device_reg_wr_data,
output reg [BITS-1:0] device_reg_rd_data,
output wire can_tx,
input wire can_rx,
output reg [BITS-1:0] count
);
// reg ready;
// reg [BITS-1:0] device_reg_rd_data;
// reg [BITS-1:0] count;
// reg [BITS-1:0] rdata;
reg [BITS-1:0] BAUD_RATE_CFG_REG;
reg [BITS-1:0] MSG_ID_REG;
reg [BITS-1:0] MSG_CFG_REG;
reg [BITS-1:0] DATA_REG1_REG;
reg [BITS-1:0] DATA_REG2_REG;
reg [BITS-1:0] SYS_CFG_REG;
reg [BITS-1:0] SYS_CTRL_STS_REG;
wire [2:0] sts_code;
// CPU controls the peripheral via pseudo memory-mapped registers
always @(posedge clk) begin
if (rst) begin
BAUD_RATE_CFG_REG <= 32'h0;
MSG_ID_REG <= 32'h0;
MSG_CFG_REG <= 32'h0;
DATA_REG1_REG <= 32'h0;
DATA_REG2_REG <= 32'h0;
SYS_CFG_REG <= 32'h0;
SYS_CTRL_STS_REG <= 32'h0;
count <= 0;
ready <= 0;
rdata <= 32'h0;
end
else begin
ready <= 1'b0;
SYS_CTRL_STS_REG[0] <= 1'b0; // SEND bit is self-clearing
if (valid && !ready) begin
ready <= 1'b1;
rdata <= 32'h0;
if(wdata[0] && device_addr[4:0] == 5'h0) begin
device_reg_rd_data <= BAUD_RATE_CFG_REG;
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[0]) BAUD_RATE_CFG_REG[7:0] <= device_reg_wr_data[7:0];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[1]) BAUD_RATE_CFG_REG[15:8] <= device_reg_wr_data[15:8];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[2]) BAUD_RATE_CFG_REG[23:16] <= device_reg_wr_data[23:16];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[3]) BAUD_RATE_CFG_REG[31:24] <= device_reg_wr_data[31:24];
end
else if(wdata[0] && device_addr[4:0] == 5'h4) begin
device_reg_rd_data <= MSG_ID_REG;
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[0]) MSG_ID_REG[7:0] <= device_reg_wr_data[7:0];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[1]) MSG_ID_REG[15:8] <= device_reg_wr_data[15:8];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[2]) MSG_ID_REG[23:16] <= device_reg_wr_data[23:16];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[3]) MSG_ID_REG[31:24] <= device_reg_wr_data[31:24];
end
else if(wdata[0] && device_addr[4:0] == 5'h8) begin
device_reg_rd_data <= MSG_CFG_REG;
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[0]) MSG_CFG_REG[7:0] <= device_reg_wr_data[7:0];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[1]) MSG_CFG_REG[15:8] <= device_reg_wr_data[15:8];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[2]) MSG_CFG_REG[23:16] <= device_reg_wr_data[23:16];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[3]) MSG_CFG_REG[31:24] <= device_reg_wr_data[31:24];
end
else if(wdata[0] && device_addr[4:0] == 5'hC) begin
device_reg_rd_data <= DATA_REG1_REG;
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[0]) DATA_REG1_REG[7:0] <= device_reg_wr_data[7:0];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[1]) DATA_REG1_REG[15:8] <= device_reg_wr_data[15:8];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[2]) DATA_REG1_REG[23:16] <= device_reg_wr_data[23:16];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[3]) DATA_REG1_REG[31:24] <= device_reg_wr_data[31:24];
end
else if(wdata[0] && device_addr[4:0] == 5'h10) begin
device_reg_rd_data <= DATA_REG2_REG;
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[0]) DATA_REG2_REG[7:0] <= device_reg_wr_data[7:0];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[1]) DATA_REG2_REG[15:8] <= device_reg_wr_data[15:8];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[2]) DATA_REG2_REG[23:16] <= device_reg_wr_data[23:16];
if (SYS_CFG_REG[1] && device_reg_wr_en && wstrb[3]) DATA_REG2_REG[31:24] <= device_reg_wr_data[31:24];
end
else if(wdata[0] && device_addr[4:0] == 5'h14) begin
device_reg_rd_data <= SYS_CFG_REG;
if (device_reg_wr_en && wstrb[0]) SYS_CFG_REG[7:0] <= device_reg_wr_data[7:0];
if (device_reg_wr_en && wstrb[1]) SYS_CFG_REG[15:8] <= device_reg_wr_data[15:8];
if (device_reg_wr_en && wstrb[2]) SYS_CFG_REG[23:16] <= device_reg_wr_data[23:16];
if (device_reg_wr_en && wstrb[3]) SYS_CFG_REG[31:24] <= device_reg_wr_data[31:24];
end
else if(wdata[0] && device_addr[4:0] == 5'h18) begin
device_reg_rd_data <= SYS_CTRL_STS_REG;
if (device_reg_wr_en && wstrb[0]) SYS_CTRL_STS_REG[7:0] <= device_reg_wr_data[7:0];
if (device_reg_wr_en && wstrb[1]) SYS_CTRL_STS_REG[15:8] <= device_reg_wr_data[15:8];
if (device_reg_wr_en && wstrb[2]) SYS_CTRL_STS_REG[23:16] <= device_reg_wr_data[23:16];
if (device_reg_wr_en && wstrb[3]) SYS_CTRL_STS_REG[31:24] <= device_reg_wr_data[31:24];
end
end
if (sts_code != 3'b0) begin
SYS_CTRL_STS_REG[3:1] <= sts_code;
end
end
end
wire ack_slot_flag;
wire pulse_gen_en, pulse_gen_synced, pulse_gen_drive_pulse, pulse_gen_sample_pulse;
wire packetizer_en, packetizer_rdy, packetizer_message_bit;
// use can_tx for receive channel in loopback mode
wire can_rx_mux;
assign can_rx_mux = (SYS_CFG_REG[0] == 1'b1) ? ((ack_slot_flag == 1'b1) ? ~can_tx : can_tx) : can_rx;
// instantiate yonga_can_pulse_gen
yonga_can_pulse_gen inst_yonga_can_pulse_gen(
.i_pulse_gen_clk(clk),
.i_pulse_gen_rst(rst),
.i_pulse_gen_config_en(pulse_gen_en),
.i_pulse_gen_prescaler_val(BAUD_RATE_CFG_REG[26:18]),
.i_pulse_gen_phase_seg1_time_quanta_val(BAUD_RATE_CFG_REG[17:9]),
.i_pulse_gen_phase_seg2_time_quanta_val(BAUD_RATE_CFG_REG[8:0]),
.o_pulse_gen_synced(pulse_gen_synced),
.o_pulse_gen_drive_pulse(pulse_gen_drive_pulse),
.o_pulse_gen_sample_pulse(pulse_gen_sample_pulse)
);
// instantiate yonga_can_controller
yonga_can_controller inst_yonga_can_controller(
.i_controller_clk(clk),
.i_controller_rst(rst),
.i_pulse_gen_synced(pulse_gen_synced),
.i_packetizer_rdy(packetizer_rdy),
.i_ack_slot(ack_slot_flag),
.o_packetizer_en(packetizer_en),
.o_pulse_gen_en(pulse_gen_en),
.i_packetizer_message_bit(packetizer_message_bit),
.i_message_bit(can_rx_mux),
.o_message_bit(can_tx),
.i_drive_pulse(pulse_gen_drive_pulse),
.i_sample_pulse(pulse_gen_sample_pulse),
.i_config_enable(SYS_CFG_REG[1]),
.i_sys_ctrl_sts_send(SYS_CTRL_STS_REG[0]),
.o_sts_code(sts_code)
);
// instantiate yonga_can_controller
yonga_can_packetizer inst_yonga_can_packetizer(
.i_packetizer_clk(clk),
.i_packetizer_rst(rst),
.i_packetizer_en(packetizer_en),
.i_drive_pulse(pulse_gen_drive_pulse),
.i_packetizer_message_sid(MSG_ID_REG[29:19]),
.i_packetizer_message_ide(MSG_ID_REG[18]),
.i_packetizer_message_r0(1'b0),
.i_packetizer_message_r1(1'b0),
.i_packetizer_message_srr(1'b1),
.i_packetizer_message_eid(MSG_ID_REG[17:0]),
.i_packetizer_message_rtr(MSG_CFG_REG[4]),
.i_packetizer_message_dlc(MSG_CFG_REG[3:0]),
.i_packetizer_message_data_byte_0(DATA_REG1_REG[7:0]),
.i_packetizer_message_data_byte_1(DATA_REG1_REG[15:8]),
.i_packetizer_message_data_byte_2(DATA_REG1_REG[23:16]),
.i_packetizer_message_data_byte_3(DATA_REG1_REG[31:24]),
.i_packetizer_message_data_byte_4(DATA_REG2_REG[7:0]),
.i_packetizer_message_data_byte_5(DATA_REG2_REG[15:8]),
.i_packetizer_message_data_byte_6(DATA_REG2_REG[23:16]),
.i_packetizer_message_data_byte_7(DATA_REG2_REG[31:24]),
.o_packetizer_rdy(packetizer_rdy),
.i_packetizer_req(/* NOT USED */),
.o_packetizer_message_bit(packetizer_message_bit),
.i_packetizer_message_bit(/* NOT USED */),
.o_ack_slot(ack_slot_flag)
);
endmodule
`default_nettype wire