| // 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 |