POC 实验报告
一、 实验目的
1. 了解 POC 工作原理,增加硬件设计中对时序的控制经验。
二、 实验原理
1、 打印机与 POC 连接
打印机准备好接收字符时会将 READY 信号拉高,POC 检测到高电平 READY 信
号后将打印字符放在 PD 端,然后发出打印脉冲信号 TR,打印机检测到高电平 TR
之后会将 READY 信号拉低。打印机一直保持 READY 信号低电平状态直到本次字符
打印完成,然后进入下一个字符打印周期。
2、 CPU 与 POC 连接
POC 内部数据寄存器 BR 用来缓存数据总线上送来的字符,状态寄存器 SR 有
两个功能,SR7 相当于 POC 的 ready 信号,SR0 代表 POC 的工作模式,1 为中断,
0 为查询。
若 POC 工作在查询工作模式,CPU 会不断查询 SR7 的值,若检测到 SR7 为高电平,
CPU 将打印字符送入数据寄存器 BR,当 BR 中含有打印字符之后 POC 清零 SR7 并
且然后发送打印脉冲信号 TR,打印完成之后 POC 再将 SR7 拉高。中断方式与此类
似,唯一的区别就是 SR0 为 1,当 SR7 为高时,POC 在 IRQ 端发出一个低电平的中
断请求,这个中断请求落后于 SR7 变化一个周期。
3、 完整过程
总的来说三者之间的时序是这样的,打印机空闲将 READY 信号拉高,POC 检
测到 READY 高电平,经过隔离时间(为了能实现连续打印,这里设置了一个字符间
的隔离时间为 3 个时钟周期)POC 将 SR7 拉高(若为中断模式,此后一个时钟周期
IRQ_N 被拉低),CPU 检测到 IRQ_N 低电平/ SR7 高电平立即将数据送入 BR,为了
表示方便,这里认为 BR 与打印机端口 PD 直接相连。此后 POC 将 SR7 拉低同时发
出脉冲 TR,打印机检测到 TR 后将 READY 信号拉低,这里认为打印需要 8 个时钟
周期,打印完成之后打印机继续将 READY 信号拉高进入下一个字符的打印周期。
三、 实验设计和说明
1、 PROCESSOR 模块
固定打印机的地址为 3‘b001,并且每次打印 CPU 送出的打印数据 DATA_OUT 是
从 8’b0000_0001 开始逐次加 1 的。DATA_IN 代表 POC 送来的状态寄存器 SR 的值。
模式选择信号 CHOOSE_MODEL 如果为 0 查询状态,那么 CPU 就会关注 SR7 的值,
如果为 1 中断状态,那么 CPU 就会关注 IRQ_N 的值,实际过程中查询与中断工作
方式大为不同,但在本例中实现两种工作方式的本质是一样的。
2、 POC 模块
这个模块采用状态机设计
初始状态 POC 如果检查到 READY 为 1 就进入握手状态,在握手状态内 POC 立
即将 SR7 拉高。如果 PD 上有数据,那么之后一个时钟周期将 SR7 拉低并且发出打
印脉冲信号 TR,如果 READY 为 0,PCO 将 TR 拉低并进入打印状态。为了保证打印
的连续性,在打印状态停留 8 个时钟周期之后打印机会给出一个 READY 信号,然
后 POC 进入初始状态循环工作。
3、 PRINTER 模块
与 POC 模块对应,PRINTER 模块同样采用三个状态
打印机复位之后直接进入初始状态,为保证仿真打印中的连续性,这里认为在
初始状态打印机直接给出 READY 信号并且进入握手状态,在握手过程中打印机检
测到脉冲 TR 则进入打印状态,在打印状态停留 8 个时钟周期之后回到初始状态。
四、 仿真内容
1、 模块连接说明
本实验在顶层模块中分别例化了三个子模块 PROCESSOR, POC, PRINTER,并引
出相应的信号来观测。
RTL 图如下:
2、 仿真波形说明
1. 查询工作模式
黄色线代表 POC 的工作方式,目前为查询工作状态。REG_PD 为打印的字
符,逐次加 1,如图在一个字符打印完成之后打印机给出 READY 信号,经过 3
个间隔时钟周期 SR7 被 POC 拉高并且 POC 开始接收 CPU 传来的字符。之后
POC 拉低 SR7 同时发出脉冲信号 REG_TR,打印机检测到脉冲 REG_TR 之后将
REG_READY 信号拉低,一直到本次字符打印完成之后再给出 REG_READY 信号
循环工作。
2. 中断工作模式
本实验设计过程中,中断工作方式与查询工作方式本质相同,如图所示
REG_IR_N 为低电平有效的中断请求信号,晚于 SR7 一个时钟周期出现。在此模
式中,REG_IR_N 的作用就相当于查询工作模式下的 SR7, 其余时序与查询工作
方式相同。
五、 附录
PROCESSOR 模块
module my_processor(
input clk,
input rst,
input irq_n,
input choose_model, //0 查询 1 中断
input [7:0]data_in,
output reg [7:0]data_out,
output reg [2:0]addr
);
reg [2:0]state;
reg [2:0]time_count;
reg [7:0] character_num_count;
reg flag;
localparam character_num=8'b1111_1111;
localparam load_character_period=3'd3;
localparam print_addr=3'b001;
localparam s_poll_initial=1;
localparam s_int_initial=2;
localparam s_process=3;
always@(posedge clk or posedge rst)
begin
if(rst==1'b1)
begin
data_out<=8'd0 ; //全零代表 cpu 不向 poc 送字符串,假设 cpu 送字符串会保持 3 个时钟周期
character_num_count<=8'd0;
flag<=1'b0;
end
flag<=1'b1;
end
flag<=1'b1;
end
end
//假设发送字符串恒定为 00000001 逐次加一
endcase
case(state)
s_poll_initial:
begin
s_int_initial:
begin
s_process:
begin
else
begin
if(data_out==character_num)
data_out<=8'd0;
else
begin
if(flag==1'b1)
begin
data_out<=data_out+8'd1;
flag<=1'b0;
end
addr<=print_addr;
end
end
end
always@(posedge clk or posedge rst)
begin
if(rst==1'b1)
s_poll_initial:
case(state)
begin
else
begin
s_process:
if(choose_model==1'b0)
state<=s_poll_initial;
end
else
if(choose_model==1'b1)
state<=s_int_initial;
begin
if (data_in[7]==1'b1)
end
begin
s_int_initial:
begin
if(irq_n==1'b0)
end
state<=s_process;
state<=s_process;
if(data_in[7]==1'b0)
begin
if(choose_model==1'b0)
end
else
state<=s_poll_initial;
if(choose_model==1'b1)
state<=s_int_initial;
endcase
end
end
end
endmodule
begin
irq_n<=1'b1;
end
begin
POC 模块
module my_poc(
input clk,
input rst,
input [2:0] addr,
input [7:0]data_in,
output reg [7:0]data_out,
output reg irq_n,
output reg [7:0]pd,
output reg tr,
input ready //这里 ready 为 1 相当于一个打印请求,并且空闲或忙状态均为 0
);
localparam s_poc_initial=1;
localparam s_poc_shakehands=2;
localparam s_poc_print=3;
reg [2:0]state;
reg [7:0]buff_register;
reg [7:0]state_register;
reg [1:0]temp_1;
reg [3:0]count;
always@(posedge clk or posedge rst)
begin
if(rst==1'b1)
else
end
always@(posedge clk or posedge rst)
begin
if(rst==1'b1)
state<=s_poc_initial;
else
begin
begin
if(pd!=8'd0&&ready==1'b1)
begin
begin
s_poc_shakehands:
begin
if(pd==8'd0&&ready==1'b1)
data_out[7]<=1'b1;
else
if ({data_out[7],data_out[7]}==2'b11)
irq_n<=1'b0;
else
irq_n<=1'b1;
end
case(state)
s_poc_initial:
if(ready==1'b1)
end
end
begin
state<=s_poc_shakehands;
data_out<=8'b00000001;
end
begin
temp_1<=2'd0;
data_out[7]<=1'b0;
tr<=1'b1;
end
else
begin
if(pd!=8'd0&&ready==1'b0)
begin
tr<=1'b0;
state<=s_poc_print;
end
end
end
if(ready==1'b1)
end
begin
state<=s_poc_initial;
end
pd<=8'd0;
count<=4'd0;
end
endcase
end
s_poc_print:
begin
end
end
//pd control
always@(posedge clk or posedge rst)
begin
if(rst==1'b1)
begin
else
begin
case(state)
s_poc_initial:pd<=8'd0;
s_poc_shakehands:pd<=buff_register;
s_poc_print:
begin
if(count==4'd8)
begin
count<=4'd0;
pd<=8'd0;
end
else
count<=count+4'd1;
end
endcase
end
end
always@(posedge clk or posedge rst)
begin
if(rst==1'b1)
begin
else
end
buff_register<=8'd0;
end
buff_register<=data_in;
endmodule