summaryrefslogtreecommitdiff
path: root/rtl/axi_timer/axi_timer.sv
blob: 80a1805f24baa2bbc1a9502a7ab224eb6a5751b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//axi_timer top file

module axi_timer(
  input i_clk,
  input i_rst_n,

  axi_bus.Slave axi_slave,

  output logic  o_IRQ
  );

// verilator lint_off CASEINCOMPLETE
// verilator lint_off WIDTHEXPAND
// verilator lint_off WIDTHTRUNC

enum logic [2:0] {
  CR_ADDR       = 3'd0,
  SR_ADDR       = 3'd1,
  PERIOD_ADDR   = 3'd2,
  COUNTER_ADDR  = 3'd3,
  IRQ_CNT_ADDR  = 3'd4
} address_map;

/*Register map for axi_timer */
//CR register
logic         enable;
//SR register
logic         irq;
//PERIOD register
logic [31:0]  period;
//COUNTER register
logic [31:0]  counter;
//IRQ_CNT register
logic [31:0]  irq_cnt;

/* Native interface for access to register */
logic         addr_valid;
logic         addr;
logic         addr_ready;
logic         addr_write;

logic         write_valid;
logic [31:0]  wdata;
logic         write_ready;

logic         read_valid;
logic [31:0]  rdata;
logic         read_ready;

/* Address section */
assign  addr_valid        = axi_slave.AVALID;
assign  addr_write        = axi_slave.AWRITE;
assign  axi_slave.AREADY  = addr_ready;

always_ff @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n)
    addr_ready  <=  1'b0;
  else if(addr_valid & addr_write)
    addr_ready  <=  1'b1;
  else
    addr_ready  <=  1'b0;

always_ff @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n)
    addr  <=  'h0;
  else if(addr_ready & addr_write)
    addr  <=  axi_slave.ADDR;

/*Write section */
assign  write_valid       = axi_slave.WVALID;
assign  axi_slave.WREADY  = write_ready;
assign  wdata             = axi_slave.WDATA;

always_ff @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n)
    write_ready <=  1'b0;
  else if(write_valid)
    write_ready <=  1'b1;
  else
    write_ready <=  1'b0;

/* registers write logic */
always_ff @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n) begin
    enable  <=  1'b0;
    period  <=  32'd0;
    irq_cnt <=  32'd0;
  end
  else if(write_valid) begin
    case(addr)
      CR_ADDR:      enable  <=  wdata[0];
      PERIOD_ADDR:  counter <=  wdata;
      IRQ_CNT_ADDR: irq_cnt <=  wdata;
    endcase
  end

/*Read section */
assign axi_slave.RVALID = read_valid;
assign read_ready = axi_slave.RREADY;
assign axi_slave.RDATA = rdata;

always_ff @ (posedge i_clk, negedge i_rst_n)
  if(!i_rst_n) begin
    rdata       <=  32'd0;
    read_valid  <=  1'b0;
  end
  else if(read_ready) begin
    read_valid  <=  1'b1;
    case(addr)
      CR_ADDR:      rdata <=  {31'd0, enable};
      SR_ADDR:      rdata <=  {31'd0, irq};
      PERIOD_ADDR:  rdata <=  period;
      COUNTER_ADDR: rdata <=  counter;
      IRQ_CNT_ADDR: rdata <=  irq_cnt;
    endcase
  end
  else begin
    read_valid  <=  1'b0;
    rdata       <=  32'd0;
  end




endmodule //axi_timer