mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-01-24 12:31:07 +02:00
166 lines
4.1 KiB
Verilog
Executable File
166 lines
4.1 KiB
Verilog
Executable File
`timescale 1ns / 1ps
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// Company:
|
|
// Engineer:
|
|
//
|
|
// Create Date: 11:52:20 10/07/2010
|
|
// Design Name:
|
|
// Module Name: ps2_tx
|
|
// Project Name: keyboard
|
|
// Target Devices:
|
|
// Tool versions:
|
|
// Description: transmisor de teclado ps2
|
|
//
|
|
// Dependencies:
|
|
//
|
|
// Revision:
|
|
// Revision 0.01 - File Created
|
|
// Additional Comments:
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
module ps2_tx
|
|
(
|
|
input wire clk, reset,
|
|
input wire we_ps2,
|
|
input wire [7:0] din,
|
|
inout wire ps2_data, ps2_clk,
|
|
output reg tx_idle, tx_done
|
|
);
|
|
|
|
// symbolic state declaration
|
|
localparam [2:0]
|
|
idle = 3'b000,
|
|
rts = 3'b001,
|
|
start = 3'b010,
|
|
data = 3'b011,
|
|
stop = 3'b100;
|
|
|
|
// signal declaration
|
|
reg [2:0] state_reg, state_next;
|
|
reg [7:0] filter_reg;
|
|
wire [7:0] filter_next;
|
|
reg f_ps2c_reg;
|
|
wire f_ps2c_next;
|
|
reg [3:0] n_reg, n_next;
|
|
reg [8:0] b_reg, b_next;
|
|
reg [12:0] c_reg, c_next;
|
|
wire par, fall_edge;
|
|
reg ps2c_out, ps2d_out;
|
|
reg tri_c, tri_d;
|
|
|
|
|
|
//=================================================
|
|
// falling-edge generation for ps2_clk
|
|
//=================================================
|
|
always @(posedge clk, posedge reset)
|
|
if (reset)
|
|
begin
|
|
filter_reg <= 0;
|
|
f_ps2c_reg <= 0;
|
|
end
|
|
else
|
|
begin
|
|
filter_reg <= filter_next;
|
|
f_ps2c_reg <= f_ps2c_next;
|
|
end
|
|
|
|
assign filter_next = {ps2_clk, filter_reg[7:1]};
|
|
assign f_ps2c_next = (filter_reg==8'b11111111) ? 1'b1 :
|
|
(filter_reg==8'b00000000) ? 1'b0 :
|
|
f_ps2c_reg;
|
|
assign fall_edge = f_ps2c_reg & ~f_ps2c_next;
|
|
|
|
//=================================================
|
|
// FSM
|
|
//=================================================
|
|
// state & data registers
|
|
always @(posedge clk, posedge reset)
|
|
if (reset)
|
|
begin
|
|
state_reg <= idle;
|
|
c_reg <= 0;
|
|
n_reg <= 0;
|
|
b_reg <= 0;
|
|
end
|
|
else
|
|
begin
|
|
state_reg <= state_next;
|
|
c_reg <= c_next;
|
|
n_reg <= n_next;
|
|
b_reg <= b_next;
|
|
end
|
|
|
|
// odd parity bit
|
|
assign par = ~(^din);
|
|
|
|
// FSM next-state logic
|
|
always @*
|
|
begin
|
|
state_next = state_reg;
|
|
c_next = c_reg;
|
|
n_next = n_reg;
|
|
b_next = b_reg;
|
|
tx_done = 1'b0;
|
|
ps2c_out = 1'bz;
|
|
ps2d_out = 1'bz;
|
|
tri_c = 1'b0;
|
|
tri_d = 1'b0;
|
|
tx_idle = 1'b0;
|
|
case (state_reg)
|
|
idle:
|
|
begin
|
|
tx_idle = 1'b1;
|
|
if (we_ps2)
|
|
begin
|
|
b_next = {par, din};
|
|
c_next = 13'h1fff; // 2^13-1
|
|
state_next = rts;
|
|
end
|
|
end
|
|
rts: // request to send
|
|
begin
|
|
ps2c_out = 1'b0;
|
|
tri_c = 1'b1;
|
|
c_next = c_reg - 1;
|
|
if (c_reg==0)
|
|
state_next = start;
|
|
end
|
|
start: // assert start bit
|
|
begin
|
|
ps2d_out = 1'b0;
|
|
tri_d = 1'b1;
|
|
if (fall_edge)
|
|
begin
|
|
n_next = 4'h8;
|
|
state_next = data;
|
|
end
|
|
end
|
|
data: // 8 data + 1 parity
|
|
begin
|
|
ps2d_out = (b_reg[0])? 1'bz : 1'b0;
|
|
tri_d = 1'b1;
|
|
if (fall_edge)
|
|
begin
|
|
b_next = {1'b0, b_reg[8:1]};
|
|
if (n_reg == 0)
|
|
state_next = stop;
|
|
else
|
|
n_next = n_reg - 1;
|
|
end
|
|
end
|
|
stop: // assume floating high for ps2_data
|
|
if (fall_edge)
|
|
begin
|
|
state_next = idle;
|
|
tx_done = 1'b1;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
// tri-state buffers
|
|
assign ps2_clk = (tri_c) ? ps2c_out : 1'bz;
|
|
assign ps2_data = (tri_d) ? ps2d_out : 1'bz;
|
|
|
|
endmodule
|