Root/PS2_INTERFACE/logic/ps2_tx.v

1`timescale 1ns / 1ps
2//////////////////////////////////////////////////////////////////////////////////
3// Company:
4// Engineer:
5//
6// Create Date: 11:52:20 10/07/2010
7// Design Name:
8// Module Name: ps2_tx
9// Project Name: keyboard
10// Target Devices:
11// Tool versions:
12// Description: transmisor de teclado ps2
13//
14// Dependencies:
15//
16// Revision:
17// Revision 0.01 - File Created
18// Additional Comments:
19//
20//////////////////////////////////////////////////////////////////////////////////
21
22module ps2_tx
23   (
24    input wire clk, reset,
25    input wire we_ps2,
26    input wire [7:0] din,
27    inout wire ps2_data, ps2_clk,
28    output reg tx_idle, tx_done
29   );
30
31   // symbolic state declaration
32   localparam [2:0]
33      idle = 3'b000,
34      rts = 3'b001,
35      start = 3'b010,
36      data = 3'b011,
37      stop = 3'b100;
38
39   // signal declaration
40   reg [2:0] state_reg, state_next;
41   reg [7:0] filter_reg;
42   wire [7:0] filter_next;
43   reg f_ps2c_reg;
44   wire f_ps2c_next;
45   reg [3:0] n_reg, n_next;
46   reg [8:0] b_reg, b_next;
47   reg [12:0] c_reg, c_next;
48   wire par, fall_edge;
49   reg ps2c_out, ps2d_out;
50   reg tri_c, tri_d;
51
52   
53   //=================================================
54   // falling-edge generation for ps2_clk
55   //=================================================
56   always @(posedge clk, posedge reset)
57   if (reset)
58      begin
59         filter_reg <= 0;
60         f_ps2c_reg <= 0;
61      end
62   else
63      begin
64         filter_reg <= filter_next;
65         f_ps2c_reg <= f_ps2c_next;
66      end
67
68   assign filter_next = {ps2_clk, filter_reg[7:1]};
69   assign f_ps2c_next = (filter_reg==8'b11111111) ? 1'b1 :
70                        (filter_reg==8'b00000000) ? 1'b0 :
71                         f_ps2c_reg;
72   assign fall_edge = f_ps2c_reg & ~f_ps2c_next;
73
74   //=================================================
75   // FSM
76   //=================================================
77   // state & data registers
78   always @(posedge clk, posedge reset)
79      if (reset)
80         begin
81            state_reg <= idle;
82            c_reg <= 0;
83            n_reg <= 0;
84            b_reg <= 0;
85         end
86      else
87         begin
88            state_reg <= state_next;
89            c_reg <= c_next;
90            n_reg <= n_next;
91            b_reg <= b_next;
92         end
93
94   // odd parity bit
95   assign par = ~(^din);
96
97   // FSM next-state logic
98   always @*
99   begin
100      state_next = state_reg;
101      c_next = c_reg;
102      n_next = n_reg;
103      b_next = b_reg;
104      tx_done = 1'b0;
105      ps2c_out = 1'bz;
106      ps2d_out = 1'bz;
107      tri_c = 1'b0;
108      tri_d = 1'b0;
109      tx_idle = 1'b0;
110      case (state_reg)
111         idle:
112            begin
113               tx_idle = 1'b1;
114               if (we_ps2)
115                  begin
116                     b_next = {par, din};
117                     c_next = 13'h1fff; // 2^13-1
118                     state_next = rts;
119                  end
120            end
121         rts: // request to send
122            begin
123               ps2c_out = 1'b0;
124               tri_c = 1'b1;
125               c_next = c_reg - 1;
126               if (c_reg==0)
127                  state_next = start;
128            end
129         start: // assert start bit
130            begin
131               ps2d_out = 1'b0;
132               tri_d = 1'b1;
133               if (fall_edge)
134                  begin
135                     n_next = 4'h8;
136                     state_next = data;
137                  end
138            end
139         data: // 8 data + 1 parity
140            begin
141               ps2d_out = (b_reg[0])? 1'bz : 1'b0;
142               tri_d = 1'b1;
143               if (fall_edge)
144                  begin
145                     b_next = {1'b0, b_reg[8:1]};
146                     if (n_reg == 0)
147                        state_next = stop;
148                     else
149                        n_next = n_reg - 1;
150                  end
151            end
152         stop: // assume floating high for ps2_data
153            if (fall_edge)
154               begin
155                  state_next = idle;
156                  tx_done = 1'b1;
157               end
158      endcase
159   end
160
161   // tri-state buffers
162   assign ps2_clk = (tri_c) ? ps2c_out : 1'bz;
163   assign ps2_data = (tri_d) ? ps2d_out : 1'bz;
164
165endmodule
166

Archive Download this file

Branches:
master



interactive