本帖最后由 circle900617 于 2015-9-28 12:23 编辑
开发环境:Quartus II 12 64bit,语言verilog hdl
主要功能:EPM570T144作为STM32的FSMC总线上的设备,为MCU提供接口扩展和一些简单的逻辑功能。
问题:
1. sensor模块中读取几个IO口数据的时候,若在判断中添加对地址的判断,则无**常读取数据。(传感器就是普通的光电对管,经过施密特)
由于我是第一次写CPLD代码,有可能是某些基础知识不了解,低级问题导致,请大家帮忙查出来予以指教!
2. 奇怪的问题:如果我将led_beeper模块中的代码添加了一些逻辑功能,甚至仅仅删除一小部分代码,就会导致sensor模块中的数据读出为全0。
具体添加的逻辑功能,在led_beeper -new.v中。
具体删除的小部分代码,在下文led_beeper.v中有标识描述,删除这一段,重新下载以后STM32读取sensor模块的数据就是全0了。
硬件没问题,其他功能完全正常,设备总线读写正常(USB、LCD),通过CPLD控制的电机等设备也运行正常。传感器的信号用示波器看过没有任何问题。
我现在是给公司开发一个项目,用到CPLD临时学的,由于时间紧迫也就没能从头到尾系统地学习,希望大家能不吝赐教!!
下面贴代码(只贴了几个模块,其他的在附件中,包括CPLD其他全部代码、STM32对应的FSMC设置代码等):
CPLD 顶层模块:
module xxxxxx
(
CLK48M,CPLD_INT,MCU_IO,
BUS_WR,BUS_RD,BUS_NE,BUS_A_L,BUS_A_H,BUS_D,
BUS_CS_CH375,BUS_CS_FLASH,BUS_CS_LCD,BUS_CS_RAM,
BEEP,LED,
SM1_MONI,SM1_EMO, SM2_MONI,SM2_EMO, SM3_MONI,SM3_EMO, SM4_MONI,SM4_EMO,
SM_ST, SM4_OE,SM4_FR,SM4_ATT, SM3_OE,SM3_FR,SM3_ATT, SM2_OE,SM2_FR,SM2_ATT, SM1_OE,SM1_FR,SM1_ATT,
DM2_EN,DM1_EN,DM1_IN,DM2_IN,
SEN_DOOR,SEN_PRESS,SEN_CARVE,SEN_TAPE_B,SEN_TAPE_F,SEN_CUT_R,SEN_CUT_L,SEN_RESERVE,
PH_PWR, PH_LATCH,PH_CLK, PH_DAT,PH_STR
);
/*********************************************************************************************************/
//接口定义
//晶振时钟
input CLK48M;
//发送至MCU的中断信号
output CPLD_INT;
//与MCU连接的预留IO口
output[3:0] MCU_IO;
//数据总线
input BUS_WR,BUS_RD;
input[4:1] BUS_NE;
input[19:0] BUS_A_L;
input[25:22] BUS_A_H;
inout[15:0] BUS_D;
output BUS_CS_CH375,BUS_CS_FLASH,BUS_CS_LCD;
output[2:1] BUS_CS_RAM;
//蜂鸣器
output BEEP;
//LED0--绿,LED1--红
output[1:0] LED;
//步进电机
input SM1_MONI,SM1_EMO, SM2_MONI,SM2_EMO, SM3_MONI,SM3_EMO, SM4_MONI,SM4_EMO;
output SM_ST, SM4_OE,SM4_FR,SM4_ATT, SM3_OE,SM3_FR,SM3_ATT, SM2_OE,SM2_FR,SM2_ATT, SM1_OE,SM1_FR,SM1_ATT;
//直流电机
output DM2_EN,DM1_EN;
output[2:1] DM1_IN,DM2_IN;
//传感器接口
input SEN_DOOR,SEN_PRESS,SEN_CARVE,SEN_TAPE_B,SEN_TAPE_F,SEN_CUT_R,SEN_CUT_L,SEN_RESERVE;
//打印头接口
output PH_PWR, PH_LATCH,PH_CLK;
output[4:1] PH_DAT,PH_STR;
/*********************************************************************************************************/
//双向总线数据口
reg[15:0] BUS_D_OUT_REG;
wire[15:0] BUS_D_OUT;
wire[15:0] BUS_D;
wire[15:0] BUS_D_IN;
assign BUS_D[15:0] = ((BUS_RD == 1'b0) && (BUS_CS_CPLD == 0))? BUS_D_OUT_REG : 16'bzzzz_zzzz_zzzz_zzzz;
assign BUS_D_IN = BUS_D;
always
begin
BUS_D_OUT_REG = BUS_D_OUT;
end
/*********************************************************************************************************/
//模拟上电复位
wire RST_n;
sim_rst mod_sim_rst(CLK48M,1'b1,RST_n);
/*********************************************************************************************************/
//时钟分频
wire clk_1k;
defparam Gen_ClkLed.divdWIDTH=15,Gen_ClkLed.divdFACTOR=24000;
gen_divd Gen_ClkLed(.reset(RST_n),.clkin(CLK48M),.clkout(clk_1k));
assign CPLD_INT = clk_1k;
/*********************************************************************************************************/
wire BUS_CS_CPLD;
logic_cs mod_logic_cs(BUS_NE,BUS_A_H, BUS_CS_CH375,BUS_CS_LCD,BUS_CS_FLASH,BUS_CS_RAM,BUS_CS_CPLD);
led_beeper mod_led_beeper(clk_1k,RST_n,BUS_CS_CPLD,BUS_WR,BUS_D_IN,BUS_A_L,LED,BEEP);
/*********************************************************************************************************/
//传感器读取
sensor mod_sensor(clk_1k,BUS_CS_CPLD,BUS_RD,BUS_D_OUT[7:0],BUS_A_L, MCU_IO[0],
SEN_DOOR,SEN_PRESS,SEN_CARVE,SEN_TAPE_B,SEN_TAPE_F,SEN_CUT_R,SEN_CUT_L,SEN_RESERVE);
//assign MCU_IO[0] = SEN_CUT_L;
/*********************************************************************************************************/
dc_motor mod_dc_motor(clk_1k,RST_n,BUS_CS_CPLD,BUS_WR,BUS_D_IN,BUS_A_L,DM1_EN,DM1_IN,DM2_EN,DM2_IN);
/*********************************************************************************************************/
step_motor mod_step_motor
(
clk_1k,RST_n,
BUS_CS_CPLD,BUS_WR,BUS_D,BUS_A_L,
SM_ST, SM4_OE,SM4_FR,SM4_ATT, SM3_OE,SM3_FR,SM3_ATT, SM2_OE,SM2_FR,SM2_ATT, SM1_OE,SM1_FR,SM1_ATT
);
/*********************************************************************************************************/
print_head mod_print_head
(
CLK48M,clk_1k,RST_n,
BUS_CS_CPLD,BUS_WR,BUS_D,BUS_A_L,
PH_PWR, PH_LATCH,PH_CLK, PH_DAT,PH_STR,
MCU_IO[1]
);
endmodule
CPLD sensor模块:
module sensor
(
inClk1K,
BUS_CS_CPLD,BUS_RD,BUS_D_OUT,BUS_A_L, MCU_IO,
SEN_DOOR,SEN_PRESS,SEN_CARVE,SEN_TAPE_B,SEN_TAPE_F,SEN_CUT_R,SEN_CUT_L,SEN_RESERVE
);
input inClk1K;
input BUS_CS_CPLD,BUS_RD;
input[19:0] BUS_A_L;
input SEN_DOOR,SEN_PRESS,SEN_CARVE,SEN_TAPE_B,SEN_TAPE_F,SEN_CUT_R,SEN_CUT_L,SEN_RESERVE;
output[7:0] BUS_D_OUT;
output MCU_IO;
reg[7:0] BUS_D_OUT;
reg MCU_IO;
parameter ADDR_SENSOR = 16'h2000;
//传感器有光(未挡住)
//parameter STATE_BRIGHT = 1'b1;
//传感无光(挡住)
//parameter STATE_DARK = 1'b0;
always@(negedge BUS_RD)
begin
if ((BUS_CS_CPLD == 0))// && (BUS_A_L[15:0] == ADDR_SENSOR))
begin
// 7 6 5 4 3 2 1 0
BUS_D_OUT[7:0] = {SEN_DOOR,SEN_PRESS,SEN_CARVE,SEN_TAPE_B,SEN_TAPE_F,SEN_CUT_R,SEN_CUT_L,SEN_RESERVE};
//出现读取数据为全0的情况时,将上句替换为 BUS_D_OUT[7:0] = 8'h23; 则可以正常读出数据,怀疑是总线上挂的设备太多了,驱动能力不足?
end
end
endmodule
CPLD led_beeper模块:
module led_beeper
(
clk_1k,rst_n,
BUS_CS_CPLD,BUS_WR,BUS_D,BUS_A_L,
outLed,outBeeper
);
/* 输入信号数据格式
[7:0] -- 蜂鸣器
[11:8] -- LED0
[15:12]-- LED1
*/
input clk_1k,rst_n;
input BUS_CS_CPLD, BUS_WR;
input[15:0] BUS_D;
input[19:0] BUS_A_L;
output[1:0] outLed;
output outBeeper;
//寄存器定义
reg[1:0] outLed;
reg outBeeper;
reg [3:0]rStateLed0,rStateLed1,rStateBeeper;
reg [9:1]rCntLed0,rCntLed1,rCntBeeper;
//定义使能信号数据
//注意:该地址为16位数据地址,即对应到MCU中的地址为0x1000<<1 (MCU中的地址为8位数据地址)
parameter ADDR_LED_BEEPER = 16'h1000;
parameter STATE_ON = 4'h1;
parameter STATE_OFF = 4'h2;
parameter STATE_1HZ = 4'hA;
parameter STATE_3HZ = 4'hB;
parameter STATE_10HZ = 4'hC;
parameter OUT_ON = 1'b0;
parameter OUT_OFF = 1'b1;
//总线数据接收
always @(negedge BUS_WR or negedge rst_n)
begin
if (rst_n == 1'b0)
begin
rStateLed1 = STATE_ON;
rStateLed0 = STATE_ON;
rStateBeeper = STATE_OFF;
end
else if ((BUS_CS_CPLD == 0) && (BUS_A_L == ADDR_LED_BEEPER))
begin
if (BUS_D[7:4] != 4'h0)
begin
rStateLed1 = BUS_D[7:4];
end
if (BUS_D[3:0] != 4'h0)
begin
rStateLed0 = BUS_D[3:0];
end
if (BUS_D[11:8] != 4'h0)
begin
rStateBeeper = BUS_D[11:8];
end
end
end
//LED0
always @(posedge clk_1k)
begin
case(rStateLed0)
STATE_ON:
begin
outLed[0] = OUT_ON;
rCntLed0 = 1'b0;
end
STATE_OFF:
begin
outLed[0] = OUT_OFF;
rCntLed0 = 1'b0;
end
STATE_1HZ:
begin
if (rCntLed0 >= 500)
begin
outLed[0] = ~outLed[0];
rCntLed0 = 1'b0;
end
rCntLed0 = rCntLed0 + 1'b1;
end
STATE_3HZ:
begin
if (rCntLed0 >= 166)
begin
outLed[0] = ~outLed[0];
rCntLed0 = 1'b0;
end
rCntLed0 = rCntLed0 + 1'b1;
end
STATE_10HZ:
begin
if (rCntLed0 >= 50)
begin
outLed[0] = ~outLed[0];
rCntLed0 = 1'b0;
end
rCntLed0 = rCntLed0 + 1'b1;
end
default: outLed[0] = OUT_ON;
endcase
end
//LED1
always @(posedge clk_1k)
begin
case(rStateLed1)
STATE_ON:
begin
outLed[1] = OUT_ON;
rCntLed1 = 1'b0;
end
STATE_OFF:
begin
outLed[1] = OUT_OFF;
rCntLed1 = 1'b0;
end
STATE_1HZ:
begin
if (rCntLed1 >= 500)
begin
outLed[1] = ~outLed[1];
rCntLed1 = 1'b0;
end
rCntLed1 = rCntLed1 + 1'b1;
end
STATE_3HZ:
begin
if (rCntLed1 >= 166)
begin
outLed[1] = ~outLed[1];
rCntLed1 = 1'b0;
end
rCntLed1 = rCntLed1 + 1'b1;
end
default: outLed[1] = OUT_ON;
endcase
end
//BEEPER
always @(posedge clk_1k)
begin
case(rStateBeeper)
STATE_ON:
begin
outBeeper = OUT_ON;
rCntBeeper = 1'b0;
end
STATE_OFF:
begin
outBeeper = OUT_OFF;
rCntBeeper = 1'b0;
end
STATE_1HZ:
begin
if (rCntBeeper >= 500)
begin
outBeeper = ~outBeeper;
rCntBeeper = 1'b0;
end
rCntBeeper = rCntBeeper + 1'b1;
end
STATE_3HZ:
begin
if (rCntBeeper >= 166)
begin
outBeeper = ~outBeeper;
rCntBeeper = 1'b0;
end
rCntBeeper = rCntBeeper + 1'b1;
end
/*STATE_10HZ:
begin
if (rCntBeeper >= 50)
begin
outBeeper = ~outBeeper;
rCntBeeper = 1'b0;
end
rCntBeeper = rCntBeeper + 1'b1;
end*/
//这段代码删除以后,会导致sensor模块的数据通过总线读出来是全0,再添加这段代码回来,就恢复了。。奇怪的问题
default: outBeeper = OUT_OFF;
endcase
end
|